Repository: FEniCS/ufl (language: python)

Issue:
Move CI tests from pydocstyle to ruff
[Pydocstyle is deprecated](https://github.com/PyCQA/pydocstyle/pull/658)


Discussion / hints:

Fix patch:
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index cd8e21ed8..000000000
--- a/.flake8
+++ /dev/null
@@ -1,6 +0,0 @@
-[flake8]
-max-line-length = 120
-builtins = ufl
-exclude = doc/sphinx/source/conf.py
-per-file-ignores =
-    */__init__.py: F401
diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml
index e6f23ec0b..a3bdfc35a 100644
--- a/.github/workflows/pythonapp.yml
+++ b/.github/workflows/pythonapp.yml
@@ -28,14 +28,11 @@ jobs:
         uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
-      - name: Lint with flake8
+      - name: Lint with ruff
         run: |
-          python -m pip install flake8
-          flake8 --statistics .
-      - name: Check documentation style
-        run: |
-          python -m pip install pydocstyle[toml]
-          python -m pydocstyle ufl/
+          pip install ruff
+          ruff check .
+          ruff format --check .
       - name: Install UFL
         run: python -m pip install .[ci]
       - name: Run unit tests
diff --git a/demo/Constant.py b/demo/Constant.py
index 96acaf22c..09f0d515f 100644
--- a/demo/Constant.py
+++ b/demo/Constant.py
@@ -18,15 +18,27 @@
 # Modified by Martin Sandve Alnes, 2009
 #
 # Test form for scalar and vector constants.
-from ufl import (Coefficient, Constant, FunctionSpace, Mesh, TestFunction, TrialFunction, VectorConstant, dot, dx, grad,
-                 inner, triangle)
+from ufl import (
+    Coefficient,
+    Constant,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    VectorConstant,
+    dot,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 cell = triangle
 element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
diff --git a/demo/ConvectionJacobi.py b/demo/ConvectionJacobi.py
index 5f3b2da10..f058ca233 100644
--- a/demo/ConvectionJacobi.py
+++ b/demo/ConvectionJacobi.py
@@ -2,13 +2,23 @@
 # Author: Martin Sandve Alnes
 # Date: 2008-10-03
 #
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dot, dx, grad, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dot,
+    dx,
+    grad,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
-element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 u = TrialFunction(space)
diff --git a/demo/ConvectionJacobi2.py b/demo/ConvectionJacobi2.py
index c88108a17..bbe68b292 100644
--- a/demo/ConvectionJacobi2.py
+++ b/demo/ConvectionJacobi2.py
@@ -7,8 +7,8 @@
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
-element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 u = TrialFunction(space)
diff --git a/demo/ConvectionVector.py b/demo/ConvectionVector.py
index e83e60698..59b5e233d 100644
--- a/demo/ConvectionVector.py
+++ b/demo/ConvectionVector.py
@@ -7,8 +7,8 @@
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
-element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
diff --git a/demo/Elasticity.py b/demo/Elasticity.py
index 73513d5d6..324b2cefd 100644
--- a/demo/Elasticity.py
+++ b/demo/Elasticity.py
@@ -8,8 +8,8 @@
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
-element = FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+element = FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1)
+domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
diff --git a/demo/EnergyNorm.py b/demo/EnergyNorm.py
index 30f1ade40..de2de347c 100644
--- a/demo/EnergyNorm.py
+++ b/demo/EnergyNorm.py
@@ -23,7 +23,7 @@
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", tetrahedron, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = Coefficient(space)
diff --git a/demo/Equation.py b/demo/Equation.py
index 33625545b..f440f303d 100644
--- a/demo/Equation.py
+++ b/demo/Equation.py
@@ -34,13 +34,25 @@
 # the unknown u to the right-hand side, all terms may
 # be listed on one line and left- and right-hand sides
 # extracted by lhs() and rhs().
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dot, dx, grad, lhs, rhs, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dot,
+    dx,
+    grad,
+    lhs,
+    rhs,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 k = 0.1
diff --git a/demo/ExplicitConvection.py b/demo/ExplicitConvection.py
index c56d27376..e5086c1a9 100644
--- a/demo/ExplicitConvection.py
+++ b/demo/ExplicitConvection.py
@@ -2,13 +2,23 @@
 # Author: Martin Sandve Alnes
 # Date: 2008-10-03
 #
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dot, dx, grad, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dot,
+    dx,
+    grad,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
-element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 u = TrialFunction(space)
diff --git a/demo/FunctionOperators.py b/demo/FunctionOperators.py
index 075e7b8c1..4aeb4d621 100644
--- a/demo/FunctionOperators.py
+++ b/demo/FunctionOperators.py
@@ -16,13 +16,25 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Test form for operators on Coefficients.
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dot, dx, grad, max_value, sqrt, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dot,
+    dx,
+    grad,
+    max_value,
+    sqrt,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
@@ -30,4 +42,7 @@
 f = Coefficient(space)
 g = Coefficient(space)
 
-a = sqrt(1 / max_value(1 / f, -1 / f)) * sqrt(g) * dot(grad(v), grad(u)) * dx + v * u * sqrt(f * g) * g * dx
+a = (
+    sqrt(1 / max_value(1 / f, -1 / f)) * sqrt(g) * dot(grad(v), grad(u)) * dx
+    + v * u * sqrt(f * g) * g * dx
+)
diff --git a/demo/H1norm.py b/demo/H1norm.py
index 9da6b28e4..769607aff 100644
--- a/demo/H1norm.py
+++ b/demo/H1norm.py
@@ -8,7 +8,7 @@
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 f = Coefficient(space)
diff --git a/demo/HarmonicMap.py b/demo/HarmonicMap.py
index 8aa3ee5d2..1d53906c9 100644
--- a/demo/HarmonicMap.py
+++ b/demo/HarmonicMap.py
@@ -9,9 +9,9 @@
 from ufl.sobolevspace import H1
 
 cell = triangle
-X = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
+X = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
 Y = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 X_space = FunctionSpace(domain, X)
 Y_space = FunctionSpace(domain, Y)
 
diff --git a/demo/HarmonicMap2.py b/demo/HarmonicMap2.py
index dfc47c3b1..fc048868f 100644
--- a/demo/HarmonicMap2.py
+++ b/demo/HarmonicMap2.py
@@ -9,10 +9,10 @@
 from ufl.sobolevspace import H1
 
 cell = triangle
-X = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
+X = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
 Y = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
 M = MixedElement([X, Y])
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, M)
 
 u = Coefficient(space)
diff --git a/demo/Heat.py b/demo/Heat.py
index f695341b2..2a197b5d1 100644
--- a/demo/Heat.py
+++ b/demo/Heat.py
@@ -20,22 +20,33 @@
 # The bilinear form a(v, u1) and linear form L(v) for
 # one backward Euler step with the heat equation.
 #
-from ufl import Coefficient, Constant, FunctionSpace, Mesh, TestFunction, TrialFunction, dot, dx, grad, triangle
+from ufl import (
+    Coefficient,
+    Constant,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dot,
+    dx,
+    grad,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 cell = triangle
 element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)  # Test function
 u1 = TrialFunction(space)  # Value at t_n
-u0 = Coefficient(space)      # Value at t_n-1
-c = Coefficient(space)      # Heat conductivity
-f = Coefficient(space)      # Heat source
-k = Constant(domain)         # Time step
+u0 = Coefficient(space)  # Value at t_n-1
+c = Coefficient(space)  # Heat conductivity
+f = Coefficient(space)  # Heat source
+k = Constant(domain)  # Time step
 
 a = v * u1 * dx + k * c * dot(grad(v), grad(u1)) * dx
 L = v * u0 * dx + k * v * f * dx
diff --git a/demo/HornSchunck.py b/demo/HornSchunck.py
index d3ec43840..5238ed04e 100644
--- a/demo/HornSchunck.py
+++ b/demo/HornSchunck.py
@@ -3,7 +3,18 @@
 #  http://code.google.com/p/debiosee/wiki/DemosOptiocFlowHornSchunck
 # but not tested so this could contain errors!
 #
-from ufl import Coefficient, Constant, FunctionSpace, Mesh, derivative, dot, dx, grad, inner, triangle
+from ufl import (
+    Coefficient,
+    Constant,
+    FunctionSpace,
+    Mesh,
+    derivative,
+    dot,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
@@ -11,8 +22,8 @@
 # Finite element spaces for scalar and vector fields
 cell = triangle
 S = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-V = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+V = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 S_space = FunctionSpace(domain, S)
 V_space = FunctionSpace(domain, V)
 
@@ -29,8 +40,7 @@
 lamda = Constant(domain)
 
 # Coefficiental to minimize
-M = (dot(u, grad(I1)) + (I1 - I0))**2 * dx\
-    + lamda * inner(grad(u), grad(u)) * dx
+M = (dot(u, grad(I1)) + (I1 - I0)) ** 2 * dx + lamda * inner(grad(u), grad(u)) * dx
 
 # Derived linear system
 L = derivative(M, u)
diff --git a/demo/HyperElasticity.py b/demo/HyperElasticity.py
index cdfd58488..e4882d2b6 100644
--- a/demo/HyperElasticity.py
+++ b/demo/HyperElasticity.py
@@ -3,22 +3,45 @@
 # Date: 2008-12-22
 #
 
-from ufl import (Coefficient, Constant, FacetNormal, FunctionSpace, Identity, Mesh, SpatialCoordinate, TestFunction,
-                 TrialFunction, derivative, det, diff, dot, ds, dx, exp, grad, inner, inv, tetrahedron, tr, variable)
+from ufl import (
+    Coefficient,
+    Constant,
+    FacetNormal,
+    FunctionSpace,
+    Identity,
+    Mesh,
+    SpatialCoordinate,
+    TestFunction,
+    TrialFunction,
+    derivative,
+    det,
+    diff,
+    dot,
+    ds,
+    dx,
+    exp,
+    grad,
+    inner,
+    inv,
+    tetrahedron,
+    tr,
+    variable,
+)
 from ufl.finiteelement import FiniteElement
+
 # Modified by Garth N. Wells, 2009
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 # Cell and its properties
 cell = tetrahedron
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
 d = 3
 N = FacetNormal(domain)
 x = SpatialCoordinate(domain)
 
 # Elements
-u_element = FiniteElement("Lagrange", cell, 2, (3, ), identity_pullback, H1)
+u_element = FiniteElement("Lagrange", cell, 2, (3,), identity_pullback, H1)
 p_element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
 A_element = FiniteElement("Lagrange", cell, 1, (3, 3), identity_pullback, H1)
 
@@ -79,7 +102,9 @@
 Ef = A * E * A.T
 
 # Strain energy function W(Q(Ef))
-Q = c00 * Ef[0, 0]**2 + c11 * Ef[1, 1]**2 + c22 * Ef[2, 2]**2  # FIXME: insert some simple law here
+Q = (
+    c00 * Ef[0, 0] ** 2 + c11 * Ef[1, 1] ** 2 + c22 * Ef[2, 2] ** 2
+)  # FIXME: insert some simple law here
 W = (K / 2) * (exp(Q) - 1)  # + p stuff
 
 # First Piola-Kirchoff stress tensor
@@ -87,13 +112,15 @@
 
 # Acceleration term discretized with finite differences
 k = dt / rho
-acc = (u - 2 * up + upp)
+acc = u - 2 * up + upp
 
 # Residual equation # FIXME: Can contain errors, not tested!
-a_F = inner(acc, v) * dx \
-    + k * inner(P, grad(v)) * dx \
-    - k * dot(J * Finv * T, v) * ds(0) \
+a_F = (
+    inner(acc, v) * dx
+    + k * inner(P, grad(v)) * dx
+    - k * dot(J * Finv * T, v) * ds(0)
     - k * dot(J * Finv * p0 * N, v) * ds(1)
+)
 
 # Jacobi matrix of residual equation
 a_J = derivative(a_F, u, w)
diff --git a/demo/HyperElasticity1D.py b/demo/HyperElasticity1D.py
index 9dfcbed96..f2cd1ab52 100644
--- a/demo/HyperElasticity1D.py
+++ b/demo/HyperElasticity1D.py
@@ -9,14 +9,14 @@
 
 cell = interval
 element = FiniteElement("Lagrange", cell, 2, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (1, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (1,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 u = Coefficient(space)
 b = Constant(domain)
 K = Constant(domain)
 
-E = u.dx(0) + u.dx(0)**2 / 2
+E = u.dx(0) + u.dx(0) ** 2 / 2
 E = variable(E)
 Q = b * E**2
 psi = K * (exp(Q) - 1)
diff --git a/demo/L2norm.py b/demo/L2norm.py
index 31050a9df..cd492f647 100644
--- a/demo/L2norm.py
+++ b/demo/L2norm.py
@@ -8,7 +8,7 @@
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 f = Coefficient(space)
diff --git a/demo/Mass.py b/demo/Mass.py
index 4f083140b..eb20c5afb 100644
--- a/demo/Mass.py
+++ b/demo/Mass.py
@@ -26,7 +26,7 @@
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 u = TrialFunction(space)
diff --git a/demo/MassAD.py b/demo/MassAD.py
index ed36e8c2c..9f90b5eec 100644
--- a/demo/MassAD.py
+++ b/demo/MassAD.py
@@ -8,7 +8,7 @@
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 u = Coefficient(space)
diff --git a/demo/MixedElasticity.py b/demo/MixedElasticity.py
index 6fe1a96a3..466935be0 100644
--- a/demo/MixedElasticity.py
+++ b/demo/MixedElasticity.py
@@ -17,8 +17,20 @@
 #
 # First added:  2008-10-03
 # Last changed: 2011-07-22
-from ufl import (FunctionSpace, Mesh, TestFunctions, TrialFunctions, as_vector, div, dot, dx, inner, skew, tetrahedron,
-                 tr)
+from ufl import (
+    FunctionSpace,
+    Mesh,
+    TestFunctions,
+    TrialFunctions,
+    as_vector,
+    div,
+    dot,
+    dx,
+    inner,
+    skew,
+    tetrahedron,
+    tr,
+)
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import contravariant_piola, identity_pullback
 from ufl.sobolevspace import H1, L2, HDiv
@@ -36,19 +48,22 @@ def skw(tau):
 # Finite element exterior calculus syntax
 r = 1
 S = FiniteElement("vector BDM", cell, r, (3, 3), contravariant_piola, HDiv)
-V = FiniteElement("Discontinuous Lagrange", cell, r - 1, (3, ), identity_pullback, L2)
-Q = FiniteElement("Discontinuous Lagrange", cell, r - 1, (3, ), identity_pullback, L2)
+V = FiniteElement("Discontinuous Lagrange", cell, r - 1, (3,), identity_pullback, L2)
+Q = FiniteElement("Discontinuous Lagrange", cell, r - 1, (3,), identity_pullback, L2)
 
 W = MixedElement([S, V, Q])
 
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
 space = FunctionSpace(domain, W)
 
 (sigma, u, gamma) = TrialFunctions(space)
 (tau, v, eta) = TestFunctions(space)
 
 a = (
-    inner(sigma, tau) - tr(sigma) * tr(tau) + dot(
-        div(tau), u
-    ) - dot(div(sigma), v) + inner(skw(tau), gamma) + inner(skw(sigma), eta)
+    inner(sigma, tau)
+    - tr(sigma) * tr(tau)
+    + dot(div(tau), u)
+    - dot(div(sigma), v)
+    + inner(skw(tau), gamma)
+    + inner(skw(sigma), eta)
 ) * dx
diff --git a/demo/MixedPoisson.py b/demo/MixedPoisson.py
index 1580372a3..6e1c1730f 100644
--- a/demo/MixedPoisson.py
+++ b/demo/MixedPoisson.py
@@ -23,17 +23,27 @@
 # a mixed formulation of Poisson's equation with BDM
 # (Brezzi-Douglas-Marini) elements.
 #
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunctions, TrialFunctions, div, dot, dx, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunctions,
+    TrialFunctions,
+    div,
+    dot,
+    dx,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import contravariant_piola, identity_pullback
 from ufl.sobolevspace import H1, HDiv
 
 cell = triangle
-BDM1 = FiniteElement("Brezzi-Douglas-Marini", cell, 1, (2, ), contravariant_piola, HDiv)
+BDM1 = FiniteElement("Brezzi-Douglas-Marini", cell, 1, (2,), contravariant_piola, HDiv)
 DG0 = FiniteElement("Discontinuous Lagrange", cell, 0, (), identity_pullback, H1)
 
 element = MixedElement([BDM1, DG0])
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 dg0_space = FunctionSpace(domain, DG0)
 
diff --git a/demo/MixedPoisson2.py b/demo/MixedPoisson2.py
index 29268a309..fc9deb84d 100644
--- a/demo/MixedPoisson2.py
+++ b/demo/MixedPoisson2.py
@@ -3,16 +3,27 @@
 # Modified by: Martin Sandve Alnes
 # Date: 2009-02-12
 #
-from ufl import FacetNormal, FunctionSpace, Mesh, TestFunctions, TrialFunctions, div, dot, ds, dx, tetrahedron
+from ufl import (
+    FacetNormal,
+    FunctionSpace,
+    Mesh,
+    TestFunctions,
+    TrialFunctions,
+    div,
+    dot,
+    ds,
+    dx,
+    tetrahedron,
+)
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import contravariant_piola, identity_pullback
 from ufl.sobolevspace import H1, HDiv
 
 cell = tetrahedron
-RT = FiniteElement("Raviart-Thomas", cell, 1, (3, ), contravariant_piola, HDiv)
+RT = FiniteElement("Raviart-Thomas", cell, 1, (3,), contravariant_piola, HDiv)
 DG = FiniteElement("DG", cell, 0, (), identity_pullback, H1)
 MX = MixedElement([RT, DG])
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
 space = FunctionSpace(domain, MX)
 
 (u, p) = TrialFunctions(space)
diff --git a/demo/NavierStokes.py b/demo/NavierStokes.py
index 14dfa5f56..e1121d9c9 100644
--- a/demo/NavierStokes.py
+++ b/demo/NavierStokes.py
@@ -21,14 +21,24 @@
 #
 # The bilinear form for the nonlinear term in the
 # Navier-Stokes equations with fixed convective velocity.
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dot, dx, grad, tetrahedron
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dot,
+    dx,
+    grad,
+    tetrahedron,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 cell = tetrahedron
-element = FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
+element = FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1)
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
diff --git a/demo/NeumannProblem.py b/demo/NeumannProblem.py
index d384c4315..95f255933 100644
--- a/demo/NeumannProblem.py
+++ b/demo/NeumannProblem.py
@@ -17,13 +17,24 @@
 #
 # The bilinear form a(v, u) and linear form L(v) for
 # Poisson's equation with Neumann boundary conditions.
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, ds, dx, grad, inner, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    ds,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
-element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
diff --git a/demo/NonlinearPoisson.py b/demo/NonlinearPoisson.py
index 7604459b5..56ef5cb9a 100644
--- a/demo/NonlinearPoisson.py
+++ b/demo/NonlinearPoisson.py
@@ -1,10 +1,20 @@
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dot, dx, grad, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dot,
+    dx,
+    grad,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
@@ -12,6 +22,5 @@
 u0 = Coefficient(space)
 f = Coefficient(space)
 
-a = (1 + u0**2) * dot(grad(v), grad(u)) * dx \
-    + 2 * u0 * u * dot(grad(v), grad(u0)) * dx
+a = (1 + u0**2) * dot(grad(v), grad(u)) * dx + 2 * u0 * u * dot(grad(v), grad(u0)) * dx
 L = v * f * dx - (1 + u0**2) * dot(grad(v), grad(u0)) * dx
diff --git a/demo/Poisson.py b/demo/Poisson.py
index 779273391..bfae70f8b 100644
--- a/demo/Poisson.py
+++ b/demo/Poisson.py
@@ -21,13 +21,23 @@
 # Last changed: 2009-03-02
 #
 # The bilinear form a(v, u) and linear form L(v) for Poisson's equation.
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dx, grad, inner, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 u = TrialFunction(space)
diff --git a/demo/PoissonDG.py b/demo/PoissonDG.py
index fd289213a..bfe01c7a0 100644
--- a/demo/PoissonDG.py
+++ b/demo/PoissonDG.py
@@ -21,15 +21,31 @@
 # The bilinear form a(v, u) and linear form L(v) for
 # Poisson's equation in a discontinuous Galerkin (DG)
 # formulation.
-from ufl import (Coefficient, Constant, FacetNormal, FunctionSpace, Mesh, TestFunction, TrialFunction, avg, dot, dS, ds,
-                 dx, grad, inner, jump, triangle)
+from ufl import (
+    Coefficient,
+    Constant,
+    FacetNormal,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    avg,
+    dot,
+    dS,
+    ds,
+    dx,
+    grad,
+    inner,
+    jump,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1, L2
 
 cell = triangle
 element = FiniteElement("Discontinuous Lagrange", cell, 1, (), identity_pullback, L2)
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
@@ -44,12 +60,14 @@
 alpha = 4.0
 gamma = 8.0
 
-a = inner(grad(v), grad(u)) * dx \
-    - inner(avg(grad(v)), jump(u, n)) * dS \
-    - inner(jump(v, n), avg(grad(u))) * dS \
-    + alpha / h('+') * dot(jump(v, n), jump(u, n)) * dS \
-    - inner(grad(v), u * n) * ds \
-    - inner(v * n, grad(u)) * ds \
+a = (
+    inner(grad(v), grad(u)) * dx
+    - inner(avg(grad(v)), jump(u, n)) * dS
+    - inner(jump(v, n), avg(grad(u))) * dS
+    + alpha / h("+") * dot(jump(v, n), jump(u, n)) * dS
+    - inner(grad(v), u * n) * ds
+    - inner(v * n, grad(u)) * ds
     + gamma / h * v * u * ds
+)
 
 L = v * f * dx + v * gN * ds
diff --git a/demo/PoissonSystem.py b/demo/PoissonSystem.py
index 29967d025..9bcd06ad3 100644
--- a/demo/PoissonSystem.py
+++ b/demo/PoissonSystem.py
@@ -21,14 +21,25 @@
 #
 # The bilinear form a(v, u) and linear form L(v) for
 # Poisson's equation in system form (vector-valued).
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dot, dx, grad, inner, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dot,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 cell = triangle
-element = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+element = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
diff --git a/demo/PowAD.py b/demo/PowAD.py
index 106f1f799..dde304d99 100644
--- a/demo/PowAD.py
+++ b/demo/PowAD.py
@@ -2,13 +2,22 @@
 # Author: Martin Sandve Alnes
 # Date: 2008-10-03
 #
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, derivative, dx, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    derivative,
+    dx,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
diff --git a/demo/ProjectionSystem.py b/demo/ProjectionSystem.py
index 7548a0b22..5211abb84 100644
--- a/demo/ProjectionSystem.py
+++ b/demo/ProjectionSystem.py
@@ -4,7 +4,7 @@
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 v = TestFunction(space)
 u = TrialFunction(space)
diff --git a/demo/QuadratureElement.py b/demo/QuadratureElement.py
index 4e01cd31b..5ca50134f 100644
--- a/demo/QuadratureElement.py
+++ b/demo/QuadratureElement.py
@@ -20,17 +20,28 @@
 #
 # The linearised bilinear form a(u,v) and linear form L(v) for
 # the nonlinear equation - div (1+u) grad u = f (non-linear Poisson)
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dot, dx, grad, i, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dot,
+    dx,
+    grad,
+    i,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 2, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 QE = FiniteElement("Quadrature", triangle, 2, (), identity_pullback, H1)
-sig = FiniteElement("Quadrature", triangle, 1, (2, ), identity_pullback, H1)
+sig = FiniteElement("Quadrature", triangle, 1, (2,), identity_pullback, H1)
 
 qe_space = FunctionSpace(domain, QE)
 sig_space = FunctionSpace(domain, sig)
@@ -42,5 +53,8 @@
 sig0 = Coefficient(sig_space)
 f = Coefficient(space)
 
-a = v.dx(i) * C * u.dx(i) * dx(metadata={"quadrature_degree": 2}) + v.dx(i) * 2 * u0 * u * u0.dx(i) * dx
+a = (
+    v.dx(i) * C * u.dx(i) * dx(metadata={"quadrature_degree": 2})
+    + v.dx(i) * 2 * u0 * u * u0.dx(i) * dx
+)
 L = v * f * dx - dot(grad(v), sig0) * dx(metadata={"quadrature_degree": 1})
diff --git a/demo/Stiffness.py b/demo/Stiffness.py
index 32bf00a54..f96fa6e32 100644
--- a/demo/Stiffness.py
+++ b/demo/Stiffness.py
@@ -8,7 +8,7 @@
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 u = TrialFunction(space)
diff --git a/demo/StiffnessAD.py b/demo/StiffnessAD.py
index 59a8bcba4..c95b94684 100644
--- a/demo/StiffnessAD.py
+++ b/demo/StiffnessAD.py
@@ -2,13 +2,24 @@
 # Author: Martin Sandve Alnes
 # Date: 2008-10-30
 #
-from ufl import Coefficient, FunctionSpace, Mesh, action, adjoint, derivative, dx, grad, inner, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    action,
+    adjoint,
+    derivative,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 w = Coefficient(space)
diff --git a/demo/Stokes.py b/demo/Stokes.py
index b4d240ffd..4a2c185ac 100644
--- a/demo/Stokes.py
+++ b/demo/Stokes.py
@@ -20,16 +20,28 @@
 #
 # The bilinear form a(v, u) and Linear form L(v) for the Stokes
 # equations using a mixed formulation (Taylor-Hood elements).
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunctions, TrialFunctions, div, dot, dx, grad, inner, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunctions,
+    TrialFunctions,
+    div,
+    dot,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 cell = triangle
-P2 = FiniteElement("Lagrange", cell, 2, (2, ), identity_pullback, H1)
+P2 = FiniteElement("Lagrange", cell, 2, (2,), identity_pullback, H1)
 P1 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
 TH = MixedElement([P2, P1])
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, TH)
 p2_space = FunctionSpace(domain, P2)
 
diff --git a/demo/StokesEquation.py b/demo/StokesEquation.py
index 949551846..667ca729b 100644
--- a/demo/StokesEquation.py
+++ b/demo/StokesEquation.py
@@ -19,17 +19,30 @@
 # equations using a mixed formulation (Taylor-Hood elements) in
 # combination with the lhs() and rhs() operators to extract the
 # bilinear and linear forms from an expression F = 0.
-from ufl import (Coefficient, FunctionSpace, Mesh, TestFunctions, TrialFunctions, div, dot, dx, grad, inner, lhs, rhs,
-                 triangle)
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunctions,
+    TrialFunctions,
+    div,
+    dot,
+    dx,
+    grad,
+    inner,
+    lhs,
+    rhs,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 cell = triangle
-P2 = FiniteElement("Lagrange", cell, 2, (2, ), identity_pullback, H1)
+P2 = FiniteElement("Lagrange", cell, 2, (2,), identity_pullback, H1)
 P1 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
 TH = MixedElement([P2, P1])
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 space = FunctionSpace(domain, TH)
 p2_space = FunctionSpace(domain, P2)
 
diff --git a/demo/SubDomain.py b/demo/SubDomain.py
index 4205a7790..39dca0653 100644
--- a/demo/SubDomain.py
+++ b/demo/SubDomain.py
@@ -23,7 +23,7 @@
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", tetrahedron, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
diff --git a/demo/SubDomains.py b/demo/SubDomains.py
index 55e9ddbe5..f4d76da7a 100644
--- a/demo/SubDomains.py
+++ b/demo/SubDomains.py
@@ -17,17 +17,23 @@
 #
 # This simple example illustrates how forms can be defined on different sub domains.
 # It is supported for all three integral types.
-from ufl import FunctionSpace, Mesh, TestFunction, TrialFunction, ds, dS, dx, tetrahedron
+from ufl import FunctionSpace, Mesh, TestFunction, TrialFunction, dS, ds, dx, tetrahedron
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
 element = FiniteElement("Lagrange", tetrahedron, 1, (), identity_pullback, H1)
-domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
 space = FunctionSpace(domain, element)
 
 v = TestFunction(space)
 u = TrialFunction(space)
 
-a = v * u * dx(0) + 10.0 * v * u * dx(1) + v * u * ds(0) + 2.0 * v * u * ds(1)\
-    + v('+') * u('+') * dS(0) + 4.3 * v('+') * u('+') * dS(1)
+a = (
+    v * u * dx(0)
+    + 10.0 * v * u * dx(1)
+    + v * u * ds(0)
+    + 2.0 * v * u * ds(1)
+    + v("+") * u("+") * dS(0)
+    + 4.3 * v("+") * u("+") * dS(1)
+)
diff --git a/demo/TensorWeightedPoisson.py b/demo/TensorWeightedPoisson.py
index 6ebc8e3c1..a46516dd4 100644
--- a/demo/TensorWeightedPoisson.py
+++ b/demo/TensorWeightedPoisson.py
@@ -17,14 +17,24 @@
 #
 # The bilinear form a(v, u) and linear form L(v) for
 # tensor-weighted Poisson's equation.
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, dx, grad, inner, triangle
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1, L2
 
 P1 = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
 P0 = FiniteElement("Discontinuous Lagrange", triangle, 0, (2, 2), identity_pullback, L2)
-domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 p1_space = FunctionSpace(domain, P1)
 p0_space = FunctionSpace(domain, P0)
 
diff --git a/demo/VectorLaplaceGradCurl.py b/demo/VectorLaplaceGradCurl.py
index f5d9b863f..ca08db9ac 100644
--- a/demo/VectorLaplaceGradCurl.py
+++ b/demo/VectorLaplaceGradCurl.py
@@ -18,7 +18,18 @@
 # The bilinear form a(v, u) and linear form L(v) for the Hodge Laplace
 # problem using 0- and 1-forms. Intended to demonstrate use of Nedelec
 # elements.
-from ufl import Coefficient, FunctionSpace, Mesh, TestFunctions, TrialFunctions, curl, dx, grad, inner, tetrahedron
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunctions,
+    TrialFunctions,
+    curl,
+    dx,
+    grad,
+    inner,
+    tetrahedron,
+)
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import covariant_piola, identity_pullback
 from ufl.sobolevspace import H1, HCurl
@@ -29,7 +40,9 @@ def HodgeLaplaceGradCurl(space, fspace):
     sigma, u = TrialFunctions(space)
     f = Coefficient(fspace)
 
-    a = (inner(tau, sigma) - inner(grad(tau), u) + inner(v, grad(sigma)) + inner(curl(v), curl(u))) * dx
+    a = (
+        inner(tau, sigma) - inner(grad(tau), u) + inner(v, grad(sigma)) + inner(curl(v), curl(u))
+    ) * dx
     L = inner(v, f) * dx
 
     return a, L
@@ -39,11 +52,11 @@ def HodgeLaplaceGradCurl(space, fspace):
 order = 1
 
 GRAD = FiniteElement("Lagrange", cell, order, (), identity_pullback, H1)
-CURL = FiniteElement("N1curl", cell, order, (3, ), covariant_piola, HCurl)
+CURL = FiniteElement("N1curl", cell, order, (3,), covariant_piola, HCurl)
 
-VectorLagrange = FiniteElement("Lagrange", cell, order + 1, (3, ), identity_pullback, H1)
+VectorLagrange = FiniteElement("Lagrange", cell, order + 1, (3,), identity_pullback, H1)
 
-domain = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
+domain = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
 space = FunctionSpace(domain, MixedElement([GRAD, CURL]))
 fspace = FunctionSpace(domain, VectorLagrange)
 
diff --git a/demo/_TensorProductElement.py b/demo/_TensorProductElement.py
index 9e6fb6ef0..c32b1fd09 100644
--- a/demo/_TensorProductElement.py
+++ b/demo/_TensorProductElement.py
@@ -17,8 +17,17 @@
 #
 # First added:  2012-08-16
 # Last changed: 2012-08-16
-from ufl import (FunctionSpace, Mesh, TensorProductElement, TestFunction, TrialFunction, dx, interval, tetrahedron,
-                 triangle)
+from ufl import (
+    FunctionSpace,
+    Mesh,
+    TensorProductElement,
+    TestFunction,
+    TrialFunction,
+    dx,
+    interval,
+    tetrahedron,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1, L2
diff --git a/doc/sphinx/source/conf.py b/doc/sphinx/source/conf.py
index 60a0af8ee..5ad9345db 100644
--- a/doc/sphinx/source/conf.py
+++ b/doc/sphinx/source/conf.py
@@ -18,43 +18,43 @@
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+# sys.path.insert(0, os.path.abspath('.'))
 
 # -- General configuration ------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
 
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 extensions = [
-    'sphinx.ext.autodoc',
-    'sphinx.ext.doctest',
-    'sphinx.ext.coverage',
-    'sphinx.ext.mathjax',
-    'sphinx.ext.viewcode',
+    "sphinx.ext.autodoc",
+    "sphinx.ext.doctest",
+    "sphinx.ext.coverage",
+    "sphinx.ext.mathjax",
+    "sphinx.ext.viewcode",
 ]
 
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
 
 # The suffix(es) of source filenames.
 # You can specify multiple suffix as a list of string:
 # source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
+source_suffix = ".rst"
 
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
 
 # The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
 # General information about the project.
-project = u'Unified Form Language (UFL)'
+project = "Unified Form Language (UFL)"
 this_year = datetime.date.today().year
-copyright = u'%s, FEniCS Project' % this_year
-author = u'FEniCS Project'
+copyright = "%s, FEniCS Project" % this_year
+author = "FEniCS Project"
 
 version = importlib.metadata.version("fenics-ufl")
 release = version
@@ -68,9 +68,9 @@
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
-#today = ''
+# today = ''
 # Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
@@ -78,27 +78,27 @@
 
 # The reST default role (used for this markup: `text`) to use for all
 # documents.
-#default_role = None
+# default_role = None
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
-#show_authors = False
+# show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
 
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
 
 # If true, keep warnings as "system message" paragraphs in the built documents.
-#keep_warnings = False
+# keep_warnings = False
 
 # If true, `todo` and `todoList` produce output, else they produce nothing.
 todo_include_todos = False
@@ -108,31 +108,31 @@
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-#html_theme = 'alabaster'
+# html_theme = 'alabaster'
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
-#html_theme_options = {}
+# html_theme_options = {}
 
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
-#html_title = None
+# html_title = None
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
 
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
-#html_logo = None
+# html_logo = None
 
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
-#html_favicon = None
+# html_favicon = None
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
@@ -142,109 +142,111 @@
 # Add any extra paths that contain custom files (such as robots.txt or
 # .htaccess) here, relative to this directory. These files are copied
 # directly to the root of the documentation.
-#html_extra_path = []
+# html_extra_path = []
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
 
 # If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
 
 # If false, no index is generated.
-#html_use_index = True
+# html_use_index = True
 
 # If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
 
 # If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
 
 # Language to be used for generating the HTML full-text search index.
 # Sphinx supports the following languages:
 #   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
 #   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
-#html_search_language = 'en'
+# html_search_language = 'en'
 
 # A dictionary with options for the search language support, empty by default.
 # Now only 'ja' uses this config value
-#html_search_options = {'type': 'default'}
+# html_search_options = {'type': 'default'}
 
 # The name of a javascript file (relative to the configuration directory) that
 # implements a search results scorer. If empty, the default will be used.
-#html_search_scorer = 'scorer.js'
+# html_search_scorer = 'scorer.js'
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'UnifiedFormLanguageUFLdoc'
+htmlhelp_basename = "UnifiedFormLanguageUFLdoc"
 
 # -- Options for LaTeX output ---------------------------------------------
 
 latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-
-# Latex figure (float) alignment
-#'figure_align': 'htbp',
+    # The paper size ('letterpaper' or 'a4paper').
+    #'papersize': 'letterpaper',
+    # The font size ('10pt', '11pt' or '12pt').
+    #'pointsize': '10pt',
+    # Additional stuff for the LaTeX preamble.
+    #'preamble': '',
+    # Latex figure (float) alignment
+    #'figure_align': 'htbp',
 }
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-  (master_doc, 'UnifiedFormLanguageUFL.tex', u'Unified Form Language (UFL) Documentation',
-   u'FEniCS Project', 'manual'),
+    (
+        master_doc,
+        "UnifiedFormLanguageUFL.tex",
+        "Unified Form Language (UFL) Documentation",
+        "FEniCS Project",
+        "manual",
+    ),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
-#latex_logo = None
+# latex_logo = None
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
 
 # If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
 
 # If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
 
 # Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
 
 # If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
 
 
 # -- Options for manual page output ---------------------------------------
@@ -252,12 +254,11 @@
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    (master_doc, 'unifiedformlanguageufl', u'Unified Form Language (UFL) Documentation',
-     [author], 1)
+    (master_doc, "unifiedformlanguageufl", "Unified Form Language (UFL) Documentation", [author], 1)
 ]
 
 # If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
 
 
 # -- Options for Texinfo output -------------------------------------------
@@ -266,19 +267,25 @@
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-  (master_doc, 'UnifiedFormLanguageUFL', u'Unified Form Language (UFL) Documentation',
-   author, 'UnifiedFormLanguageUFL', 'One line description of project.',
-   'Miscellaneous'),
+    (
+        master_doc,
+        "UnifiedFormLanguageUFL",
+        "Unified Form Language (UFL) Documentation",
+        author,
+        "UnifiedFormLanguageUFL",
+        "One line description of project.",
+        "Miscellaneous",
+    ),
 ]
 
 # Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
 
 # If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
 
 # If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
+# texinfo_no_detailmenu = False
diff --git a/pyproject.toml b/pyproject.toml
index 468cd0a10..8fb43220d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,11 +5,14 @@ build-backend = "setuptools.build_meta"
 [project]
 name = "fenics-ufl"
 version = "2023.3.0.dev0"
-authors = [{name="UFL contributors"}]
-maintainers = [{email="fenics-steering-council@googlegroups.com"}, {name="FEniCS Steering Council"}]
+authors = [{ name = "UFL contributors" }]
+maintainers = [
+    { email = "fenics-steering-council@googlegroups.com" },
+    { name = "FEniCS Steering Council" },
+]
 description = "Unified Form Language"
 readme = "README.rst"
-license = {file = "COPYING.lesser"}
+license = { file = "COPYING.lesser" }
 requires-python = ">=3.8.0"
 dependencies = ["numpy"]
 
@@ -21,7 +24,7 @@ issues = "https://github.com/FEniCS/ufl/issues"
 funding = "https://numfocus.org/donate"
 
 [project.optional-dependencies]
-lint = ["flake8", "pydocstyle[toml]"]
+lint = ["ruff"]
 docs = ["sphinx", "sphinx_rtd_theme"]
 test = ["pytest"]
 ci = [
@@ -44,8 +47,38 @@ packages = [
     "ufl.utils",
 ]
 
-[tool.pydocstyle]
-convention = "google"
+[tool.ruff]
+line-length = 100
+indent-width = 4
 
-[tool.isort]
-line_length = 120
+[tool.ruff.format]
+docstring-code-format = true
+
+[tool.ruff.lint]
+select = [
+    # "N", # pep8-naming
+    "E", # pycodestyle
+    "W", # pycodestyle
+    "D",   # pydocstyle
+    "F",   # pyflakes
+    "I",   # isort
+    "RUF", # Ruff-specific rules
+    # "UP",  # pyupgrade
+    "ICN", # flake8-import-conventions
+    "NPY", # numpy-specific rules
+    "FLY", # use f-string not static joins
+    "LOG", # https://docs.astral.sh/ruff/rules/#flake8-logging-log
+    # "ISC", # https://docs.astral.sh/ruff/rules/#flake8-implicit-str-concat-isc
+    # "B", # https://docs.astral.sh/ruff/rules/#flake8-bugbear-b
+    # "A", # https://docs.astral.sh/ruff/rules/#flake8-builtins-a
+]
+ignore = ["RUF005", "RUF012"]
+allowed-confusables = ["𝐚", "𝐀", "∕", "γ", "⨯", "∨"]
+
+[tool.ruff.lint.per-file-ignores]
+"demo/*" = ["D"]
+"doc/*" = ["D"]
+"test/*" = ["D"]
+
+[tool.ruff.lint.pydocstyle]
+convention = "google"
diff --git a/ufl/__init__.py b/ufl/__init__.py
index 59c19e61f..e2656a76b 100644
--- a/ufl/__init__.py
+++ b/ufl/__init__.py
@@ -245,10 +245,17 @@
 
 from math import e, pi
 
-import ufl.exproperators as __exproperators
 from ufl.action import Action
 from ufl.adjoint import Adjoint
-from ufl.argument import Argument, Arguments, Coargument, TestFunction, TestFunctions, TrialFunction, TrialFunctions
+from ufl.argument import (
+    Argument,
+    Arguments,
+    Coargument,
+    TestFunction,
+    TestFunctions,
+    TrialFunction,
+    TrialFunctions,
+)
 from ufl.cell import AbstractCell, Cell, TensorProductCell, as_cell
 from ufl.coefficient import Coefficient, Coefficients, Cofunction
 from ufl.constant import Constant, TensorConstant, VectorConstant
@@ -259,84 +266,372 @@
 from ufl.domain import AbstractDomain, Mesh, MeshView
 from ufl.finiteelement import AbstractFiniteElement
 from ufl.form import BaseForm, Form, FormSum, ZeroBaseForm
-from ufl.formoperators import (action, adjoint, derivative, energy_norm, extract_blocks, functional, lhs, replace, rhs,
-                               sensitivity_rhs, system)
+from ufl.formoperators import (
+    action,
+    adjoint,
+    derivative,
+    energy_norm,
+    extract_blocks,
+    functional,
+    lhs,
+    replace,
+    rhs,
+    sensitivity_rhs,
+    system,
+)
 from ufl.functionspace import FunctionSpace, MixedFunctionSpace
-from ufl.geometry import (CellDiameter, CellNormal, CellVolume, Circumradius, FacetArea, FacetNormal, Jacobian,
-                          JacobianDeterminant, JacobianInverse, MaxCellEdgeLength, MaxFacetEdgeLength,
-                          MinCellEdgeLength, MinFacetEdgeLength, SpatialCoordinate)
+from ufl.geometry import (
+    CellDiameter,
+    CellNormal,
+    CellVolume,
+    Circumradius,
+    FacetArea,
+    FacetNormal,
+    Jacobian,
+    JacobianDeterminant,
+    JacobianInverse,
+    MaxCellEdgeLength,
+    MaxFacetEdgeLength,
+    MinCellEdgeLength,
+    MinFacetEdgeLength,
+    SpatialCoordinate,
+)
 from ufl.integral import Integral
 from ufl.matrix import Matrix
 from ufl.measure import Measure, custom_integral_types, integral_types, register_integral_type
-from ufl.objects import (dc, dC, dI, dO, dP, ds, dS, ds_b, dS_h, ds_t, ds_tb, ds_v, dS_v, dx, dX, facet, hexahedron, i,
-                         interval, j, k, l, p, pentatope, prism, pyramid, q, quadrilateral, r, s, tesseract,
-                         tetrahedron, triangle, vertex)
-from ufl.operators import (And, Dn, Dx, Not, Or, acos, asin, atan, atan2, avg, bessel_I, bessel_J, bessel_K, bessel_Y,
-                           cell_avg, cofac, conditional, conj, cos, cosh, cross, curl, det, dev, diag, diag_vector,
-                           diff, div, dot, elem_div, elem_mult, elem_op, elem_pow, eq, erf, exp, exterior_derivative,
-                           facet_avg, ge, grad, gt, imag, inner, inv, jump, le, ln, lt, max_value, min_value, nabla_div,
-                           nabla_grad, ne, outer, perp, rank, real, rot, shape, sign, sin, sinh, skew, sqrt, sym, tan,
-                           tanh, tr, transpose, variable)
-from ufl.pullback import (AbstractPullback, MixedPullback, SymmetricPullback, contravariant_piola, covariant_piola,
-                          double_contravariant_piola, double_covariant_piola, identity_pullback, l2_piola)
+from ufl.objects import (
+    dC,
+    dc,
+    dI,
+    dO,
+    dP,
+    dS,
+    ds,
+    ds_b,
+    dS_h,
+    ds_t,
+    ds_tb,
+    dS_v,
+    ds_v,
+    dX,
+    dx,
+    facet,
+    hexahedron,
+    i,
+    interval,
+    j,
+    k,
+    l,
+    p,
+    pentatope,
+    prism,
+    pyramid,
+    q,
+    quadrilateral,
+    r,
+    s,
+    tesseract,
+    tetrahedron,
+    triangle,
+    vertex,
+)
+from ufl.operators import (
+    And,
+    Dn,
+    Dx,
+    Not,
+    Or,
+    acos,
+    asin,
+    atan,
+    atan2,
+    avg,
+    bessel_I,
+    bessel_J,
+    bessel_K,
+    bessel_Y,
+    cell_avg,
+    cofac,
+    conditional,
+    conj,
+    cos,
+    cosh,
+    cross,
+    curl,
+    det,
+    dev,
+    diag,
+    diag_vector,
+    diff,
+    div,
+    dot,
+    elem_div,
+    elem_mult,
+    elem_op,
+    elem_pow,
+    eq,
+    erf,
+    exp,
+    exterior_derivative,
+    facet_avg,
+    ge,
+    grad,
+    gt,
+    imag,
+    inner,
+    inv,
+    jump,
+    le,
+    ln,
+    lt,
+    max_value,
+    min_value,
+    nabla_div,
+    nabla_grad,
+    ne,
+    outer,
+    perp,
+    rank,
+    real,
+    rot,
+    shape,
+    sign,
+    sin,
+    sinh,
+    skew,
+    sqrt,
+    sym,
+    tan,
+    tanh,
+    tr,
+    transpose,
+    variable,
+)
+from ufl.pullback import (
+    AbstractPullback,
+    MixedPullback,
+    SymmetricPullback,
+    contravariant_piola,
+    covariant_piola,
+    double_contravariant_piola,
+    double_covariant_piola,
+    identity_pullback,
+    l2_piola,
+)
 from ufl.sobolevspace import H1, H2, L2, HCurl, HDiv, HDivDiv, HEin, HInf
 from ufl.split_functions import split
-from ufl.tensors import as_matrix, as_tensor, as_vector, unit_matrices, unit_matrix, unit_vector, unit_vectors
+from ufl.tensors import (
+    as_matrix,
+    as_tensor,
+    as_vector,
+    unit_matrices,
+    unit_matrix,
+    unit_vector,
+    unit_vectors,
+)
 from ufl.utils.sequences import product
 
 __all__ = [
-    'product',
-    'as_cell', 'AbstractCell', 'Cell', 'TensorProductCell',
-    'AbstractDomain', 'Mesh', 'MeshView',
-    'L2', 'H1', 'H2', 'HCurl', 'HDiv', 'HInf', 'HEin', 'HDivDiv',
-    'identity_pullback', 'l2_piola', 'contravariant_piola', 'covariant_piola',
-    'double_contravariant_piola', 'double_covariant_piola',
-    'l2_piola', 'MixedPullback', 'SymmetricPullback', 'AbstractPullback',
-    'SpatialCoordinate',
-    'CellVolume', 'CellDiameter', 'Circumradius',
-    'MinCellEdgeLength', 'MaxCellEdgeLength',
-    'FacetArea', 'MinFacetEdgeLength', 'MaxFacetEdgeLength',
-    'FacetNormal', 'CellNormal',
-    'Jacobian', 'JacobianDeterminant', 'JacobianInverse',
-    'AbstractFiniteElement',
-    'FunctionSpace', 'MixedFunctionSpace',
-    'Argument', 'Coargument', 'TestFunction', 'TrialFunction',
-    'Arguments', 'TestFunctions', 'TrialFunctions',
-    'Coefficient', 'Cofunction', 'Coefficients',
-    'Matrix', 'Adjoint', 'Action',
-    'Interpolate', 'interpolate',
-    'ExternalOperator',
-    'Constant', 'VectorConstant', 'TensorConstant',
-    'split',
-    'PermutationSymbol', 'Identity', 'zero', 'as_ufl',
-    'Index', 'indices',
-    'as_tensor', 'as_vector', 'as_matrix',
-    'unit_vector', 'unit_vectors', 'unit_matrix', 'unit_matrices',
-    'rank', 'shape', 'conj', 'real', 'imag',
-    'outer', 'inner', 'dot', 'cross', 'perp',
-    'det', 'inv', 'cofac',
-    'transpose', 'tr', 'diag', 'diag_vector', 'dev', 'skew', 'sym',
-    'sqrt', 'exp', 'ln', 'erf',
-    'cos', 'sin', 'tan',
-    'acos', 'asin', 'atan', 'atan2',
-    'cosh', 'sinh', 'tanh',
-    'bessel_J', 'bessel_Y', 'bessel_I', 'bessel_K',
-    'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not',
-    'conditional', 'sign', 'max_value', 'min_value',
-    'variable', 'diff',
-    'Dx', 'grad', 'div', 'curl', 'rot', 'nabla_grad', 'nabla_div', 'Dn', 'exterior_derivative',
-    'jump', 'avg', 'cell_avg', 'facet_avg',
-    'elem_mult', 'elem_div', 'elem_pow', 'elem_op',
-    'Form', 'BaseForm', 'FormSum', 'ZeroBaseForm',
-    'Integral', 'Measure', 'register_integral_type', 'integral_types', 'custom_integral_types',
-    'replace', 'derivative', 'action', 'energy_norm', 'rhs', 'lhs', 'extract_blocks',
-    'system', 'functional', 'adjoint', 'sensitivity_rhs',
-    'dx', 'ds', 'dS', 'dP',
-    'dc', 'dC', 'dO', 'dI', 'dX',
-    'ds_b', 'ds_t', 'ds_tb', 'ds_v', 'dS_h', 'dS_v',
-    'vertex', 'interval', 'triangle', 'tetrahedron',
-    'prism', 'pyramid', 'pentatope', 'tesseract',
-    'quadrilateral', 'hexahedron', 'facet',
-    'i', 'j', 'k', 'l', 'p', 'q', 'r', 's',
-    'e', 'pi',
+    "product",
+    "as_cell",
+    "AbstractCell",
+    "Cell",
+    "TensorProductCell",
+    "AbstractDomain",
+    "Mesh",
+    "MeshView",
+    "L2",
+    "H1",
+    "H2",
+    "HCurl",
+    "HDiv",
+    "HInf",
+    "HEin",
+    "HDivDiv",
+    "identity_pullback",
+    "l2_piola",
+    "contravariant_piola",
+    "covariant_piola",
+    "double_contravariant_piola",
+    "double_covariant_piola",
+    "l2_piola",
+    "MixedPullback",
+    "SymmetricPullback",
+    "AbstractPullback",
+    "SpatialCoordinate",
+    "CellVolume",
+    "CellDiameter",
+    "Circumradius",
+    "MinCellEdgeLength",
+    "MaxCellEdgeLength",
+    "FacetArea",
+    "MinFacetEdgeLength",
+    "MaxFacetEdgeLength",
+    "FacetNormal",
+    "CellNormal",
+    "Jacobian",
+    "JacobianDeterminant",
+    "JacobianInverse",
+    "AbstractFiniteElement",
+    "FunctionSpace",
+    "MixedFunctionSpace",
+    "Argument",
+    "Coargument",
+    "TestFunction",
+    "TrialFunction",
+    "Arguments",
+    "TestFunctions",
+    "TrialFunctions",
+    "Coefficient",
+    "Cofunction",
+    "Coefficients",
+    "Matrix",
+    "Adjoint",
+    "Action",
+    "Interpolate",
+    "interpolate",
+    "ExternalOperator",
+    "Constant",
+    "VectorConstant",
+    "TensorConstant",
+    "split",
+    "PermutationSymbol",
+    "Identity",
+    "zero",
+    "as_ufl",
+    "Index",
+    "indices",
+    "as_tensor",
+    "as_vector",
+    "as_matrix",
+    "unit_vector",
+    "unit_vectors",
+    "unit_matrix",
+    "unit_matrices",
+    "rank",
+    "shape",
+    "conj",
+    "real",
+    "imag",
+    "outer",
+    "inner",
+    "dot",
+    "cross",
+    "perp",
+    "det",
+    "inv",
+    "cofac",
+    "transpose",
+    "tr",
+    "diag",
+    "diag_vector",
+    "dev",
+    "skew",
+    "sym",
+    "sqrt",
+    "exp",
+    "ln",
+    "erf",
+    "cos",
+    "sin",
+    "tan",
+    "acos",
+    "asin",
+    "atan",
+    "atan2",
+    "cosh",
+    "sinh",
+    "tanh",
+    "bessel_J",
+    "bessel_Y",
+    "bessel_I",
+    "bessel_K",
+    "eq",
+    "ne",
+    "le",
+    "ge",
+    "lt",
+    "gt",
+    "And",
+    "Or",
+    "Not",
+    "conditional",
+    "sign",
+    "max_value",
+    "min_value",
+    "variable",
+    "diff",
+    "Dx",
+    "grad",
+    "div",
+    "curl",
+    "rot",
+    "nabla_grad",
+    "nabla_div",
+    "Dn",
+    "exterior_derivative",
+    "jump",
+    "avg",
+    "cell_avg",
+    "facet_avg",
+    "elem_mult",
+    "elem_div",
+    "elem_pow",
+    "elem_op",
+    "Form",
+    "BaseForm",
+    "FormSum",
+    "ZeroBaseForm",
+    "Integral",
+    "Measure",
+    "register_integral_type",
+    "integral_types",
+    "custom_integral_types",
+    "replace",
+    "derivative",
+    "action",
+    "energy_norm",
+    "rhs",
+    "lhs",
+    "extract_blocks",
+    "system",
+    "functional",
+    "adjoint",
+    "sensitivity_rhs",
+    "dx",
+    "ds",
+    "dS",
+    "dP",
+    "dc",
+    "dC",
+    "dO",
+    "dI",
+    "dX",
+    "ds_b",
+    "ds_t",
+    "ds_tb",
+    "ds_v",
+    "dS_h",
+    "dS_v",
+    "vertex",
+    "interval",
+    "triangle",
+    "tetrahedron",
+    "prism",
+    "pyramid",
+    "pentatope",
+    "tesseract",
+    "quadrilateral",
+    "hexahedron",
+    "facet",
+    "i",
+    "j",
+    "k",
+    "l",
+    "p",
+    "q",
+    "r",
+    "s",
+    "e",
+    "pi",
 ]
diff --git a/ufl/action.py b/ufl/action.py
index 2401e05ea..3bb9fd533 100644
--- a/ufl/action.py
+++ b/ufl/action.py
@@ -45,7 +45,8 @@ class Action(BaseForm):
         "_arguments",
         "_coefficients",
         "_domains",
-        "_hash")
+        "_hash",
+    )
 
     def __new__(cls, *args, **kw):
         """Create a new Action."""
@@ -71,12 +72,10 @@ def __new__(cls, *args, **kw):
 
         if isinstance(left, (FormSum, Sum)):
             # Action distributes over sums on the LHS
-            return FormSum(*[(Action(component, right), 1)
-                             for component in left.ufl_operands])
+            return FormSum(*[(Action(component, right), 1) for component in left.ufl_operands])
         if isinstance(right, (FormSum, Sum)):
             # Action also distributes over sums on the RHS
-            return FormSum(*[(Action(left, component), 1)
-                             for component in right.ufl_operands])
+            return FormSum(*[(Action(left, component), 1) for component in right.ufl_operands])
 
         return super(Action, cls).__new__(cls)
 
@@ -98,8 +97,7 @@ def __init__(self, left, right):
     def ufl_function_spaces(self):
         """Get the tuple of function spaces of the underlying form."""
         if isinstance(self._right, Form):
-            return self._left.ufl_function_spaces()[:-1] \
-                + self._right.ufl_function_spaces()[1:]
+            return self._left.ufl_function_spaces()[:-1] + self._right.ufl_function_spaces()[1:]
         elif isinstance(self._right, Coefficient):
             return self._left.ufl_function_spaces()[:-1]
 
@@ -124,7 +122,9 @@ def _analyze_domains(self):
         from ufl.domain import join_domains
 
         # Collect domains
-        self._domains = join_domains(chain.from_iterable(e.ufl_domains() for e in self.ufl_operands))
+        self._domains = join_domains(
+            chain.from_iterable(e.ufl_domains() for e in self.ufl_operands)
+        )
 
     def equals(self, other):
         """Check if two Actions are equal."""
@@ -158,18 +158,19 @@ def _check_function_spaces(left, right):
         # right as a consequence of Leibniz formula.
         right, *_ = right.ufl_operands
 
-    # `left` can also be a Coefficient in V (= V**), e.g. `action(Coefficient(V), Cofunction(V.dual()))`.
+    # `left` can also be a Coefficient in V (= V**), e.g.
+    # `action(Coefficient(V), Cofunction(V.dual()))`.
     left_arg = left.arguments()[-1] if not isinstance(left, Coefficient) else left
     if isinstance(right, (Form, Action, Matrix, ZeroBaseForm)):
         if left_arg.ufl_function_space().dual() != right.arguments()[0].ufl_function_space():
             raise TypeError("Incompatible function spaces in Action")
     elif isinstance(right, (Coefficient, Cofunction, Argument, BaseFormOperator)):
         if left_arg.ufl_function_space() != right.ufl_function_space():
-
             raise TypeError("Incompatible function spaces in Action")
     # `Zero` doesn't contain any information about the function space.
-    # -> Not a problem since Action will get simplified with a `ZeroBaseForm`
-    #    which won't take into account the arguments on the right because of argument contraction.
+    # -> Not a problem since Action will get simplified with a
+    #    `ZeroBaseForm` which won't take into account the arguments on
+    #    the right because of argument contraction.
     # This occurs for:
     # `derivative(Action(A, B), u)` with B is an `Expr` such that dB/du == 0
     # -> `derivative(B, u)` becomes `Zero` when expanding derivatives since B is an Expr.
@@ -180,7 +181,8 @@ def _check_function_spaces(left, right):
 def _get_action_form_arguments(left, right):
     """Perform argument contraction to work out the arguments of Action."""
     coefficients = ()
-    # `left` can also be a Coefficient in V (= V**), e.g. `action(Coefficient(V), Cofunction(V.dual()))`.
+    # `left` can also be a Coefficient in V (= V**), e.g.
+    # `action(Coefficient(V), Cofunction(V.dual()))`.
     left_args = left.arguments()[:-1] if not isinstance(left, Coefficient) else ()
     if isinstance(right, BaseForm):
         arguments = left_args + right.arguments()[1:]
@@ -189,6 +191,7 @@ def _get_action_form_arguments(left, right):
         # Action differentiation pushes differentiation through
         # right as a consequence of Leibniz formula.
         from ufl.algorithms.analysis import extract_arguments_and_coefficients
+
         right_args, right_coeffs = extract_arguments_and_coefficients(right)
         arguments = left_args + tuple(right_args)
         coefficients += tuple(right_coeffs)
diff --git a/ufl/adjoint.py b/ufl/adjoint.py
index 38f003870..92447b985 100644
--- a/ufl/adjoint.py
+++ b/ufl/adjoint.py
@@ -32,7 +32,8 @@ class Adjoint(BaseForm):
         "_coefficients",
         "_domains",
         "ufl_operands",
-        "_hash")
+        "_hash",
+    )
 
     def __new__(cls, *args, **kw):
         """Create a new Adjoint."""
@@ -46,15 +47,17 @@ def __new__(cls, *args, **kw):
             return form._form
         elif isinstance(form, FormSum):
             # Adjoint distributes over sums
-            return FormSum(*[(Adjoint(component), 1)
-                             for component in form.components()])
+            return FormSum(*[(Adjoint(component), 1) for component in form.components()])
         elif isinstance(form, Coargument):
-            # The adjoint of a coargument `c: V* -> V*` is the identity matrix mapping from V to V (i.e. V x V* -> R).
-            # Equivalently, the adjoint of `c` is its first argument, which is a ufl.Argument defined on the
-            # primal space of `c`.
+            # The adjoint of a coargument `c: V* -> V*` is the identity
+            # matrix mapping from V to V (i.e. V x V* -> R).
+            # Equivalently, the adjoint of `c` is its first argument,
+            # which is a ufl.Argument defined on the primal space of
+            # `c`.
             primal_arg, _ = form.arguments()
-            # Returning the primal argument avoids explicit argument reconstruction, making it
-            # a robust strategy for handling subclasses of `ufl.Coargument`.
+            # Returning the primal argument avoids explicit argument
+            # reconstruction, making it a robust strategy for handling
+            # subclasses of `ufl.Coargument`.
             return primal_arg
 
         return super(Adjoint, cls).__new__(cls)
@@ -98,8 +101,9 @@ def equals(self, other):
             return False
         if self is other:
             return True
-        # Make sure we are returning a boolean as the equality can result in a `ufl.Equation`
-        # if the underlying objects are `ufl.BaseForm`.
+        # Make sure we are returning a boolean as the equality can
+        # result in a `ufl.Equation` if the underlying objects are
+        # `ufl.BaseForm`.
         return bool(self._form == other._form)
 
     def __str__(self):
diff --git a/ufl/algebra.py b/ufl/algebra.py
index 376c16d02..dea6fd021 100644
--- a/ufl/algebra.py
+++ b/ufl/algebra.py
@@ -19,9 +19,13 @@
 # --- Algebraic operators ---
 
 
-@ufl_type(num_ops=2,
-          inherit_shape_from_operand=0, inherit_indices_from_operand=0,
-          binop="__add__", rbinop="__radd__")
+@ufl_type(
+    num_ops=2,
+    inherit_shape_from_operand=0,
+    inherit_indices_from_operand=0,
+    binop="__add__",
+    rbinop="__radd__",
+)
 class Sum(Operator):
     """Sum."""
 
@@ -87,16 +91,14 @@ def __init__(self, a, b):
 
     def evaluate(self, x, mapping, component, index_values):
         """Evaluate."""
-        return sum(o.evaluate(x, mapping, component,
-                              index_values) for o in self.ufl_operands)
+        return sum(o.evaluate(x, mapping, component, index_values) for o in self.ufl_operands)
 
     def __str__(self):
         """Format as a string."""
         return " + ".join([parstr(o, self) for o in self.ufl_operands])
 
 
-@ufl_type(num_ops=2,
-          binop="__mul__", rbinop="__rmul__")
+@ufl_type(num_ops=2, binop="__mul__", rbinop="__rmul__")
 class Product(Operator):
     """The product of two or more UFL objects."""
 
@@ -111,16 +113,20 @@ def __new__(cls, a, b):
         # Type checking
         # Make sure everything is scalar
         if a.ufl_shape or b.ufl_shape:
-            raise ValueError("Product can only represent products of scalars, "
-                             f"got\n    {ufl_err_str(a)}\nand\n    {ufl_err_str(b)}")
+            raise ValueError(
+                "Product can only represent products of scalars, "
+                f"got\n    {ufl_err_str(a)}\nand\n    {ufl_err_str(b)}"
+            )
 
         # Simplification
         if isinstance(a, Zero) or isinstance(b, Zero):
             # Got any zeros? Return zero.
-            fi, fid = merge_unique_indices(a.ufl_free_indices,
-                                           a.ufl_index_dimensions,
-                                           b.ufl_free_indices,
-                                           b.ufl_index_dimensions)
+            fi, fid = merge_unique_indices(
+                a.ufl_free_indices,
+                a.ufl_index_dimensions,
+                b.ufl_free_indices,
+                b.ufl_index_dimensions,
+            )
             return Zero((), fi, fid)
         sa = isinstance(a, ScalarValue)
         sb = isinstance(b, ScalarValue)
@@ -154,10 +160,9 @@ def _init(self, a, b):
         self.ufl_operands = (a, b)
 
         # Extract indices
-        fi, fid = merge_unique_indices(a.ufl_free_indices,
-                                       a.ufl_index_dimensions,
-                                       b.ufl_free_indices,
-                                       b.ufl_index_dimensions)
+        fi, fid = merge_unique_indices(
+            a.ufl_free_indices, a.ufl_index_dimensions, b.ufl_free_indices, b.ufl_index_dimensions
+        )
         self.ufl_free_indices = fi
         self.ufl_index_dimensions = fid
 
@@ -173,7 +178,9 @@ def evaluate(self, x, mapping, component, index_values):
         sh = self.ufl_shape
         if sh:
             if sh != ops[-1].ufl_shape:
-                raise ValueError("Expecting nonscalar product operand to be the last by convention.")
+                raise ValueError(
+                    "Expecting nonscalar product operand to be the last by convention."
+                )
             tmp = ops[-1].evaluate(x, mapping, component, index_values)
             ops = ops[:-1]
         else:
@@ -188,9 +195,7 @@ def __str__(self):
         return " * ".join((parstr(a, self), parstr(b, self)))
 
 
-@ufl_type(num_ops=2,
-          inherit_indices_from_operand=0,
-          binop="__div__", rbinop="__rdiv__")
+@ufl_type(num_ops=2, inherit_indices_from_operand=0, binop="__div__", rbinop="__rdiv__")
 class Division(Operator):
     """Division."""
 
@@ -260,9 +265,7 @@ def __str__(self):
         return f"{parstr(self.ufl_operands[0], self)} / {parstr(self.ufl_operands[1], self)}"
 
 
-@ufl_type(num_ops=2,
-          inherit_indices_from_operand=0,
-          binop="__pow__", rbinop="__rpow__")
+@ufl_type(num_ops=2, inherit_indices_from_operand=0, binop="__pow__", rbinop="__rpow__")
 class Power(Operator):
     """Power."""
 
@@ -282,7 +285,7 @@ def __new__(cls, a, b):
 
         # Simplification
         if isinstance(a, ScalarValue) and isinstance(b, ScalarValue):
-            return as_ufl(a._value ** b._value)
+            return as_ufl(a._value**b._value)
         if isinstance(b, Zero):
             return IntValue(1)
         if isinstance(a, Zero) and isinstance(b, ScalarValue):
@@ -324,9 +327,7 @@ def __str__(self):
         return f"{parstr(a, self)} ** {parstr(b, self)}"
 
 
-@ufl_type(num_ops=1,
-          inherit_shape_from_operand=0, inherit_indices_from_operand=0,
-          unop="__abs__")
+@ufl_type(num_ops=1, inherit_shape_from_operand=0, inherit_indices_from_operand=0, unop="__abs__")
 class Abs(Operator):
     """Absolute value."""
 
@@ -357,12 +358,11 @@ def evaluate(self, x, mapping, component, index_values):
 
     def __str__(self):
         """Format as a string."""
-        a, = self.ufl_operands
+        (a,) = self.ufl_operands
         return f"|{parstr(a, self)}|"
 
 
-@ufl_type(num_ops=1,
-          inherit_shape_from_operand=0, inherit_indices_from_operand=0)
+@ufl_type(num_ops=1, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class Conj(Operator):
     """Complex conjugate."""
 
@@ -393,12 +393,11 @@ def evaluate(self, x, mapping, component, index_values):
 
     def __str__(self):
         """Format as a string."""
-        a, = self.ufl_operands
+        (a,) = self.ufl_operands
         return f"conj({parstr(a, self)})"
 
 
-@ufl_type(num_ops=1,
-          inherit_shape_from_operand=0, inherit_indices_from_operand=0)
+@ufl_type(num_ops=1, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class Real(Operator):
     """Real part."""
 
@@ -431,12 +430,11 @@ def evaluate(self, x, mapping, component, index_values):
 
     def __str__(self):
         """Format as a string."""
-        a, = self.ufl_operands
+        (a,) = self.ufl_operands
         return f"Re[{parstr(a, self)}]"
 
 
-@ufl_type(num_ops=1,
-          inherit_shape_from_operand=0, inherit_indices_from_operand=0)
+@ufl_type(num_ops=1, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class Imag(Operator):
     """Imaginary part."""
 
@@ -467,5 +465,5 @@ def evaluate(self, x, mapping, component, index_values):
 
     def __str__(self):
         """Format as a string."""
-        a, = self.ufl_operands
+        (a,) = self.ufl_operands
         return f"Im[{parstr(a, self)}]"
diff --git a/ufl/algorithms/__init__.py b/ufl/algorithms/__init__.py
index 8e3ce5a1a..43eac078f 100644
--- a/ufl/algorithms/__init__.py
+++ b/ufl/algorithms/__init__.py
@@ -57,9 +57,16 @@
 ]
 
 from ufl.algorithms.ad import expand_derivatives
-from ufl.algorithms.analysis import (extract_arguments, extract_base_form_operators, extract_coefficients,
-                                     extract_elements, extract_sub_elements, extract_type, extract_unique_elements,
-                                     sort_elements)
+from ufl.algorithms.analysis import (
+    extract_arguments,
+    extract_base_form_operators,
+    extract_coefficients,
+    extract_elements,
+    extract_sub_elements,
+    extract_type,
+    extract_unique_elements,
+    sort_elements,
+)
 from ufl.algorithms.change_to_reference import change_to_reference_grad
 from ufl.algorithms.checks import validate_form
 from ufl.algorithms.compute_form_data import compute_form_data, preprocess_form
@@ -68,13 +75,24 @@
 from ufl.algorithms.expand_indices import expand_indices
 from ufl.algorithms.formfiles import load_forms, load_ufl_file, read_ufl_file
 from ufl.algorithms.formsplitter import FormSplitter
-from ufl.algorithms.formtransformations import (compute_energy_norm, compute_form_action, compute_form_adjoint,
-                                                compute_form_arities, compute_form_functional, compute_form_lhs,
-                                                compute_form_rhs)
+from ufl.algorithms.formtransformations import (
+    compute_energy_norm,
+    compute_form_action,
+    compute_form_adjoint,
+    compute_form_arities,
+    compute_form_functional,
+    compute_form_lhs,
+    compute_form_rhs,
+)
 from ufl.algorithms.replace import replace
 from ufl.algorithms.signature import compute_form_signature
 from ufl.algorithms.strip_terminal_data import replace_terminal_data, strip_terminal_data
-from ufl.algorithms.transformer import ReuseTransformer, Transformer, apply_transformer, strip_variables
+from ufl.algorithms.transformer import (
+    ReuseTransformer,
+    Transformer,
+    apply_transformer,
+    strip_variables,
+)
 from ufl.corealg.multifunction import MultiFunction
 from ufl.corealg.traversal import post_traversal
 from ufl.utils.formatting import tree_format
diff --git a/ufl/algorithms/analysis.py b/ufl/algorithms/analysis.py
index ba3afe6c6..1d0464a95 100644
--- a/ufl/algorithms/analysis.py
+++ b/ufl/algorithms/analysis.py
@@ -1,4 +1,4 @@
-"""Utility algorithms for inspection of and information extraction from UFL objects in various ways."""
+"""Utility algorithms for inspection of and information extraction from UFL objects."""
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
@@ -43,6 +43,7 @@ def unique_tuple(objects):
 
 # --- Utilities to extract information from an expression ---
 
+
 def extract_type(a, ufl_types):
     """Build a set of all objects found in a whose class is in ufl_types.
 
@@ -76,15 +77,22 @@ def extract_type(a, ufl_types):
 
     if all(issubclass(t, Terminal) for t in ufl_types):
         # Optimization
-        objects = set(o for e in iter_expressions(a)
-                      for o in traverse_unique_terminals(e)
-                      if any(isinstance(o, t) for t in ufl_types))
+        objects = set(
+            o
+            for e in iter_expressions(a)
+            for o in traverse_unique_terminals(e)
+            if any(isinstance(o, t) for t in ufl_types)
+        )
     else:
-        objects = set(o for e in iter_expressions(a)
-                      for o in unique_pre_traversal(e)
-                      if any(isinstance(o, t) for t in ufl_types))
-
-    # Need to extract objects contained in base form operators whose type is in ufl_types
+        objects = set(
+            o
+            for e in iter_expressions(a)
+            for o in unique_pre_traversal(e)
+            if any(isinstance(o, t) for t in ufl_types)
+        )
+
+    # Need to extract objects contained in base form operators whose
+    # type is in ufl_types
     base_form_ops = set(e for e in objects if isinstance(e, BaseFormOperator))
     ufl_types_no_args = tuple(t for t in ufl_types if not issubclass(t, BaseArgument))
     base_form_objects = ()
@@ -93,16 +101,19 @@ def extract_type(a, ufl_types):
         # `N(u; v*) * v * dx` <=> `action(v1 * v * dx, N(...; v*))`
         # where `v`, `v1` are `Argument`s and `v*` a `Coargument`.
         for ai in tuple(arg for arg in o.argument_slots(isinstance(a, Form))):
-            # Extracting BaseArguments of an object of which a Coargument is an argument,
-            # then we just return the dual argument of the Coargument and not its primal argument.
+            # Extracting BaseArguments of an object of which a
+            # Coargument is an argument, then we just return the dual
+            # argument of the Coargument and not its primal argument.
             if isinstance(ai, Coargument):
                 new_types = tuple(Coargument if t is BaseArgument else t for t in ufl_types)
                 base_form_objects += tuple(extract_type(ai, new_types))
             else:
                 base_form_objects += tuple(extract_type(ai, ufl_types))
-        # Look for BaseArguments in BaseFormOperator's argument slots only since that's where they are by definition.
-        # Don't look into operands, which is convenient for external operator composition, e.g. N1(N2; v*)
-        # where N2 is seen as an operator and not a form.
+        # Look for BaseArguments in BaseFormOperator's argument slots
+        # only since that's where they are by definition. Don't look
+        # into operands, which is convenient for external operator
+        # composition, e.g. N1(N2; v*) where N2 is seen as an operator
+        # and not a form.
         slots = o.ufl_operands
         for ai in slots:
             base_form_objects += tuple(extract_type(ai, ufl_types_no_args))
@@ -207,14 +218,16 @@ def extract_arguments_and_coefficients(a):
         raise ValueError(
             "Found different Arguments with same number and part.\n"
             "Did you combine test or trial functions from different spaces?\n"
-            "The Arguments found are:\n" + "\n".join(f"  {a}" for a in arguments))
+            "The Arguments found are:\n" + "\n".join(f"  {a}" for a in arguments)
+        )
 
     # Build count: instance mappings, should be one to one
     fcounts = dict((f, f.count()) for f in coefficients)
     if len(fcounts) != len(set(fcounts.values())):
         raise ValueError(
             "Found different coefficients with same counts.\n"
-            "The arguments found are:\n" + "\n".join(f"  {c}" for c in coefficients))
+            "The arguments found are:\n" + "\n".join(f"  {c}" for c in coefficients)
+        )
 
     # Passed checks, so we can safely sort the instances by count
     arguments = _sorted_by_number_and_part(arguments)
diff --git a/ufl/algorithms/apply_algebra_lowering.py b/ufl/algorithms/apply_algebra_lowering.py
index e7dc4cd46..ea5b3bbb2 100644
--- a/ufl/algorithms/apply_algebra_lowering.py
+++ b/ufl/algorithms/apply_algebra_lowering.py
@@ -1,4 +1,4 @@
-"""Algorithm for expanding compound expressions into equivalent representations using basic operators."""
+"""Algorithm for expanding compound expressions."""
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
@@ -53,8 +53,10 @@ def sym(self, o, A):
 
     def cross(self, o, a, b):
         """Lower a cross."""
+
         def c(i, j):
             return Product(a[i], b[j]) - Product(a[j], b[i])
+
         return as_vector((c(1, 2), c(2, 0), c(0, 1)))
 
     def perp(self, o, a):
@@ -125,12 +127,14 @@ def nabla_grad(self, o, a):
 
     def curl(self, o, a):
         """Lower a curl."""
+
         # o = curl a = "[a.dx(1), -a.dx(0)]"            if a.ufl_shape == ()
         # o = curl a = "cross(nabla, (a0, a1, 0))[2]" if a.ufl_shape == (2,)
         # o = curl a = "cross(nabla, a)"              if a.ufl_shape == (3,)
         def c(i, j):
             """A component of curl."""
             return a[j].dx(i) - a[i].dx(j)
+
         sh = a.ufl_shape
         if sh == ():
             return as_vector((a.dx(1), -a.dx(0)))
diff --git a/ufl/algorithms/apply_derivatives.py b/ufl/algorithms/apply_derivatives.py
index 7ef8a0a5f..6fcbb1b5f 100644
--- a/ufl/algorithms/apply_derivatives.py
+++ b/ufl/algorithms/apply_derivatives.py
@@ -1,4 +1,4 @@
-"""This module contains the apply_derivatives algorithm which computes the derivatives of a form of expression."""
+"""Apply derivatives algorithm which computes the derivatives of a form of expression."""
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
@@ -16,9 +16,31 @@
 from ufl.algorithms.replace_derivative_nodes import replace_derivative_nodes
 from ufl.argument import BaseArgument
 from ufl.checks import is_cellwise_constant
-from ufl.classes import (Coefficient, ComponentTensor, Conj, ConstantValue, ExprList, ExprMapping, FloatValue,
-                         FormArgument, Grad, Identity, Imag, Indexed, IndexSum, JacobianInverse, ListTensor, Product,
-                         Real, ReferenceGrad, ReferenceValue, SpatialCoordinate, Sum, Variable, Zero)
+from ufl.classes import (
+    Coefficient,
+    ComponentTensor,
+    Conj,
+    ConstantValue,
+    ExprList,
+    ExprMapping,
+    FloatValue,
+    FormArgument,
+    Grad,
+    Identity,
+    Imag,
+    Indexed,
+    IndexSum,
+    JacobianInverse,
+    ListTensor,
+    Product,
+    Real,
+    ReferenceGrad,
+    ReferenceValue,
+    SpatialCoordinate,
+    Sum,
+    Variable,
+    Zero,
+)
 from ufl.constantvalue import is_true_ufl_scalar, is_ufl_scalar
 from ufl.core.base_form_operator import BaseFormOperator
 from ufl.core.expr import ufl_err_str
@@ -26,11 +48,30 @@
 from ufl.core.terminal import Terminal
 from ufl.corealg.map_dag import map_expr_dag
 from ufl.corealg.multifunction import MultiFunction
-from ufl.differentiation import BaseFormCoordinateDerivative, BaseFormOperatorDerivative, CoordinateDerivative
+from ufl.differentiation import (
+    BaseFormCoordinateDerivative,
+    BaseFormOperatorDerivative,
+    CoordinateDerivative,
+)
 from ufl.domain import extract_unique_domain
 from ufl.form import Form, ZeroBaseForm
-from ufl.operators import (bessel_I, bessel_J, bessel_K, bessel_Y, cell_avg, conditional, cos, cosh, exp, facet_avg, ln,
-                           sign, sin, sinh, sqrt)
+from ufl.operators import (
+    bessel_I,
+    bessel_J,
+    bessel_K,
+    bessel_Y,
+    cell_avg,
+    conditional,
+    cos,
+    cosh,
+    exp,
+    facet_avg,
+    ln,
+    sign,
+    sin,
+    sinh,
+    sqrt,
+)
 from ufl.pullback import CustomPullback, PhysicalPullback
 from ufl.tensors import as_scalar, as_scalars, as_tensor, unit_indexed_tensor, unwrap_list_tensor
 
@@ -53,8 +94,10 @@ def __init__(self, var_shape):
 
     def expr(self, o):
         """Raise error."""
-        raise ValueError(f"Missing differentiation handler for type {o._ufl_class_.__name__}. "
-                         "Have you added a new type?")
+        raise ValueError(
+            f"Missing differentiation handler for type {o._ufl_class_.__name__}. "
+            "Have you added a new type?"
+        )
 
     def unexpected(self, o):
         """Raise error about unexpected type."""
@@ -62,11 +105,16 @@ def unexpected(self, o):
 
     def override(self, o):
         """Raise error about overriding."""
-        raise ValueError(f"Type {o._ufl_class_.__name__} must be overridden in specialized AD rule set.")
+        raise ValueError(
+            f"Type {o._ufl_class_.__name__} must be overridden in specialized AD rule set."
+        )
 
     def derivative(self, o):
         """Raise error."""
-        raise ValueError(f"Unhandled derivative type {o._ufl_class_.__name__}, nested differentiation has failed.")
+        raise ValueError(
+            f"Unhandled derivative type {o._ufl_class_.__name__}, "
+            "nested differentiation has failed."
+        )
 
     # --- Some types just don't have any derivative, this is just to
     # --- make algorithm structure generic
@@ -74,20 +122,22 @@ def derivative(self, o):
     def non_differentiable_terminal(self, o):
         """Return the non-differentiated object.
 
-        Labels and indices are not differentiable: it's convenient to return the non-differentiated object.
+        Labels and indices are not differentiable: it's convenient to
+        return the non-differentiated object.
         """
         return o
+
     label = non_differentiable_terminal
     multi_index = non_differentiable_terminal
 
     # --- Helper functions for creating zeros with the right shapes
 
     def independent_terminal(self, o):
-        """Return a zero with the right shape for terminals independent of differentiation variable."""
+        """A zero with correct shape for terminals independent of diff. variable."""
         return Zero(o.ufl_shape + self._var_shape)
 
     def independent_operator(self, o):
-        """Return a zero with the right shape and indices for operators independent of differentiation variable."""
+        """A zero with correct shape and indices for operators independent of diff. variable."""
         return Zero(o.ufl_shape + self._var_shape, o.ufl_free_indices, o.ufl_index_dimensions)
 
     # --- All derivatives need to define grad and averaging
@@ -276,11 +326,13 @@ def power(self, o, fp, gp):
         if isinstance(gp, Zero):
             # This probably produces better results for the common
             # case of f**constant
-            op = fp * g * f**(g - 1)
+            op = fp * g * f ** (g - 1)
         else:
             # Note: This produces expressions like (1/w)*w**5 instead of w**4
             # op = o * (fp * g / f + gp * ln(f)) # This reuses o
-            op = f**(g - 1) * (g * fp + f * ln(f) * gp)  # This gives better accuracy in dolfin integration test
+            op = f ** (g - 1) * (
+                g * fp + f * ln(f) * gp
+            )  # This gives better accuracy in dolfin integration test
 
         # Example: d/dx[x**(x**3)]:
         # f = x
@@ -296,7 +348,7 @@ def power(self, o, fp, gp):
 
     def abs(self, o, df):
         """Differentiate an abs."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         # return conditional(eq(f, 0), 0, Product(sign(f), df)) abs is
         # not complex differentiable, so we workaround the case of a
         # real F in complex mode by defensively casting to real inside
@@ -323,8 +375,8 @@ def math_function(self, o, df):
         """Differentiate a math_function."""
         # FIXME: Introduce a UserOperator type instead of this hack
         # and define user derivative() function properly
-        if hasattr(o, 'derivative'):
-            f, = o.ufl_operands
+        if hasattr(o, "derivative"):
+            (f,) = o.ufl_operands
             return df * o.derivative()
         raise ValueError("Unknown math function.")
 
@@ -338,57 +390,58 @@ def exp(self, o, fp):
 
     def ln(self, o, fp):
         """Differentiate a ln."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         if isinstance(f, Zero):
             raise ZeroDivisionError()
         return fp / f
 
     def cos(self, o, fp):
         """Differentiate a cos."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         return fp * -sin(f)
 
     def sin(self, o, fp):
         """Differentiate a sin."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         return fp * cos(f)
 
     def tan(self, o, fp):
         """Differentiate a tan."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         return 2.0 * fp / (cos(2.0 * f) + 1.0)
 
     def cosh(self, o, fp):
         """Differentiate a cosh."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         return fp * sinh(f)
 
     def sinh(self, o, fp):
         """Differentiate a sinh."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         return fp * cosh(f)
 
     def tanh(self, o, fp):
         """Differentiate a tanh."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
 
         def sech(y):
             return (2.0 * cosh(y)) / (cosh(2.0 * y) + 1.0)
-        return fp * sech(f)**2
+
+        return fp * sech(f) ** 2
 
     def acos(self, o, fp):
         """Differentiate an acos."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         return -fp / sqrt(1.0 - f**2)
 
     def asin(self, o, fp):
         """Differentiate an asin."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         return fp / sqrt(1.0 - f**2)
 
     def atan(self, o, fp):
         """Differentiate an atan."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         return fp / (1.0 + f**2)
 
     def atan2(self, o, fp, gp):
@@ -398,8 +451,8 @@ def atan2(self, o, fp, gp):
 
     def erf(self, o, fp):
         """Differentiate an erf."""
-        f, = o.ufl_operands
-        return fp * (2.0 / sqrt(pi) * exp(-f**2))
+        (f,) = o.ufl_operands
+        return fp * (2.0 / sqrt(pi) * exp(-(f**2)))
 
     # --- Bessel functions
 
@@ -407,7 +460,9 @@ def bessel_j(self, o, nup, fp):
         """Differentiate a bessel_j."""
         nu, f = o.ufl_operands
         if not (nup is None or isinstance(nup, Zero)):
-            raise NotImplementedError("Differentiation of bessel function w.r.t. nu is not supported.")
+            raise NotImplementedError(
+                "Differentiation of bessel function w.r.t. nu is not supported."
+            )
 
         if isinstance(nu, Zero):
             op = -bessel_J(1, f)
@@ -419,7 +474,9 @@ def bessel_y(self, o, nup, fp):
         """Differentiate a bessel_y."""
         nu, f = o.ufl_operands
         if not (nup is None or isinstance(nup, Zero)):
-            raise NotImplementedError("Differentiation of bessel function w.r.t. nu is not supported.")
+            raise NotImplementedError(
+                "Differentiation of bessel function w.r.t. nu is not supported."
+            )
 
         if isinstance(nu, Zero):
             op = -bessel_Y(1, f)
@@ -431,7 +488,9 @@ def bessel_i(self, o, nup, fp):
         """Differentiate a bessel_i."""
         nu, f = o.ufl_operands
         if not (nup is None or isinstance(nup, Zero)):
-            raise NotImplementedError("Differentiation of bessel function w.r.t. nu is not supported.")
+            raise NotImplementedError(
+                "Differentiation of bessel function w.r.t. nu is not supported."
+            )
 
         if isinstance(nu, Zero):
             op = bessel_I(1, f)
@@ -443,7 +502,9 @@ def bessel_k(self, o, nup, fp):
         """Differentiate a bessel_k."""
         nu, f = o.ufl_operands
         if not (nup is None or isinstance(nup, Zero)):
-            raise NotImplementedError("Differentiation of bessel function w.r.t. nu is not supported.")
+            raise NotImplementedError(
+                "Differentiation of bessel function w.r.t. nu is not supported."
+            )
 
         if isinstance(nu, Zero):
             op = -bessel_K(1, f)
@@ -568,7 +629,8 @@ def base_form_operator(self, o):
         """Differentiate a base_form_operator."""
         # Push the grad through the operator is not legal in most cases:
         #    -> Not enouth regularity for chain rule to hold!
-        # By the time we evaluate `grad(o)`, the operator `o` will have been assembled and substituted by its output.
+        # By the time we evaluate `grad(o)`, the operator `o` will have
+        # been assembled and substituted by its output.
         return Grad(o)
 
     def coefficient(self, o):
@@ -609,7 +671,9 @@ def reference_grad(self, o):
         # grad(o) == grad(rgrad(rv(f))) -> K_ji*rgrad(rgrad(rv(f)))_rj
         f = o.ufl_operands[0]
 
-        valid_operand = f._ufl_is_in_reference_frame_ or isinstance(f, (JacobianInverse, SpatialCoordinate))
+        valid_operand = f._ufl_is_in_reference_frame_ or isinstance(
+            f, (JacobianInverse, SpatialCoordinate)
+        )
         if not valid_operand:
             raise ValueError("ReferenceGrad can only wrap a reference frame type!")
         domain = extract_unique_domain(f)
@@ -664,10 +728,10 @@ def grad_to_reference_grad(o, K):
 
 class ReferenceGradRuleset(GenericDerivativeRuleset):
     """Apply the reference grad derivative."""
+
     def __init__(self, topological_dimension):
         """Initialise."""
-        GenericDerivativeRuleset.__init__(self,
-                                          var_shape=(topological_dimension,))
+        GenericDerivativeRuleset.__init__(self, var_shape=(topological_dimension,))
         self._Id = Identity(topological_dimension)
 
     # --- Specialized rules for geometric quantities
@@ -722,7 +786,9 @@ def argument(self, o):
 
     def grad(self, o):
         """Differentiate a grad."""
-        raise ValueError(f"Grad should have been transformed by this point, but got {type(o).__name__}.")
+        raise ValueError(
+            f"Grad should have been transformed by this point, but got {type(o).__name__}."
+        )
 
     def reference_grad(self, o):
         """Differentiate a reference_grad.
@@ -730,8 +796,7 @@ def reference_grad(self, o):
         Represent ref_grad(ref_grad(f)) as RefGrad(RefGrad(f)).
         """
         # Check that o is a "differential terminal"
-        if not isinstance(o.ufl_operands[0],
-                          (ReferenceGrad, ReferenceValue, Terminal)):
+        if not isinstance(o.ufl_operands[0], (ReferenceGrad, ReferenceValue, Terminal)):
             raise ValueError("Expecting only grads applied to a terminal.")
         return ReferenceGrad(o)
 
@@ -741,6 +806,7 @@ def reference_grad(self, o):
 
 class VariableRuleset(GenericDerivativeRuleset):
     """Differentiate with respect to a variable."""
+
     def __init__(self, var):
         """Initialise."""
         GenericDerivativeRuleset.__init__(self, var_shape=var.ufl_shape)
@@ -785,9 +851,6 @@ def _make_identity(self, sh):
     # Explicitly defining da/dw == 0
     argument = GenericDerivativeRuleset.independent_terminal
 
-    # def _argument(self, o):
-    #    return AnnotatedZero(o.ufl_shape + self._var_shape, arguments=(o,))  # TODO: Missing this type
-
     def coefficient(self, o):
         """Differentiate a coefficient.
 
@@ -838,7 +901,8 @@ def reference_value(self, o):
                 #   convert to reference frame in the first place
                 raise ValueError(
                     "Missing implementation: To handle derivatives of rv(f) w.r.t. f for "
-                    "mapped elements, rewriting to reference frame should not happen first...")
+                    "mapped elements, rewriting to reference frame should not happen first..."
+                )
             # dv/dv = identity of rank 2*rank(v)
             return self._Id
         else:
@@ -850,8 +914,7 @@ def reference_grad(self, o):
 
         Variable derivative of a gradient of a terminal must be 0.
         """
-        if not isinstance(o.ufl_operands[0],
-                          (ReferenceGrad, ReferenceValue)):
+        if not isinstance(o.ufl_operands[0], (ReferenceGrad, ReferenceValue)):
             raise ValueError("Unexpected argument to reference_grad.")
         return self.independent_terminal(o)
 
@@ -942,7 +1005,10 @@ def coefficient(self, o):
             if not isinstance(dos, tuple):
                 dos = (dos,)
             if len(dos) != len(self._v):
-                raise ValueError("Got a tuple of arguments, expecting a matching tuple of coefficient derivatives.")
+                raise ValueError(
+                    "Got a tuple of arguments, expecting a "
+                    "matching tuple of coefficient derivatives."
+                )
             dosum = Zero(o.ufl_shape)
             for do, v in zip(dos, self._v):
                 so, oi = as_scalar(do)
@@ -958,7 +1024,9 @@ def coefficient(self, o):
 
     def reference_value(self, o):
         """Differentiate a reference_value."""
-        raise NotImplementedError("Currently no support for ReferenceValue in CoefficientDerivative.")
+        raise NotImplementedError(
+            "Currently no support for ReferenceValue in CoefficientDerivative."
+        )
         # TODO: This is implementable for regular derivative(M(f),f,v)
         #       but too messy if customized coefficient derivative
         #       relations are given by the user.  We would only need
@@ -976,7 +1044,9 @@ def reference_value(self, o):
 
     def reference_grad(self, o):
         """Differentiate a reference_grad."""
-        raise NotImplementedError("Currently no support for ReferenceGrad in CoefficientDerivative.")
+        raise NotImplementedError(
+            "Currently no support for ReferenceGrad in CoefficientDerivative."
+        )
         # TODO: This is implementable for regular derivative(M(f),f,v)
         #       but too messy if customized coefficient derivative
         #       relations are given by the user.  We would only need
@@ -995,7 +1065,7 @@ def grad(self, g):
         ngrads = 0
         o = g
         while isinstance(o, Grad):
-            o, = o.ufl_operands
+            (o,) = o.ufl_operands
             ngrads += 1
         # `grad(N)` where N is a BaseFormOperator is treated as if `N` was a Coefficient.
         if not isinstance(o, (FormArgument, BaseFormOperator)):
@@ -1008,7 +1078,7 @@ def apply_grads(f):
 
         # Find o among all w without any indexing, which makes this
         # easy
-        for (w, v) in zip(self._w, self._v):
+        for w, v in zip(self._w, self._v):
             if o == w and isinstance(v, FormArgument):
                 # Case: d/dt [w + t v]
                 return apply_grads(v)
@@ -1048,8 +1118,7 @@ def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
 
         # Accumulate contributions from variations in different
         # components
-        for (w, v) in zip(self._w, self._v):
-
+        for w, v in zip(self._w, self._v):
             # -- Analyse differentiation variable coefficient -- #
 
             # Can differentiate a Form wrt a BaseFormOperator
@@ -1067,7 +1136,9 @@ def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
                     for wcomp, vsub in unwrap_list_tensor(v):
                         if not isinstance(vsub, Zero):
                             vval, vcomp = analyse_variation_argument(vsub)
-                            gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
+                            gprimesum = gprimesum + compute_gprimeterm(
+                                ngrads, vval, vcomp, wshape, wcomp
+                            )
 
                 else:
                     if wshape != ():
@@ -1076,11 +1147,11 @@ def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
                     wval, wcomp = w, ()
 
                     vval, vcomp = analyse_variation_argument(v)
-                    gprimesum = gprimesum + compute_gprimeterm(ngrads, vval,
-                                                               vcomp, wshape,
-                                                               wcomp)
+                    gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
 
-            elif isinstance(w, Indexed):  # This path is tested in unit tests, but not actually used?
+            elif isinstance(
+                w, Indexed
+            ):  # This path is tested in unit tests, but not actually used?
                 # Case: d/dt [w[...] + t v[...]]
                 # Case: d/dt [w[...] + t v]
                 wval, wcomp = w.ufl_operands
@@ -1115,14 +1186,15 @@ def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
                     if len(oprimes) != len(self._v):
                         raise ValueError(
                             "Got a tuple of arguments, expecting a"
-                            " matching tuple of coefficient derivatives.")
+                            " matching tuple of coefficient derivatives."
+                        )
 
                 # Compute dg/dw_j = dg/dw_h : v.
                 # Since we may actually have a tuple of oprimes and vs
                 # in a 'mixed' space, sum over them all to get the
                 # complete inner product. Using indices to define a
                 # non-compound inner product.
-                for (oprime, v) in zip(oprimes, self._v):
+                for oprime, v in zip(oprimes, self._v):
                     raise NotImplementedError("FIXME: Figure out how to do this with ngrads")
                     so, oi = as_scalar(oprime)
                     rv = len(v.ufl_shape)
@@ -1144,8 +1216,10 @@ def coordinate_derivative(self, o):
     def base_form_operator(self, o, *dfs):
         """Differentiate a base_form_operator.
 
-        If d_coeff = 0 => BaseFormOperator's derivative is taken wrt a variable => we call the appropriate handler.
-        Otherwise => differentiation done wrt the BaseFormOperator (dF/dN[Nhat]) => we treat o as a Coefficient.
+        If d_coeff = 0 => BaseFormOperator's derivative is taken wrt a
+        variable => we call the appropriate handler. Otherwise =>
+        differentiation done wrt the BaseFormOperator (dF/dN[Nhat]) =>
+        we treat o as a Coefficient.
         """
         d_coeff = self.coefficient(o)
         # It also handles the non-scalar case
@@ -1178,7 +1252,8 @@ def coargument(self, o):
     def matrix(self, M):
         """Differentiate a matrix."""
         # Matrix rule: D_w[v](M) = v if M == w else 0
-        # We can't differentiate wrt a matrix so always return zero in the appropriate space
+        # We can't differentiate wrt a matrix so always return zero in
+        # the appropriate space
         return ZeroBaseForm(M.arguments() + self._v)
 
 
@@ -1191,22 +1266,31 @@ class BaseFormOperatorDerivativeRuleset(GateauxDerivativeRuleset):
 
     def __init__(self, coefficients, arguments, coefficient_derivatives, pending_operations):
         """Initialise."""
-        GateauxDerivativeRuleset.__init__(self, coefficients, arguments, coefficient_derivatives, pending_operations)
+        GateauxDerivativeRuleset.__init__(
+            self, coefficients, arguments, coefficient_derivatives, pending_operations
+        )
 
     def pending_operations_recording(base_form_operator_handler):
         """Decorate a function to record pending operations."""
+
         def wrapper(self, base_form_op, *dfs):
             """Decorate."""
-            # Get the outer `BaseFormOperator` expression, i.e. the operator that is being differentiated.
+            # Get the outer `BaseFormOperator` expression, i.e. the
+            # operator that is being differentiated.
             expression = self.pending_operations.expression
-            # If the base form operator we observe is different from the outer `BaseFormOperator`:
-            # -> Record that `BaseFormOperator` so that `d(expression)/d(base_form_op)` can then be computed later.
+            # If the base form operator we observe is different from the
+            # outer `BaseFormOperator`:
+            # -> Record that `BaseFormOperator` so that
+            # `d(expression)/d(base_form_op)` can then be computed
+            # later.
             # Else:
-            # -> Compute the Gateaux derivative of `base_form_ops` by calling the appropriate handler.
+            # -> Compute the Gateaux derivative of `base_form_ops` by
+            # calling the appropriate handler.
             if expression != base_form_op:
                 self.pending_operations += (base_form_op,)
                 return self.coefficient(base_form_op)
             return base_form_operator_handler(self, base_form_op, *dfs)
+
         return wrapper
 
     @pending_operations_recording
@@ -1232,16 +1316,22 @@ def external_operator(self, N, *dfs):
                 #
                 #   `\sum_{i} dNdOi(..., Oi, ...; DOi(u)[v], ..., v*)`
                 #
-                # where we differentate wrt u, Oi is the i-th operand, N(..., Oi, ...; ..., v*) an ExternalOperator
-                # and v the direction (Argument). dNdOi(..., Oi, ...; DOi(u)[v]) is an ExternalOperator
-                # representing the Gateaux-derivative of N. For example:
+                # where we differentate wrt u, Oi is the i-th operand,
+                # N(..., Oi, ...; ..., v*) an ExternalOperator and v the
+                # direction (Argument). dNdOi(..., Oi, ...; DOi(u)[v])
+                # is an ExternalOperator representing the
+                # Gateaux-derivative of N. For example:
                 #  -> From N(u) = u**2, we get `dNdu(u; uhat, v*) = 2 * u * uhat`.
                 new_args = N.argument_slots() + (df,)
-                extop = N._ufl_expr_reconstruct_(*N.ufl_operands, derivatives=derivatives, argument_slots=new_args)
+                extop = N._ufl_expr_reconstruct_(
+                    *N.ufl_operands, derivatives=derivatives, argument_slots=new_args
+                )
             elif df == 0:
                 extop = Zero(N.ufl_shape)
             else:
-                raise NotImplementedError('Frechet derivative of external operators need to be provided!')
+                raise NotImplementedError(
+                    "Frechet derivative of external operators need to be provided!"
+                )
             result += (extop,)
         return sum(result)
 
@@ -1274,49 +1364,47 @@ def grad(self, o, f):
         """Apply to a grad."""
         rules = GradRuleset(o.ufl_shape[-1])
         key = (GradRuleset, o.ufl_shape[-1])
-        return map_expr_dag(rules, f,
-                            vcache=self.vcaches[key],
-                            rcache=self.rcaches[key])
+        return map_expr_dag(rules, f, vcache=self.vcaches[key], rcache=self.rcaches[key])
 
     def reference_grad(self, o, f):
         """Apply to a reference_grad."""
         rules = ReferenceGradRuleset(o.ufl_shape[-1])  # FIXME: Look over this and test better.
         key = (ReferenceGradRuleset, o.ufl_shape[-1])
-        return map_expr_dag(rules, f,
-                            vcache=self.vcaches[key],
-                            rcache=self.rcaches[key])
+        return map_expr_dag(rules, f, vcache=self.vcaches[key], rcache=self.rcaches[key])
 
     def variable_derivative(self, o, f, dummy_v):
         """Apply to a variable_derivative."""
         op = o.ufl_operands[1]
         rules = VariableRuleset(op)
         key = (VariableRuleset, op)
-        return map_expr_dag(rules, f,
-                            vcache=self.vcaches[key],
-                            rcache=self.rcaches[key])
+        return map_expr_dag(rules, f, vcache=self.vcaches[key], rcache=self.rcaches[key])
 
     def coefficient_derivative(self, o, f, dummy_w, dummy_v, dummy_cd):
         """Apply to a coefficient_derivative."""
         dummy, w, v, cd = o.ufl_operands
-        pending_operations = BaseFormOperatorDerivativeRecorder(f, w, arguments=v, coefficient_derivatives=cd)
+        pending_operations = BaseFormOperatorDerivativeRecorder(
+            f, w, arguments=v, coefficient_derivatives=cd
+        )
         rules = GateauxDerivativeRuleset(w, v, cd, pending_operations)
         key = (GateauxDerivativeRuleset, w, v, cd)
-        # We need to go through the dag first to record the pending operations
-        mapped_expr = map_expr_dag(rules, f,
-                                   vcache=self.vcaches[key],
-                                   rcache=self.rcaches[key])
-        # Need to account for pending operations that have been stored in other integrands
+        # We need to go through the dag first to record the pending
+        # operations
+        mapped_expr = map_expr_dag(rules, f, vcache=self.vcaches[key], rcache=self.rcaches[key])
+        # Need to account for pending operations that have been stored
+        # in other integrands
         self.pending_operations += pending_operations
         return mapped_expr
 
     def base_form_operator_derivative(self, o, f, dummy_w, dummy_v, dummy_cd):
         """Apply to a base_form_operator_derivative."""
         dummy, w, v, cd = o.ufl_operands
-        pending_operations = BaseFormOperatorDerivativeRecorder(f, w, arguments=v, coefficient_derivatives=cd)
+        pending_operations = BaseFormOperatorDerivativeRecorder(
+            f, w, arguments=v, coefficient_derivatives=cd
+        )
         rules = BaseFormOperatorDerivativeRuleset(w, v, cd, pending_operations=pending_operations)
         key = (BaseFormOperatorDerivativeRuleset, w, v, cd)
         if isinstance(f, ZeroBaseForm):
-            arg, = v.ufl_operands
+            (arg,) = v.ufl_operands
             arguments = f.arguments()
             # derivative(F, u, du) with `du` a Coefficient
             # is equivalent to taking the action of the derivative.
@@ -1325,9 +1413,7 @@ def base_form_operator_derivative(self, o, f, dummy_w, dummy_v, dummy_cd):
                 arguments += (arg,)
             return ZeroBaseForm(arguments)
         # We need to go through the dag first to record the pending operations
-        mapped_expr = map_expr_dag(rules, f,
-                                   vcache=self.vcaches[key],
-                                   rcache=self.rcaches[key])
+        mapped_expr = map_expr_dag(rules, f, vcache=self.vcaches[key], rcache=self.rcaches[key])
 
         mapped_f = rules.coefficient(f)
         if mapped_f != 0:
@@ -1342,19 +1428,23 @@ def coordinate_derivative(self, o, f, dummy_w, dummy_v, dummy_cd):
         """Apply to a coordinate_derivative."""
         o_ = o.ufl_operands
         key = (CoordinateDerivative, o_[0])
-        return CoordinateDerivative(map_expr_dag(self, o_[0],
-                                                 vcache=self.vcaches[key],
-                                                 rcache=self.rcaches[key]),
-                                    o_[1], o_[2], o_[3])
+        return CoordinateDerivative(
+            map_expr_dag(self, o_[0], vcache=self.vcaches[key], rcache=self.rcaches[key]),
+            o_[1],
+            o_[2],
+            o_[3],
+        )
 
     def base_form_coordinate_derivative(self, o, f, dummy_w, dummy_v, dummy_cd):
         """Apply to a base_form_coordinate_derivative."""
         o_ = o.ufl_operands
         key = (BaseFormCoordinateDerivative, o_[0])
-        return BaseFormCoordinateDerivative(map_expr_dag(self, o_[0],
-                                                         vcache=self.vcaches[key],
-                                                         rcache=self.rcaches[key]),
-                                            o_[1], o_[2], o_[3])
+        return BaseFormCoordinateDerivative(
+            map_expr_dag(self, o_[0], vcache=self.vcaches[key], rcache=self.rcaches[key]),
+            o_[1],
+            o_[2],
+            o_[3],
+        )
 
     def indexed(self, o, Ap, ii):  # TODO: (Partially) duplicated in generic rules
         """Apply to an indexed."""
@@ -1389,15 +1479,18 @@ def indexed(self, o, Ap, ii):  # TODO: (Partially) duplicated in generic rules
         return op
 
 
-class BaseFormOperatorDerivativeRecorder():
+class BaseFormOperatorDerivativeRecorder:
     """A derivative recorded for a base form operator."""
 
     def __init__(self, expression, var, **kwargs):
         """Initialise."""
         base_form_ops = kwargs.pop("base_form_ops", ())
 
-        if kwargs.keys() != {'arguments', 'coefficient_derivatives'}:
-            raise ValueError("Only `arguments` and `coefficient_derivatives` are allowed as derivative arguments.")
+        if kwargs.keys() != {"arguments", "coefficient_derivatives"}:
+            raise ValueError(
+                "Only `arguments` and `coefficient_derivatives` are "
+                "allowed as derivative arguments."
+            )
 
         self.expression = expression
         self.var = var
@@ -1418,18 +1511,23 @@ def __add__(self, other):
             base_form_ops = self.base_form_ops + other
         elif isinstance(other, BaseFormOperatorDerivativeRecorder):
             if self.der_kwargs != other.der_kwargs:
-                raise ValueError(f"Derivative arguments must match when summing {type(self).__name__} objects.")
+                raise ValueError(
+                    f"Derivative arguments must match when summing {type(self).__name__} objects."
+                )
             base_form_ops = self.base_form_ops + other.base_form_ops
         else:
-            raise NotImplementedError(f"Sum of {type(self)} and {type(other)} objects is not supported.")
+            raise NotImplementedError(
+                f"Sum of {type(self)} and {type(other)} objects is not supported."
+            )
 
-        return BaseFormOperatorDerivativeRecorder(self.expression, self.var,
-                                                  base_form_ops=base_form_ops,
-                                                  **self.der_kwargs)
+        return BaseFormOperatorDerivativeRecorder(
+            self.expression, self.var, base_form_ops=base_form_ops, **self.der_kwargs
+        )
 
     def __radd__(self, other):
         """Add."""
-        # Recording order doesn't matter as collected `BaseFormOperator`s are sorted later on.
+        # Recording order doesn't matter as collected
+        # `BaseFormOperator`s are sorted later on.
         return self.__add__(other)
 
     def __iadd__(self, other):
@@ -1457,8 +1555,10 @@ def apply_derivatives(expression):
     rules = DerivativeRuleDispatcher()
 
     # If we hit a base form operator (bfo), then if `var` is:
-    #    - a BaseFormOperator → Return `d(expression)/dw` where `w` is the coefficient produced by the bfo `var`.
-    #    - else → Record the bfo on the MultiFunction object and returns 0.
+    #    - a BaseFormOperator → Return `d(expression)/dw` where `w` is
+    #      the coefficient produced by the bfo `var`.
+    #    - else → Record the bfo on the MultiFunction object and returns
+    #    - 0.
     # Example:
     #    → If derivative(F(u, N(u); v), u) was taken the following line would compute `∂F/∂u`.
     dexpression_dvar = map_integrand_dags(rules, expression)
@@ -1474,29 +1574,40 @@ def apply_derivatives(expression):
     else:
         dexpression_dvar = ()
 
-    # Retrieve the base form operators, var, and the argument and coefficient_derivatives for `derivative`
+    # Retrieve the base form operators, var, and the argument and
+    # coefficient_derivatives for `derivative`
     var = pending_operations.var
     base_form_ops = pending_operations.base_form_ops
     der_kwargs = pending_operations.der_kwargs
     for N in sorted(set(base_form_ops), key=lambda x: x.count()):
         # -- Replace dexpr/dvar by dexpr/dN -- #
-        # We don't use `apply_derivatives` since the differentiation is done via `\partial` and not `d`.
-        dexpr_dN = map_integrand_dags(rules, replace_derivative_nodes(expression, {var.ufl_operands[0]: N}))
+        # We don't use `apply_derivatives` since the differentiation is
+        # done via `\partial` and not `d`.
+        dexpr_dN = map_integrand_dags(
+            rules, replace_derivative_nodes(expression, {var.ufl_operands[0]: N})
+        )
         # -- Add the BaseFormOperatorDerivative node -- #
-        var_arg, = der_kwargs['arguments'].ufl_operands
-        cd = der_kwargs['coefficient_derivatives']
-        # Not always the case since `derivative`'s syntax enables one to use a Coefficient as the Gateaux direction
+        (var_arg,) = der_kwargs["arguments"].ufl_operands
+        cd = der_kwargs["coefficient_derivatives"]
+        # Not always the case since `derivative`'s syntax enables one to
+        # use a Coefficient as the Gateaux direction
         if isinstance(var_arg, BaseArgument):
-            # Construct the argument number based on the BaseFormOperator arguments instead of naively
-            # using `var_arg`. This is critical when BaseFormOperators are used inside 0-forms.
+            # Construct the argument number based on the
+            # BaseFormOperator arguments instead of naively using
+            # `var_arg`. This is critical when BaseFormOperators are
+            # used inside 0-forms.
             #
             # Example: F = 0.5 * u** 2 * dx + 0.5 * N(u; v*)** 2 * dx
             #    -> dFdu[vhat] = <u, vhat> + Action(<N(u; v*), v0>, dNdu(u; v1, v*))
-            # with `vhat` a 0-numbered argument, and where `v1` and `vhat` have the same function space but
-            # a different number. Here, applying `vhat` (`var_arg`) naively would result in `dNdu(u; vhat, v*)`,
-            # i.e. the 2-forms `dNdu` would have two 0-numbered arguments. Instead we increment the argument number
-            # of `vhat` to form `v1`.
-            var_arg = type(var_arg)(var_arg.ufl_function_space(), number=len(N.arguments()), part=var_arg.part())
+            # with `vhat` a 0-numbered argument, and where `v1` and
+            # `vhat` have the same function space but a different
+            # number. Here, applying `vhat` (`var_arg`) naively would
+            # result in `dNdu(u; vhat, v*)`, i.e. the 2-forms `dNdu`
+            # would have two 0-numbered arguments. Instead we increment
+            # the argument number of `vhat` to form `v1`.
+            var_arg = type(var_arg)(
+                var_arg.ufl_function_space(), number=len(N.arguments()), part=var_arg.part()
+            )
         dN_dvar = apply_derivatives(BaseFormOperatorDerivative(N, var, ExprList(var_arg), cd))
         # -- Sum the Action: dF/du = ∂F/∂u + \sum_{i=1,...} Action(∂F/∂Ni, dNi/du) -- #
         if not (isinstance(dexpr_dN, Form) and len(dexpr_dN.integrals()) == 0):
@@ -1545,7 +1656,9 @@ def __init__(self, coefficients, arguments, coefficient_derivatives):
 
     def coefficient(self, o):
         """Differentiate a coefficient."""
-        raise NotImplementedError("CoordinateDerivative of coefficient in physical space is not implemented.")
+        raise NotImplementedError(
+            "CoordinateDerivative of coefficient in physical space is not implemented."
+        )
 
     def grad(self, o):
         """Differentiate a grad."""
@@ -1558,8 +1671,10 @@ def spatial_coordinate(self, o):
         if do is not None:
             return do
         else:
-            raise NotImplementedError("CoordinateDerivative found a SpatialCoordinate that is different "
-                                      "from the one being differentiated.")
+            raise NotImplementedError(
+                "CoordinateDerivative found a SpatialCoordinate that is different "
+                "from the one being differentiated."
+            )
 
     def reference_value(self, o):
         """Differentiate a reference_value."""
@@ -1575,7 +1690,7 @@ def reference_grad(self, g):
         o = g
         ngrads = 0
         while isinstance(o, ReferenceGrad):
-            o, = o.ufl_operands
+            (o,) = o.ufl_operands
             ngrads += 1
         if not (isinstance(o, SpatialCoordinate) or isinstance(o.ufl_operands[0], FormArgument)):
             raise ValueError(f"Expecting gradient of a FormArgument, not {ufl_err_str(o)}")
@@ -1587,8 +1702,12 @@ def apply_grads(f):
 
         # Find o among all w without any indexing, which makes this
         # easy
-        for (w, v) in zip(self._w, self._v):
-            if o == w and isinstance(v, ReferenceValue) and isinstance(v.ufl_operands[0], FormArgument):
+        for w, v in zip(self._w, self._v):
+            if (
+                o == w
+                and isinstance(v, ReferenceValue)
+                and isinstance(v.ufl_operands[0], FormArgument)
+            ):
                 # Case: d/dt [w + t v]
                 return apply_grads(v)
         return self.independent_terminal(o)
@@ -1596,8 +1715,10 @@ def apply_grads(f):
     def jacobian(self, o):
         """Differentiate a jacobian."""
         # d (grad_X(x))/d x => grad_X(Argument(x.function_space())
-        for (w, v) in zip(self._w, self._v):
-            if extract_unique_domain(o) == extract_unique_domain(w) and isinstance(v.ufl_operands[0], FormArgument):
+        for w, v in zip(self._w, self._v):
+            if extract_unique_domain(o) == extract_unique_domain(w) and isinstance(
+                v.ufl_operands[0], FormArgument
+            ):
                 return ReferenceGrad(v)
         return self.independent_terminal(o)
 
@@ -1636,10 +1757,12 @@ def coefficient_derivative(self, o):
     def coordinate_derivative(self, o, f, w, v, cd):
         """Apply to a coordinate_derivative."""
         from ufl.algorithms import extract_unique_elements
+
         for space in extract_unique_elements(o):
             if isinstance(space.pullback, CustomPullback):
                 raise NotImplementedError(
-                    "CoordinateDerivative is not supported for elements with custom pull back.")
+                    "CoordinateDerivative is not supported for elements with custom pull back."
+                )
 
         _, w, v, cd = o.ufl_operands
         rules = CoordinateDerivativeRuleset(w, v, cd)
diff --git a/ufl/algorithms/apply_function_pullbacks.py b/ufl/algorithms/apply_function_pullbacks.py
index 44b0e86ba..124c2a2dd 100644
--- a/ufl/algorithms/apply_function_pullbacks.py
+++ b/ufl/algorithms/apply_function_pullbacks.py
@@ -1,4 +1,4 @@
-"""Algorithm for replacing gradients in an expression with reference gradients and coordinate mappings."""
+"""Algorithm for replacing gradients in an expression."""
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
@@ -35,12 +35,15 @@ def form_argument(self, o):
 
         if r.ufl_shape != element.reference_value_shape:
             raise ValueError(
-                f"Expecting reference space expression with shape '{element.reference_value_shape}', "
-                f"got '{r.ufl_shape}'")
+                "Expecting reference space expression with shape "
+                f"'{element.reference_value_shape}', got '{r.ufl_shape}'"
+            )
         f = element.pullback.apply(r)
         if f.ufl_shape != space.value_shape:
-            raise ValueError(f"Expecting pulled back expression with shape '{space.value_shape}', "
-                             f"got '{f.ufl_shape}'")
+            raise ValueError(
+                f"Expecting pulled back expression with shape '{space.value_shape}', "
+                f"got '{f.ufl_shape}'"
+            )
 
         assert f.ufl_shape == o.ufl_shape
         return f
diff --git a/ufl/algorithms/apply_geometry_lowering.py b/ufl/algorithms/apply_geometry_lowering.py
index c1a39d863..4ef00c1c1 100644
--- a/ufl/algorithms/apply_geometry_lowering.py
+++ b/ufl/algorithms/apply_geometry_lowering.py
@@ -14,10 +14,31 @@
 from functools import reduce
 from itertools import combinations
 
-from ufl.classes import (CellCoordinate, CellEdgeVectors, CellFacetJacobian, CellOrientation, CellOrigin, CellVertices,
-                         CellVolume, Expr, FacetEdgeVectors, FacetJacobian, FacetJacobianDeterminant, FloatValue, Form,
-                         Integral, Jacobian, JacobianDeterminant, JacobianInverse, MaxCellEdgeLength,
-                         ReferenceCellVolume, ReferenceFacetVolume, ReferenceGrad, ReferenceNormal, SpatialCoordinate)
+from ufl.classes import (
+    CellCoordinate,
+    CellEdgeVectors,
+    CellFacetJacobian,
+    CellOrientation,
+    CellOrigin,
+    CellVertices,
+    CellVolume,
+    Expr,
+    FacetEdgeVectors,
+    FacetJacobian,
+    FacetJacobianDeterminant,
+    FloatValue,
+    Form,
+    Integral,
+    Jacobian,
+    JacobianDeterminant,
+    JacobianInverse,
+    MaxCellEdgeLength,
+    ReferenceCellVolume,
+    ReferenceFacetVolume,
+    ReferenceGrad,
+    ReferenceNormal,
+    SpatialCoordinate,
+)
 from ufl.compound_expressions import cross_expr, determinant_expr, inverse_expr
 from ufl.core.multiindex import Index, indices
 from ufl.corealg.map_dag import map_expr_dag
@@ -30,6 +51,7 @@
 
 class GeometryLoweringApplier(MultiFunction):
     """Geometry lowering."""
+
     def __init__(self, preserve_types=()):
         """Initialise."""
         MultiFunction.__init__(self)
@@ -180,8 +202,10 @@ def facet_cell_coordinate(self, o):
         if self._preserve_types[o._ufl_typecode_]:
             return o
 
-        raise ValueError("Missing computation of facet reference coordinates "
-                         "from physical coordinates via mappings.")
+        raise ValueError(
+            "Missing computation of facet reference coordinates "
+            "from physical coordinates via mappings."
+        )
 
     @memoized_handler
     def cell_volume(self, o):
@@ -256,7 +280,7 @@ def circumradius(self, o):
             lb = elen[4] * elen[1]
             lc = elen[5] * elen[0]
             # p = perimeter
-            p = (la + lb + lc)
+            p = la + lb + lc
             # s = semiperimeter
             s = p / 2
             # area of intermediate triangle with Herons formula
@@ -431,7 +455,9 @@ def facet_normal(self, o):
             r = n
 
         if r.ufl_shape != o.ufl_shape:
-            raise ValueError(f"Inconsistent dimensions (in={o.ufl_shape[0]}, out={r.ufl_shape[0]}).")
+            raise ValueError(
+                f"Inconsistent dimensions (in={o.ufl_shape[0]}, out={r.ufl_shape[0]})."
+            )
         return r
 
 
@@ -445,8 +471,9 @@ def apply_geometry_lowering(form, preserve_types=()):
         preserve_types: Preserved types
     """
     if isinstance(form, Form):
-        newintegrals = [apply_geometry_lowering(integral, preserve_types)
-                        for integral in form.integrals()]
+        newintegrals = [
+            apply_geometry_lowering(integral, preserve_types) for integral in form.integrals()
+        ]
         return Form(newintegrals)
 
     elif isinstance(form, Integral):
diff --git a/ufl/algorithms/apply_integral_scaling.py b/ufl/algorithms/apply_integral_scaling.py
index 7e5e35ff2..81c6252a1 100644
--- a/ufl/algorithms/apply_integral_scaling.py
+++ b/ufl/algorithms/apply_integral_scaling.py
@@ -1,4 +1,4 @@
-"""Algorithm for replacing gradients in an expression with reference gradients and coordinate mappings."""
+"""Algorithm for replacing gradients in an expression."""
 
 # Copyright (C) 2013-2016 Martin Sandve Alnæs
 #
@@ -8,7 +8,13 @@
 
 from ufl.algorithms.apply_geometry_lowering import apply_geometry_lowering
 from ufl.algorithms.estimate_degrees import estimate_total_polynomial_degree
-from ufl.classes import FacetJacobianDeterminant, Form, Integral, JacobianDeterminant, QuadratureWeight
+from ufl.classes import (
+    FacetJacobianDeterminant,
+    Form,
+    Integral,
+    JacobianDeterminant,
+    QuadratureWeight,
+)
 from ufl.differentiation import CoordinateDerivative
 from ufl.measure import custom_integral_types, point_integral_types
 
@@ -52,7 +58,7 @@ def compute_integrand_scaling_factor(integral):
             # side and quadrature weight
             detFJ = FacetJacobianDeterminant(domain)
             degree = estimate_total_polynomial_degree(apply_geometry_lowering(detFJ))
-            scale = detFJ('+') * weight
+            scale = detFJ("+") * weight
         else:
             # No need to scale 'integral' over a vertex
             scale = 1
@@ -77,8 +83,7 @@ def apply_integral_scaling(form):
     # TODO: Consider adding an in_reference_frame property to Integral
     #       and checking it here and setting it in the returned form
     if isinstance(form, Form):
-        newintegrals = [apply_integral_scaling(integral)
-                        for integral in form.integrals()]
+        newintegrals = [apply_integral_scaling(integral) for integral in form.integrals()]
         return Form(newintegrals)
 
     elif isinstance(form, Integral):
@@ -107,9 +112,12 @@ def scale_coordinate_derivative(o, scale):
             """Scale the coordinate derivative."""
             o_ = o.ufl_operands
             if isinstance(o, CoordinateDerivative):
-                return CoordinateDerivative(scale_coordinate_derivative(o_[0], scale), o_[1], o_[2], o_[3])
+                return CoordinateDerivative(
+                    scale_coordinate_derivative(o_[0], scale), o_[1], o_[2], o_[3]
+                )
             else:
                 return scale * o
+
         newintegrand = scale_coordinate_derivative(integrand, scale)
         return integral.reconstruct(integrand=newintegrand, metadata=md)
 
diff --git a/ufl/algorithms/apply_restrictions.py b/ufl/algorithms/apply_restrictions.py
index 8f788a009..b8c049ab7 100644
--- a/ufl/algorithms/apply_restrictions.py
+++ b/ufl/algorithms/apply_restrictions.py
@@ -1,7 +1,7 @@
 """Apply restrictions.
 
-This module contains the apply_restrictions algorithm which propagates restrictions in a form
-towards the terminals.
+This module contains the apply_restrictions algorithm which propagates
+restrictions in a form towards the terminals.
 """
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
@@ -32,8 +32,7 @@ def __init__(self, side=None):
         self.vcaches = {"+": {}, "-": {}}
         self.rcaches = {"+": {}, "-": {}}
         if self.current_restriction is None:
-            self._rp = {"+": RestrictionPropagator("+"),
-                        "-": RestrictionPropagator("-")}
+            self._rp = {"+": RestrictionPropagator("+"), "-": RestrictionPropagator("-")}
 
     def restricted(self, o):
         """When hitting a restricted quantity, visit child with a separate restriction algorithm."""
@@ -43,14 +42,18 @@ def restricted(self, o):
             raise ValueError("Cannot restrict an expression twice.")
         # Configure a propagator for this side and apply to subtree
         side = o.side()
-        return map_expr_dag(self._rp[side], o.ufl_operands[0],
-                            vcache=self.vcaches[side],
-                            rcache=self.rcaches[side])
+        return map_expr_dag(
+            self._rp[side], o.ufl_operands[0], vcache=self.vcaches[side], rcache=self.rcaches[side]
+        )
 
     # --- Reusable rules
 
     def _ignore_restriction(self, o):
-        """Ignore current restriction, quantity is independent of side also from a computational point of view."""
+        """Ignore current restriction.
+
+        Quantity is independent of side also from a computational point
+        of view.
+        """
         return o
 
     def _require_restriction(self, o):
@@ -99,7 +102,7 @@ def variable(self, o, op, label):
 
     def reference_value(self, o):
         """Reference value of something follows same restriction rule as the underlying object."""
-        f, = o.ufl_operands
+        (f,) = o.ufl_operands
         assert f._ufl_is_terminal_
         g = self(f)
         if isinstance(g, Restricted):
@@ -140,8 +143,8 @@ def reference_value(self, o):
     def coefficient(self, o):
         """Restrict a coefficient.
 
-        Allow coefficients to be unrestricted (apply default if so) if the values are fully continuous
-        across the facet.
+        Allow coefficients to be unrestricted (apply default if so) if
+        the values are fully continuous across the facet.
         """
         if o.ufl_element() in H1:
             # If the coefficient _value_ is _fully_ continuous
@@ -174,11 +177,11 @@ def facet_normal(self, o):
 
 def apply_restrictions(expression):
     """Propagate restriction nodes to wrap differential terminals directly."""
-    integral_types = [k for k in integral_type_to_measure_name.keys()
-                      if k.startswith("interior_facet")]
+    integral_types = [
+        k for k in integral_type_to_measure_name.keys() if k.startswith("interior_facet")
+    ]
     rules = RestrictionPropagator()
-    return map_integrand_dags(rules, expression,
-                              only_integral_type=integral_types)
+    return map_integrand_dags(rules, expression, only_integral_type=integral_types)
 
 
 class DefaultRestrictionApplier(MultiFunction):
@@ -190,8 +193,7 @@ def __init__(self, side=None):
         self.current_restriction = side
         self.default_restriction = "+"
         if self.current_restriction is None:
-            self._rp = {"+": DefaultRestrictionApplier("+"),
-                        "-": DefaultRestrictionApplier("-")}
+            self._rp = {"+": DefaultRestrictionApplier("+"), "-": DefaultRestrictionApplier("-")}
 
     def terminal(self, o):
         """Apply to terminal."""
@@ -241,8 +243,8 @@ def apply_default_restrictions(expression):
 
     This applies a default restriction to such terminals if unrestricted.
     """
-    integral_types = [k for k in integral_type_to_measure_name.keys()
-                      if k.startswith("interior_facet")]
+    integral_types = [
+        k for k in integral_type_to_measure_name.keys() if k.startswith("interior_facet")
+    ]
     rules = DefaultRestrictionApplier()
-    return map_integrand_dags(rules, expression,
-                              only_integral_type=integral_types)
+    return map_integrand_dags(rules, expression, only_integral_type=integral_types)
diff --git a/ufl/algorithms/balancing.py b/ufl/algorithms/balancing.py
index 477ec3f6f..e671d01d0 100644
--- a/ufl/algorithms/balancing.py
+++ b/ufl/algorithms/balancing.py
@@ -6,20 +6,31 @@
 #
 # SPDX-License-Identifier:    LGPL-3.0-or-later
 
-from ufl.classes import (CellAvg, FacetAvg, Grad, Indexed, NegativeRestricted, PositiveRestricted, ReferenceGrad,
-                         ReferenceValue)
+from ufl.classes import (
+    CellAvg,
+    FacetAvg,
+    Grad,
+    Indexed,
+    NegativeRestricted,
+    PositiveRestricted,
+    ReferenceGrad,
+    ReferenceValue,
+)
 from ufl.corealg.map_dag import map_expr_dag
 from ufl.corealg.multifunction import MultiFunction
 
 modifier_precedence = [
-    ReferenceValue, ReferenceGrad, Grad, CellAvg, FacetAvg, PositiveRestricted,
-    NegativeRestricted, Indexed
+    ReferenceValue,
+    ReferenceGrad,
+    Grad,
+    CellAvg,
+    FacetAvg,
+    PositiveRestricted,
+    NegativeRestricted,
+    Indexed,
 ]
 
-modifier_precedence = {
-    m._ufl_handler_name_: i
-    for i, m in enumerate(modifier_precedence)
-}
+modifier_precedence = {m._ufl_handler_name_: i for i, m in enumerate(modifier_precedence)}
 
 
 def balance_modified_terminal(expr):
@@ -44,10 +55,9 @@ def balance_modified_terminal(expr):
     assert expr._ufl_is_terminal_
 
     # Apply modifiers in order
-    layers = sorted(
-        layers[:-1], key=lambda e: modifier_precedence[e._ufl_handler_name_])
+    layers = sorted(layers[:-1], key=lambda e: modifier_precedence[e._ufl_handler_name_])
     for op in layers:
-        ops = (expr, ) + op.ufl_operands[1:]
+        ops = (expr,) + op.ufl_operands[1:]
         expr = op._ufl_expr_reconstruct_(*ops)
 
     # Preserve id if nothing has changed
diff --git a/ufl/algorithms/change_to_reference.py b/ufl/algorithms/change_to_reference.py
index ed5c22ca2..17b106ad7 100644
--- a/ufl/algorithms/change_to_reference.py
+++ b/ufl/algorithms/change_to_reference.py
@@ -1,4 +1,4 @@
-"""Algorithm for replacing gradients in an expression with reference gradients and coordinate mappings."""
+"""Algorithm for replacing gradients in an expression."""
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
@@ -18,14 +18,17 @@
 
 """
 # Some notes:
-# Below, let v_i mean physical coordinate of vertex i and V_i mean the reference cell coordinate of the same vertex.
+# Below, let v_i mean physical coordinate of vertex i and V_i mean the
+reference cell coordinate of the same vertex.
 
 
-# Add a type for CellVertices? Note that vertices must be computed in linear cell cases!
-triangle_vertices[i,j] = component j of vertex i, following ufc numbering conventions
+# Add a type for CellVertices? Note that vertices must be computed in
+linear cell cases! triangle_vertices[i,j] = component j of vertex i,
+following ufc numbering conventions
 
 
-# DONE Add a type for CellEdgeLengths? Note that these are only easy to define in the linear cell case!
+# DONE Add a type for CellEdgeLengths? Note that these are only easy to
+define in the linear cell case!
 triangle_edge_lengths    = [v1v2, v0v2, v0v1] # shape (3,)
 tetrahedron_edge_lengths = [v0v1, v0v2, v0v3, v1v2, v1v3, v2v3] # shape (6,)
 
@@ -33,7 +36,8 @@
 # DONE Here's how to compute edge lengths from the Jacobian:
 J =[ [dx0/dX0, dx0/dX1],
      [dx1/dX0, dx1/dX1] ]
-# First compute the edge vector, which is constant for each edge: the vector from one vertex to the other
+# First compute the edge vector, which is constant for each edge: the
+vector from one vertex to the other
 reference_edge_vector_0 = V2 - V1 # Example! Add a type ReferenceEdgeVectors?
 # Then apply J to it and take the length of the resulting vector, this is generic for affine cells
 edge_length_i = || dot(J, reference_edge_vector_i) ||
@@ -121,18 +125,18 @@ def grad(self, o):
         # Peel off the Grads and count them, and get restriction if
         # it's between the grad and the terminal
         ngrads = 0
-        restricted = ''
+        restricted = ""
         rv = False
         while not o._ufl_is_terminal_:
             if isinstance(o, Grad):
-                o, = o.ufl_operands
+                (o,) = o.ufl_operands
                 ngrads += 1
             elif isinstance(o, Restricted):
                 restricted = o.side()
-                o, = o.ufl_operands
+                (o,) = o.ufl_operands
             elif isinstance(o, ReferenceValue):
                 rv = True
-                o, = o.ufl_operands
+                (o,) = o.ufl_operands
             else:
                 raise ValueError(f"Invalid type {o._ufl_class_.__name__}")
         f = o
@@ -150,7 +154,9 @@ def grad(self, o):
 
             # Create some new indices
             ii = indices(len(f.ufl_shape))  # Indices to get to the scalar component of f
-            jj = indices(ngrads)  # Indices to sum over the local gradient axes with the inverse Jacobian
+            jj = indices(
+                ngrads
+            )  # Indices to sum over the local gradient axes with the inverse Jacobian
             kk = indices(ngrads)  # Indices for the leftover inverse Jacobian axes
 
             # Preserve restricted property
@@ -182,7 +188,9 @@ def grad(self, o):
 
             jinv_lgrad_f = f
             for foo in range(ngrads):
-                ii = indices(len(jinv_lgrad_f.ufl_shape))  # Indices to get to the scalar component of f
+                ii = indices(
+                    len(jinv_lgrad_f.ufl_shape)
+                )  # Indices to get to the scalar component of f
                 j, k = indices(2)
 
                 lgrad = ReferenceGrad(jinv_lgrad_f)
@@ -199,13 +207,16 @@ def reference_grad(self, o):
 
     def coefficient_derivative(self, o):
         """Apply to coefficient_derivative."""
-        raise ValueError("Coefficient derivatives should be expanded before applying change to reference grad.")
+        raise ValueError(
+            "Coefficient derivatives should be expanded before applying change to reference grad."
+        )
 
 
 def change_to_reference_grad(e):
     """Change Grad objects in expression to products of JacobianInverse and ReferenceGrad.
 
-    Assumes the expression is preprocessed or at least that derivatives have been expanded.
+    Assumes the expression is preprocessed or at least that derivatives
+    have been expanded.
 
     Args:
         e: An Expr or Form.
diff --git a/ufl/algorithms/check_arities.py b/ufl/algorithms/check_arities.py
index c93727ad8..12a7e53c1 100644
--- a/ufl/algorithms/check_arities.py
+++ b/ufl/algorithms/check_arities.py
@@ -9,6 +9,7 @@
 
 class ArityMismatch(BaseException):
     """Arity mismatch exception."""
+
     pass
 
 
@@ -41,8 +42,10 @@ def nonlinear_operator(self, o):
         # way we know of:
         for t in traverse_unique_terminals(o):
             if t._ufl_typecode_ == Argument._ufl_typecode_:
-                raise ArityMismatch(f"Applying nonlinear operator {o._ufl_class_.__name__} to "
-                                    f"expression depending on form argument {t}.")
+                raise ArityMismatch(
+                    f"Applying nonlinear operator {o._ufl_class_.__name__} to "
+                    f"expression depending on form argument {t}."
+                )
         return self._et
 
     expr = nonlinear_operator
@@ -50,7 +53,9 @@ def nonlinear_operator(self, o):
     def sum(self, o, a, b):
         """Apply to sum."""
         if a != b:
-            raise ArityMismatch(f"Adding expressions with non-matching form arguments {_afmt(a)} vs {_afmt(b)}.")
+            raise ArityMismatch(
+                f"Adding expressions with non-matching form arguments {_afmt(a)} vs {_afmt(b)}."
+            )
         return a
 
     def division(self, o, a, b):
@@ -67,15 +72,19 @@ def product(self, o, a, b):
             anumbers = set(x[0].number() for x in a)
             for x in b:
                 if x[0].number() in anumbers:
-                    raise ArityMismatch("Multiplying expressions with overlapping form argument number "
-                                        f"{x[0].number()}, argument is {_afmt(x)}.")
+                    raise ArityMismatch(
+                        "Multiplying expressions with overlapping form argument number "
+                        f"{x[0].number()}, argument is {_afmt(x)}."
+                    )
             # Combine argument lists
             c = tuple(sorted(set(a + b), key=lambda x: (x[0].number(), x[0].part())))
             # Check that we don't have any arguments shared between a
             # and b
             if len(c) != len(a) + len(b) or len(c) != len({x[0] for x in c}):
-                raise ArityMismatch("Multiplying expressions with overlapping form arguments "
-                                    f"{_afmt(a)} vs {_afmt(b)}.")
+                raise ArityMismatch(
+                    "Multiplying expressions with overlapping form arguments "
+                    f"{_afmt(a)} vs {_afmt(b)}."
+                )
             # It's fine for argument parts to overlap
             return c
         elif a:
@@ -139,8 +148,10 @@ def conditional(self, o, c, a, b):
         else:
             # Do not allow e.g. conditional(c, test, trial),
             # conditional(c, test, nonzeroconstant)
-            raise ArityMismatch("Conditional subexpressions with non-matching form arguments "
-                                f"{_afmt(a)} vs {_afmt(b)}.")
+            raise ArityMismatch(
+                "Conditional subexpressions with non-matching form arguments "
+                f"{_afmt(a)} vs {_afmt(b)}."
+            )
 
     def linear_indexed_type(self, o, a, i):
         """Apply to linear_indexed_type."""
@@ -161,8 +172,10 @@ def list_tensor(self, o, *ops):
             if () in numbers:  # Allow e.g. <v[0], 0, v[1]> but not <v[0], u[0]>
                 numbers.remove(())
             if len(numbers) > 1:
-                raise ArityMismatch("Listtensor components must depend on the same argument numbers, "
-                                    f"found {numbers}.")
+                raise ArityMismatch(
+                    "Listtensor components must depend on the same argument numbers, "
+                    f"found {numbers}."
+                )
 
             # Allow different parts with the same number
             return tuple(sorted(args, key=lambda x: (x[0].number(), x[0].part())))
@@ -173,8 +186,7 @@ def list_tensor(self, o, *ops):
 
 def check_integrand_arity(expr, arguments, complex_mode=False):
     """Check the arity of an integrand."""
-    arguments = tuple(sorted(set(arguments),
-                             key=lambda x: (x.number(), x.part())))
+    arguments = tuple(sorted(set(arguments), key=lambda x: (x.number(), x.part())))
     rules = ArityChecker(arguments)
     arg_tuples = map_expr_dag(rules, expr, compress=False)
     args = tuple(a[0] for a in arg_tuples)
diff --git a/ufl/algorithms/check_restrictions.py b/ufl/algorithms/check_restrictions.py
index df75e279e..061935981 100644
--- a/ufl/algorithms/check_restrictions.py
+++ b/ufl/algorithms/check_restrictions.py
@@ -28,7 +28,7 @@ def restricted(self, o):
         if self.current_restriction is not None:
             raise ValueError("Not expecting twice restricted expression.")
         self.current_restriction = o._side
-        e, = o.ufl_operands
+        (e,) = o.ufl_operands
         self.visit(e)
         self.current_restriction = None
 
diff --git a/ufl/algorithms/checks.py b/ufl/algorithms/checks.py
index 9257b160d..a25ba9ec5 100644
--- a/ufl/algorithms/checks.py
+++ b/ufl/algorithms/checks.py
@@ -10,11 +10,13 @@
 # Modified by Mehdi Nikbakht, 2010.
 
 from ufl.algorithms.check_restrictions import check_restrictions
+
 # UFL algorithms
 from ufl.algorithms.traversal import iter_expressions
 from ufl.argument import Argument
 from ufl.coefficient import Coefficient
 from ufl.constantvalue import is_true_ufl_scalar
+
 # UFL classes
 from ufl.core.expr import ufl_err_str
 from ufl.corealg.traversal import traverse_unique_terminals
@@ -22,7 +24,9 @@
 from ufl.form import Form
 
 
-def validate_form(form):  # TODO: Can we make this return a list of errors instead of raising exception?
+def validate_form(
+    form,
+):  # TODO: Can we make this return a list of errors instead of raising exception?
     """Performs all implemented validations on a form. Raises exception if something fails."""
     errors = []
 
@@ -37,9 +41,11 @@ def validate_form(form):  # TODO: Can we make this return a list of errors inste
     #     errors.append("Form is not multilinear in arguments.")
 
     # FIXME DOMAIN: Add check for consistency between domains somehow
-    domains = set(extract_unique_domain(t)
-                  for e in iter_expressions(form)
-                  for t in traverse_unique_terminals(e)) - {None}
+    domains = set(
+        extract_unique_domain(t)
+        for e in iter_expressions(form)
+        for t in traverse_unique_terminals(e)
+    ) - {None}
     if not domains:
         errors.append("Missing domain definition in form.")
 
@@ -61,8 +67,7 @@ def validate_form(form):  # TODO: Can we make this return a list of errors inste
                 if c in coefficients:
                     g = coefficients[c]
                     if f is not g:
-                        errors.append("Found different Coefficients with "
-                                      f"same count: {f} and {g}.")
+                        errors.append(f"Found different Coefficients with same count: {f} and {g}.")
                 else:
                     coefficients[c] = f
 
@@ -101,4 +106,4 @@ def validate_form(form):  # TODO: Can we make this return a list of errors inste
     # TODO: Return errors list instead, need to collect messages from
     # all validations above first.
     if errors:
-        raise ValueError("Found errors in validation of form:\n" + '\n\n'.join(errors))
+        raise ValueError("Found errors in validation of form:\n" + "\n\n".join(errors))
diff --git a/ufl/algorithms/comparison_checker.py b/ufl/algorithms/comparison_checker.py
index e61aeecf3..509287e74 100644
--- a/ufl/algorithms/comparison_checker.py
+++ b/ufl/algorithms/comparison_checker.py
@@ -83,19 +83,19 @@ def min_value(self, o, *ops):
     def real(self, o, *ops):
         """Apply to real."""
         o = self.reuse_if_untouched(o, *ops)
-        self.nodetype[o] = 'real'
+        self.nodetype[o] = "real"
         return o
 
     def imag(self, o, *ops):
         """Apply to imag."""
         o = self.reuse_if_untouched(o, *ops)
-        self.nodetype[o] = 'real'
+        self.nodetype[o] = "real"
         return o
 
     def sqrt(self, o, *ops):
         """Apply to sqrt."""
         o = self.reuse_if_untouched(o, *ops)
-        self.nodetype[o] = 'complex'
+        self.nodetype[o] = "complex"
         return o
 
     def power(self, o, base, exponent):
@@ -104,28 +104,28 @@ def power(self, o, base, exponent):
         try:
             # Attempt to diagnose circumstances in which the result must be real.
             exponent = float(exponent)
-            if self.nodetype[base] == 'real' and int(exponent) == exponent:
-                self.nodetype[o] = 'real'
+            if self.nodetype[base] == "real" and int(exponent) == exponent:
+                self.nodetype[o] = "real"
                 return o
         except TypeError:
             pass
 
-        self.nodetype[o] = 'complex'
+        self.nodetype[o] = "complex"
         return o
 
     def abs(self, o, *ops):
         """Apply to abs."""
         o = self.reuse_if_untouched(o, *ops)
-        self.nodetype[o] = 'real'
+        self.nodetype[o] = "real"
         return o
 
     def terminal(self, term, *ops):
         """Apply to terminal."""
         # default terminals to complex, except the ones we *know* are real
         if isinstance(term, (RealValue, Zero, Argument, GeometricQuantity)):
-            self.nodetype[term] = 'real'
+            self.nodetype[term] = "real"
         else:
-            self.nodetype[term] = 'complex'
+            self.nodetype[term] = "complex"
         return term
 
     def indexed(self, o, expr, multiindex):
diff --git a/ufl/algorithms/compute_form_data.py b/ufl/algorithms/compute_form_data.py
index af0ddf68d..687e8edc4 100644
--- a/ufl/algorithms/compute_form_data.py
+++ b/ufl/algorithms/compute_form_data.py
@@ -1,7 +1,7 @@
 """This module provides the compute_form_data function.
 
-Form compilers will typically call compute_form_dataprior to code generation to preprocess/simplify a
-raw input form given by a user.
+Form compilers will typically call compute_form_dataprior to code
+generation to preprocess/simplify a raw input form given by a user.
 """
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
@@ -14,6 +14,7 @@
 from ufl.algorithms.analysis import extract_coefficients, extract_sub_elements, unique_tuple
 from ufl.algorithms.apply_algebra_lowering import apply_algebra_lowering
 from ufl.algorithms.apply_derivatives import apply_coordinate_derivatives, apply_derivatives
+
 # These are the main symbolic processing steps:
 from ufl.algorithms.apply_function_pullbacks import apply_function_pullbacks
 from ufl.algorithms.apply_geometry_lowering import apply_geometry_lowering
@@ -21,9 +22,13 @@
 from ufl.algorithms.apply_restrictions import apply_default_restrictions, apply_restrictions
 from ufl.algorithms.check_arities import check_form_arity
 from ufl.algorithms.comparison_checker import do_comparison_check
+
 # See TODOs at the call sites of these below:
-from ufl.algorithms.domain_analysis import (build_integral_data, group_form_integrals,
-                                            reconstruct_form_from_integral_data)
+from ufl.algorithms.domain_analysis import (
+    build_integral_data,
+    group_form_integrals,
+    reconstruct_form_from_integral_data,
+)
 from ufl.algorithms.estimate_degrees import estimate_total_polynomial_degree
 from ufl.algorithms.formdata import FormData
 from ufl.algorithms.formtransformations import compute_form_arities
@@ -56,8 +61,7 @@ def _compute_element_mapping(form):
     #   worked around to drop this requirement
 
     # Extract all elements and include subelements of mixed elements
-    elements = [obj.ufl_element() for obj in chain(form.arguments(),
-                                                   form.coefficients())]
+    elements = [obj.ufl_element() for obj in chain(form.arguments(), form.coefficients())]
     elements = extract_sub_elements(elements)
 
     # Try to find a common degree for elements
@@ -66,7 +70,6 @@ def _compute_element_mapping(form):
     # Compute element map
     element_mapping = {}
     for element in elements:
-
         # Flag for whether element needs to be reconstructed
         reconstruct = False
 
@@ -74,9 +77,10 @@ def _compute_element_mapping(form):
         cell = element.cell
         if cell is None:
             domains = form.ufl_domains()
-            if not all(domains[0].ufl_cell() == d.ufl_cell()
-                       for d in domains):
-                raise ValueError("Cannot replace unknown element cell without unique common cell in form.")
+            if not all(domains[0].ufl_cell() == d.ufl_cell() for d in domains):
+                raise ValueError(
+                    "Cannot replace unknown element cell without unique common cell in form."
+                )
             cell = domains[0].ufl_cell()
             reconstruct = True
 
@@ -133,8 +137,7 @@ def _compute_form_data_elements(self, arguments, coefficients, domains):
 
 def _check_elements(form_data):
     """Check elements."""
-    for element in chain(form_data.unique_elements,
-                         form_data.unique_sub_elements):
+    for element in chain(form_data.unique_elements, form_data.unique_sub_elements):
         if element.cell is None:
             raise ValueError(f"Found element with undefined cell: {element}")
 
@@ -244,10 +247,15 @@ def preprocess_form(form, complex_mode):
 
 
 def compute_form_data(
-    form, do_apply_function_pullbacks=False, do_apply_integral_scaling=False,
-    do_apply_geometry_lowering=False, preserve_geometry_types=(),
-    do_apply_default_restrictions=True, do_apply_restrictions=True,
-    do_estimate_degrees=True, do_append_everywhere_integrals=True,
+    form,
+    do_apply_function_pullbacks=False,
+    do_apply_integral_scaling=False,
+    do_apply_geometry_lowering=False,
+    preserve_geometry_types=(),
+    do_apply_default_restrictions=True,
+    do_apply_restrictions=True,
+    do_estimate_degrees=True,
+    do_append_everywhere_integrals=True,
     complex_mode=False,
 ):
     """Compute form data.
@@ -273,8 +281,11 @@ def compute_form_data(
     # TODO: Refactor this, it's rather opaque what this does
     # TODO: Is self.original_form.ufl_domains() right here?
     #       It will matter when we start including 'num_domains' in ufc form.
-    form = group_form_integrals(form, self.original_form.ufl_domains(),
-                                do_append_everywhere_integrals=do_append_everywhere_integrals)
+    form = group_form_integrals(
+        form,
+        self.original_form.ufl_domains(),
+        do_append_everywhere_integrals=do_append_everywhere_integrals,
+    )
 
     # Estimate polynomial degree of integrands now, before applying
     # any pullbacks and geometric lowering.  Otherwise quad degrees
@@ -350,17 +361,18 @@ def compute_form_data(
     reduced_coefficients_set = set()
     for itg_data in self.integral_data:
         reduced_coefficients_set.update(itg_data.integral_coefficients)
-    self.reduced_coefficients = sorted(reduced_coefficients_set,
-                                       key=lambda c: c.count())
+    self.reduced_coefficients = sorted(reduced_coefficients_set, key=lambda c: c.count())
     self.num_coefficients = len(self.reduced_coefficients)
-    self.original_coefficient_positions = [i for i, c in enumerate(self.original_form.coefficients())
-                                           if c in self.reduced_coefficients]
+    self.original_coefficient_positions = [
+        i for i, c in enumerate(self.original_form.coefficients()) if c in self.reduced_coefficients
+    ]
 
     # Store back into integral data which form coefficients are used
     # by each integral
     for itg_data in self.integral_data:
-        itg_data.enabled_coefficients = [bool(coeff in itg_data.integral_coefficients)
-                                         for coeff in self.reduced_coefficients]
+        itg_data.enabled_coefficients = [
+            bool(coeff in itg_data.integral_coefficients) for coeff in self.reduced_coefficients
+        ]
 
     # --- Collect some trivial data
 
@@ -384,17 +396,19 @@ def compute_form_data(
     # Mappings from elements and coefficients that reside in form to
     # objects with canonical numbering as well as completed cells and
     # elements
-    renumbered_coefficients, function_replace_map = \
-        _build_coefficient_replace_map(self.reduced_coefficients,
-                                       self.element_replace_map)
+    renumbered_coefficients, function_replace_map = _build_coefficient_replace_map(
+        self.reduced_coefficients, self.element_replace_map
+    )
     self.function_replace_map = function_replace_map
 
     # --- Store various lists of elements and sub elements (adds
     #     members to self)
-    _compute_form_data_elements(self,
-                                self.original_form.arguments(),
-                                renumbered_coefficients,
-                                self.original_form.ufl_domains())
+    _compute_form_data_elements(
+        self,
+        self.original_form.arguments(),
+        renumbered_coefficients,
+        self.original_form.ufl_domains(),
+    )
 
     # --- Store number of domains for integral types
     # TODO: Group this by domain first. For now keep a backwards
diff --git a/ufl/algorithms/coordinate_derivative_helpers.py b/ufl/algorithms/coordinate_derivative_helpers.py
index 77b1c19bf..852b655c2 100644
--- a/ufl/algorithms/coordinate_derivative_helpers.py
+++ b/ufl/algorithms/coordinate_derivative_helpers.py
@@ -1,4 +1,4 @@
-"""This module provides the necessary tools to strip away and reattach coordinate derivatives.
+"""Tools to strip away and reattach coordinate derivatives.
 
 This is used in compute_form_data.
 """
@@ -64,7 +64,10 @@ def strip_coordinate_derivatives(integrals):
         coordinate_derivatives = []
 
         def take_top_coordinate_derivatives(o):
-            """Grab all coordinate derivatives and store them, so that we can apply them later again."""
+            """Get all coordinate derivatives and store them.
+
+            So we can apply them later again.
+            """
             o_ = o.ufl_operands
             if isinstance(o, CoordinateDerivative):
                 coordinate_derivatives.append((o_[1], o_[2], o_[3]))
diff --git a/ufl/algorithms/domain_analysis.py b/ufl/algorithms/domain_analysis.py
index 3a11b123a..7d7c34042 100644
--- a/ufl/algorithms/domain_analysis.py
+++ b/ufl/algorithms/domain_analysis.py
@@ -11,7 +11,10 @@
 from collections import defaultdict
 
 import ufl
-from ufl.algorithms.coordinate_derivative_helpers import attach_coordinate_derivatives, strip_coordinate_derivatives
+from ufl.algorithms.coordinate_derivative_helpers import (
+    attach_coordinate_derivatives,
+    strip_coordinate_derivatives,
+)
 from ufl.form import Form
 from ufl.integral import Integral
 from ufl.protocols import id_or_none
@@ -22,17 +25,22 @@
 class IntegralData(object):
     """Utility class.
 
-    This class has members (domain, integral_type, subdomain_id, integrals, metadata),
-    where metadata is an empty dictionary that may be used for
-    associating metadata with each object.
+    This class has members (domain, integral_type, subdomain_id,
+    integrals, metadata), where metadata is an empty dictionary that may
+    be used for associating metadata with each object.
     """
-    __slots__ = ('domain', 'integral_type', 'subdomain_id',
-                 'integrals', 'metadata',
-                 'integral_coefficients',
-                 'enabled_coefficients')
 
-    def __init__(self, domain, integral_type, subdomain_id, integrals,
-                 metadata):
+    __slots__ = (
+        "domain",
+        "integral_type",
+        "subdomain_id",
+        "integrals",
+        "metadata",
+        "integral_coefficients",
+        "enabled_coefficients",
+    )
+
+    def __init__(self, domain, integral_type, subdomain_id, integrals, metadata):
         """Initialise."""
         if 1 != len(set(itg.ufl_domain() for itg in integrals)):
             raise ValueError("Multiple domains mismatch in integral data.")
@@ -59,21 +67,27 @@ def __init__(self, domain, integral_type, subdomain_id, integrals,
     def __lt__(self, other):
         """Check if self is less than other."""
         # To preserve behaviour of extract_integral_data:
-        return (
-            self.integral_type, self.subdomain_id, self.integrals, self.metadata
-        ) < (
-            other.integral_type, other.subdomain_id, other.integrals, other.metadata
+        return (self.integral_type, self.subdomain_id, self.integrals, self.metadata) < (
+            other.integral_type,
+            other.subdomain_id,
+            other.integrals,
+            other.metadata,
         )
 
     def __eq__(self, other):
         """Check for equality."""
         # Currently only used for tests:
-        return (self.integral_type == other.integral_type and self.subdomain_id == other.subdomain_id and  # noqa: W504
-                self.integrals == other.integrals and self.metadata == other.metadata)
+        return (
+            self.integral_type == other.integral_type
+            and self.subdomain_id == other.subdomain_id
+            and self.integrals == other.integrals
+            and self.metadata == other.metadata
+        )
 
     def __str__(self):
         """Format as a string."""
-        s = f"IntegralData over domain({self.integral_type}, {self.subdomain_id}), with integrals:\n"
+        s = f"IntegralData over domain({self.integral_type}, {self.subdomain_id})"
+        s += " with integrals:\n"
         s += "\n\n".join(map(str, self.integrals))
         s += "\nand metadata:\n{metadata}"
         return s
@@ -81,7 +95,8 @@ def __str__(self):
 
 class ExprTupleKey(object):
     """Tuple comparison helper."""
-    __slots__ = ('x',)
+
+    __slots__ = ("x",)
 
     def __init__(self, x):
         """Initialise."""
@@ -141,14 +156,14 @@ def integral_subdomain_ids(integral):
 
 
 def rearrange_integrals_by_single_subdomains(
-    integrals: typing.List[Integral],
-    do_append_everywhere_integrals: bool
+    integrals: typing.List[Integral], do_append_everywhere_integrals: bool
 ) -> typing.Dict[int, typing.List[Integral]]:
     """Rearrange integrals over multiple subdomains to single subdomain integrals.
 
     Args:
         integrals: List of integrals
-        do_append_everywhere_integrals: Boolean indicating if integrals defined on the whole domain should
+        do_append_everywhere_integrals: Boolean indicating if integrals
+        defined on the whole domain should
             just be restricted to the set of input subdomain ids.
 
     Returns:
@@ -188,7 +203,8 @@ def rearrange_integrals_by_single_subdomains(
         if do_append_everywhere_integrals:
             for subdomain_id in sorted(single_subdomain_integrals.keys()):
                 single_subdomain_integrals[subdomain_id].append(
-                    ev_itg.reconstruct(subdomain_id=subdomain_id))
+                    ev_itg.reconstruct(subdomain_id=subdomain_id)
+                )
 
     if otherwise_integrals:
         single_subdomain_integrals["otherwise"] = otherwise_integrals
@@ -203,8 +219,9 @@ def accumulate_integrands_with_same_metadata(integrals):
         integrals: a list of integrals
 
     Returns:
-        A list of the form [(integrand0, metadata0), (integrand1, metadata1), ...]
-        where integrand0 < integrand1 by the canonical ufl expression ordering criteria.
+        A list of the form [(integrand0, metadata0), (integrand1,
+        metadata1), ...] where integrand0 < integrand1 by the canonical
+        ufl expression ordering criteria.
     """
     # Group integrals by compiler data hash
     by_cdid = {}
@@ -256,15 +273,26 @@ def build_integral_data(integrals):
         subdomain_id = integral.subdomain_id()
         subdomain_data = id_or_none(integral.subdomain_data())
         if subdomain_id == "everywhere":
-            raise ValueError("'everywhere' not a valid subdomain id.  Did you forget to call group_form_integrals?")
-        unique_integrals[(integral_type, ufl_domain, meta_hash, integrand, subdomain_data)] += (subdomain_id,)
+            raise ValueError(
+                "'everywhere' not a valid subdomain id. "
+                "Did you forget to call group_form_integrals?"
+            )
+        unique_integrals[(integral_type, ufl_domain, meta_hash, integrand, subdomain_data)] += (
+            subdomain_id,
+        )
         metadata_table[(integral_type, ufl_domain, meta_hash, integrand, subdomain_data)] = metadata
 
     for integral_data, subdomain_ids in unique_integrals.items():
         (integral_type, ufl_domain, metadata, integrand, subdomain_data) = integral_data
 
-        integral = Integral(integrand, integral_type, ufl_domain, subdomain_ids,
-                            metadata_table[integral_data], subdomain_data)
+        integral = Integral(
+            integrand,
+            integral_type,
+            ufl_domain,
+            subdomain_ids,
+            metadata_table[integral_data],
+            subdomain_data,
+        )
         # Group for integral data (One integral data object for all
         # integrals with same domain, itype, (but possibly different metadata).
         itgs[(ufl_domain, integral_type, subdomain_ids)].append(integral)
@@ -274,7 +302,8 @@ def build_integral_data(integrals):
     def keyfunc(item):
         (d, itype, sid), integrals = item
         sid_int = tuple(-1 if i == "otherwise" else i for i in sid)
-        return (d._ufl_sort_key_(), itype, (type(sid).__name__, ), sid_int)
+        return (d._ufl_sort_key_(), itype, (type(sid).__name__,), sid_int)
+
     integral_datas = []
     for (d, itype, sid), integrals in sorted(itgs.items(), key=keyfunc):
         integral_datas.append(IntegralData(d, itype, sid, integrals, {}))
@@ -287,7 +316,8 @@ def group_form_integrals(form, domains, do_append_everywhere_integrals=True):
     Args:
         form: the Form to group the integrals of.
         domains: an iterable of Domains.
-        do_append_everywhere_integrals: Boolean indicating if integrals defined on the whole domain should
+        do_append_everywhere_integrals: Boolean indicating if integrals
+        defined on the whole domain should
             just be restricted to the set of input subdomain ids.
 
     Returns:
@@ -309,18 +339,21 @@ def group_form_integrals(form, domains, do_append_everywhere_integrals=True):
             # (note: before this call, 'everywhere' is a valid subdomain_id,
             # and after this call, 'otherwise' is a valid subdomain_id)
             single_subdomain_integrals = rearrange_integrals_by_single_subdomains(
-                ddt_integrals, do_append_everywhere_integrals)
+                ddt_integrals, do_append_everywhere_integrals
+            )
 
             for subdomain_id, ss_integrals in sorted_by_key(single_subdomain_integrals):
-
                 # strip the coordinate derivatives from all integrals
                 # this yields a list of the form [(coordinate derivative, integral), ...]
                 stripped_integrals_and_coordderivs = strip_coordinate_derivatives(ss_integrals)
 
                 # now group the integrals by the coordinate derivative
                 def calc_hash(cd):
-                    return sum(sum(tuple_elem._ufl_compute_hash_()
-                                   for tuple_elem in tuple_) for tuple_ in cd)
+                    return sum(
+                        sum(tuple_elem._ufl_compute_hash_() for tuple_elem in tuple_)
+                        for tuple_ in cd
+                    )
+
                 coordderiv_integrals_dict = {}
                 for integral, coordderiv in stripped_integrals_and_coordderivs:
                     coordderivhash = calc_hash(coordderiv)
@@ -335,14 +368,16 @@ def calc_hash(cd):
                 # apply the CoordinateDerivative again
 
                 for cdhash, samecd_integrals in sorted_by_key(coordderiv_integrals_dict):
-
                     # Accumulate integrands of integrals that share the
                     # same compiler data
-                    integrands_and_cds = accumulate_integrands_with_same_metadata(samecd_integrals[1])
+                    integrands_and_cds = accumulate_integrands_with_same_metadata(
+                        samecd_integrals[1]
+                    )
 
                     for integrand, metadata in integrands_and_cds:
-                        integral = Integral(integrand, integral_type, domain,
-                                            subdomain_id, metadata, None)
+                        integral = Integral(
+                            integrand, integral_type, domain, subdomain_id, metadata, None
+                        )
                         integral = attach_coordinate_derivatives(integral, samecd_integrals[0])
                         integrals.append(integral)
     return Form(integrals)
diff --git a/ufl/algorithms/estimate_degrees.py b/ufl/algorithms/estimate_degrees.py
index 334041d3f..da550116c 100644
--- a/ufl/algorithms/estimate_degrees.py
+++ b/ufl/algorithms/estimate_degrees.py
@@ -46,7 +46,8 @@ def constant(self, v):
     def geometric_quantity(self, v):
         """Apply to geometric_quantity.
 
-        Some geometric quantities are cellwise constant. Others are nonpolynomial and thus hard to estimate.
+        Some geometric quantities are cellwise constant. Others are
+        nonpolynomial and thus hard to estimate.
         """
         if is_cellwise_constant(v):
             return 0
@@ -74,7 +75,9 @@ def argument(self, v):
         A form argument provides a degree depending on the element,
         or the default degree if the element has no degree.
         """
-        return v.ufl_element().embedded_superdegree  # FIXME: Use component to improve accuracy for mixed elements
+        return (
+            v.ufl_element().embedded_superdegree
+        )  # FIXME: Use component to improve accuracy for mixed elements
 
     def coefficient(self, v):
         """Apply to coefficient.
@@ -95,7 +98,10 @@ def _reduce_degree(self, v, f):
         This is used when derivatives are taken. It does not reduce the degree when
         TensorProduct elements or quadrilateral elements are involved.
         """
-        if isinstance(f, int) and extract_unique_domain(v).ufl_cell().cellname() not in ["quadrilateral", "hexahedron"]:
+        if isinstance(f, int) and extract_unique_domain(v).ufl_cell().cellname() not in [
+            "quadrilateral",
+            "hexahedron",
+        ]:
             return max(f - 1, 0)
         else:
             return f
@@ -284,7 +290,8 @@ def atan2(self, v, a, b):
         Using the heuristic:
         degree(atan2(const,const)) == 0
         degree(atan2(a,b)) == max(degree(a),degree(b))+2
-        which can be wildly inaccurate but at least gives a somewhat high integration degree.
+        which can be wildly inaccurate but at least gives a somewhat
+        high integration degree.
         """
         if a or b:
             return self._add_degrees(v, self._max_degrees(v, a, b), 2)
@@ -297,7 +304,8 @@ def math_function(self, v, a):
         Using the heuristic:
         degree(sin(const)) == 0
         degree(sin(a)) == degree(a)+2
-        which can be wildly inaccurate but at least gives a somewhat high integration degree.
+        which can be wildly inaccurate but at least gives a somewhat
+        high integration degree.
         """
         if a:
             return self._add_degrees(v, a, 2)
@@ -310,7 +318,8 @@ def bessel_function(self, v, nu, x):
         Using the heuristic
         degree(bessel_*(const)) == 0
         degree(bessel_*(x)) == degree(x)+2
-        which can be wildly inaccurate but at least gives a somewhat high integration degree.
+        which can be wildly inaccurate but at least gives a somewhat
+        high integration degree.
         """
         if x:
             return self._add_degrees(v, x, 2)
@@ -337,6 +346,7 @@ def min_value(self, v, a, r):
         Same as conditional.
         """
         return self._max_degrees(v, a, r)
+
     max_value = min_value
 
     def coordinate_derivative(self, v, integrand_degree, b, direction_degree, d):
@@ -357,8 +367,7 @@ def expr_mapping(self, v, *o):
         return self._max_degrees(v, *o)
 
 
-def estimate_total_polynomial_degree(e, default_degree=1,
-                                     element_replace_map={}):
+def estimate_total_polynomial_degree(e, default_degree=1, element_replace_map={}):
     """Estimate total polynomial degree of integrand.
 
     NB: Although some compound types are supported here,
@@ -366,8 +375,8 @@ def estimate_total_polynomial_degree(e, default_degree=1,
     prior to degree estimation. In generic code, this algorithm
     should only be applied after preprocessing.
 
-    For coefficients defined on an element with unspecified degree (None),
-    the degree is set to the given default degree.
+    For coefficients defined on an element with unspecified degree
+    (None), the degree is set to the given default degree.
     """
     de = SumDegreeEstimator(default_degree, element_replace_map)
     if isinstance(e, Form):
diff --git a/ufl/algorithms/expand_compounds.py b/ufl/algorithms/expand_compounds.py
index 97eecc499..0f2bc9d14 100644
--- a/ufl/algorithms/expand_compounds.py
+++ b/ufl/algorithms/expand_compounds.py
@@ -1,4 +1,4 @@
-"""Algorithm for expanding compound expressions into equivalent representations using basic operators."""
+"""Algorithm for expanding compound expressions into equivalent representations."""
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
@@ -15,7 +15,10 @@
 
 def expand_compounds(e):
     """Expand compounds."""
-    warnings.warn("The use of expand_compounds is deprecated and will be removed after December 2023. "
-                  "Please, use apply_algebra_lowering directly instead", FutureWarning)
+    warnings.warn(
+        "The use of expand_compounds is deprecated and will be removed after December 2023. "
+        "Please, use apply_algebra_lowering directly instead",
+        FutureWarning,
+    )
 
     return apply_algebra_lowering(e)
diff --git a/ufl/algorithms/expand_indices.py b/ufl/algorithms/expand_indices.py
index 1523bd4c4..1ae1cbfc3 100644
--- a/ufl/algorithms/expand_indices.py
+++ b/ufl/algorithms/expand_indices.py
@@ -133,7 +133,7 @@ def index_sum(self, x):
         """Apply to index_sum."""
         ops = []
         summand, multiindex = x.ufl_operands
-        index, = multiindex
+        (index,) = multiindex
 
         # TODO: For the list tensor purging algorithm, do something like:
         # if index not in self._to_expand:
@@ -222,7 +222,7 @@ def list_tensor(self, x):
 
     def grad(self, x):
         """Apply to grad."""
-        f, = x.ufl_operands
+        (f,) = x.ufl_operands
         if not isinstance(f, (Terminal, Grad)):
             raise ValueError("Expecting expand_derivatives to have been applied.")
         # No need to visit child as long as it is on the form [Grad]([Grad](terminal))
diff --git a/ufl/algorithms/formdata.py b/ufl/algorithms/formdata.py
index 6f1048aec..f6bdf4c14 100644
--- a/ufl/algorithms/formdata.py
+++ b/ufl/algorithms/formdata.py
@@ -20,9 +20,11 @@ def __init__(self):
     def __str__(self):
         """Return formatted summary of form data."""
         types = sorted(self.max_subdomain_ids.keys())
-        geometry = (("Geometric dimension", self.geometric_dimension), )
-        subdomains = tuple((f"Number of {integral_type} subdomains", self.max_subdomain_ids[integral_type])
-                           for integral_type in types)
+        geometry = (("Geometric dimension", self.geometric_dimension),)
+        subdomains = tuple(
+            (f"Number of {integral_type} subdomains", self.max_subdomain_ids[integral_type])
+            for integral_type in types
+        )
         functions = (
             # Arguments
             ("Rank", self.rank),
diff --git a/ufl/algorithms/formfiles.py b/ufl/algorithms/formfiles.py
index 7927f3a11..a93383275 100644
--- a/ufl/algorithms/formfiles.py
+++ b/ufl/algorithms/formfiles.py
@@ -37,8 +37,15 @@ def __init__(self):
 
     def __bool__(self):
         """Convert to a bool."""
-        return bool(self.elements or self.coefficients or self.forms or self.expressions or  # noqa: W504
-                    self.object_names or self.object_by_name or self.reserved_objects)
+        return bool(
+            self.elements
+            or self.coefficients
+            or self.forms
+            or self.expressions
+            or self.object_names
+            or self.object_by_name
+            or self.reserved_objects
+        )
 
     __nonzero__ = __bool__
 
@@ -59,9 +66,9 @@ def match(line):
     for i in range(min(2, len(lines))):
         m = match(lines[i])
         if m:
-            encoding, = m.groups()
+            (encoding,) = m.groups()
             # Drop encoding line
-            lines = lines[:i] + lines[i + 1:]
+            lines = lines[:i] + lines[i + 1 :]
             break
     else:
         # Default to utf-8 (works for ascii files
@@ -107,7 +114,9 @@ def interpret_ufl_namespace(namespace):
             # FIXME: Remove after FFC is updated to use reserved_objects:
             ufd.object_names[name] = value
             ufd.object_by_name[name] = value
-        elif isinstance(value, (AbstractFiniteElement, Coefficient, Constant, Argument, Form, Expr)):
+        elif isinstance(
+            value, (AbstractFiniteElement, Coefficient, Constant, Argument, Form, Expr)
+        ):
             # Store instance <-> name mappings for important objects
             # without a reserved name
             ufd.object_names[id(value)] = name
@@ -121,6 +130,7 @@ def interpret_ufl_namespace(namespace):
         def get_form(name):
             form = ufd.object_by_name.get(name)
             return form if isinstance(form, Form) else None
+
         a_form = get_form("a")
         L_form = get_form("L")
         M_form = get_form("M")
@@ -149,7 +159,9 @@ def get_form(name):
 
     # Validate types
     if not isinstance(ufd.elements, (list, tuple)):
-        raise ValueError(f"Expecting 'elements' to be a list or tuple, not '{type(ufd.elements)}''.")
+        raise ValueError(
+            f"Expecting 'elements' to be a list or tuple, not '{type(ufd.elements)}''."
+        )
     if not all(isinstance(e, AbstractFiniteElement) for e in ufd.elements):
         raise ValueError("Expecting 'elements' to be a list of AbstractFiniteElement instances.")
 
@@ -159,7 +171,9 @@ def get_form(name):
 
     # Validate types
     if not isinstance(ufd.coefficients, (list, tuple)):
-        raise ValueError(f"Expecting 'coefficients' to be a list or tuple, not '{type(ufd.coefficients)}'.")
+        raise ValueError(
+            f"Expecting 'coefficients' to be a list or tuple, not '{type(ufd.coefficients)}'."
+        )
     if not all(isinstance(e, Coefficient) for e in ufd.coefficients):
         raise ValueError("Expecting 'coefficients' to be a list of Coefficient instances.")
 
@@ -168,7 +182,9 @@ def get_form(name):
 
     # Validate types
     if not isinstance(ufd.expressions, (list, tuple)):
-        raise ValueError(f"Expecting 'expressions' to be a list or tuple, not '{type(ufd.expressions)}'.")
+        raise ValueError(
+            f"Expecting 'expressions' to be a list or tuple, not '{type(ufd.expressions)}'."
+        )
     if not all(isinstance(e[0], Expr) for e in ufd.expressions):
         raise ValueError("Expecting 'expressions' to be a list of Expr instances.")
 
diff --git a/ufl/algorithms/formsplitter.py b/ufl/algorithms/formsplitter.py
index ef9b2bbef..c96a63e99 100644
--- a/ufl/algorithms/formsplitter.py
+++ b/ufl/algorithms/formsplitter.py
@@ -27,11 +27,11 @@ def split(self, form, ix, iy=0):
 
     def argument(self, obj):
         """Apply to argument."""
-        if (obj.part() is not None):
+        if obj.part() is not None:
             # Mixed element built from MixedFunctionSpace,
             # whose sub-function spaces are indexed by obj.part()
             if len(obj.ufl_shape) == 0:
-                if (obj.part() == self.idx[obj.number()]):
+                if obj.part() == self.idx[obj.number()]:
                     return obj
                 else:
                     return Zero()
@@ -40,7 +40,7 @@ def argument(self, obj):
                 for m in obj.ufl_shape:
                     indices = [(k + (j,)) for k in indices for j in range(m)]
 
-                if (obj.part() == self.idx[obj.number()]):
+                if obj.part() == self.idx[obj.number()]:
                     return as_vector([obj[j] for j in indices])
                 else:
                     return as_vector([Zero() for j in indices])
@@ -52,7 +52,7 @@ def argument(self, obj):
             sub_elements = obj.ufl_element().sub_elements()
 
             # If not a mixed element, do nothing
-            if (len(sub_elements) == 0):
+            if len(sub_elements) == 0:
                 return obj
 
             args = []
@@ -64,7 +64,7 @@ def argument(self, obj):
                 for m in a.ufl_shape:
                     indices = [(k + (j,)) for k in indices for j in range(m)]
 
-                if (i == self.idx[obj.number()]):
+                if i == self.idx[obj.number()]:
                     args += [a[j] for j in indices]
                 else:
                     args += [Zero() for j in indices]
@@ -90,7 +90,7 @@ def extract_blocks(form, i=None, j=None):
     assert arity <= 2
 
     if arity == 0:
-        return (form, )
+        return (form,)
 
     for pi in parts:
         if arity > 1:
@@ -111,7 +111,7 @@ def extract_blocks(form, i=None, j=None):
         forms_tuple = tuple(forms)
     except TypeError:
         # Only one form returned
-        forms_tuple = (forms, )
+        forms_tuple = (forms,)
 
     if i is not None:
         if arity > 1 and j is not None:
diff --git a/ufl/algorithms/formtransformations.py b/ufl/algorithms/formtransformations.py
index 58d168c14..20a6a1743 100644
--- a/ufl/algorithms/formtransformations.py
+++ b/ufl/algorithms/formtransformations.py
@@ -1,4 +1,4 @@
-"""This module defines utilities for transforming complete Forms into new related Forms."""
+"""Utilities for transforming complete Forms into new related Forms."""
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
@@ -14,6 +14,7 @@
 from logging import debug
 
 from ufl.algebra import Conj
+
 # Other algorithms:
 from ufl.algorithms.map_integrands import map_integrands
 from ufl.algorithms.replace import replace
@@ -21,6 +22,7 @@
 from ufl.argument import Argument
 from ufl.coefficient import Coefficient
 from ufl.constantvalue import Zero
+
 # All classes:
 from ufl.core.expr import ufl_err_str
 
@@ -123,7 +125,6 @@ def sum(self, x):
         original_terms = x.ufl_operands
         assert len(original_terms) == 2
         for term in original_terms:
-
             # Visit this term in the sum
             part, term_provides = self.visit(term)
 
@@ -145,8 +146,7 @@ def sum(self, x):
 
         # 3. Return the terms that provide the biggest set
         most_provided = frozenset()
-        for (provideds, parts) in parts_that_provide.items():  # TODO: Just sort instead?
-
+        for provideds, parts in parts_that_provide.items():  # TODO: Just sort instead?
             # Throw error if size of sets are equal (and not zero)
             if len(provideds) == len(most_provided) and len(most_provided):
                 raise ValueError("Don't know what to do with sums with different Arguments.")
@@ -158,7 +158,7 @@ def sum(self, x):
         if len(terms) == 2:
             x = self.reuse_if_possible(x, *terms)
         else:
-            x, = terms
+            (x,) = terms
 
         return (x, most_provided)
 
@@ -172,7 +172,6 @@ def product(self, x, *ops):
         factors = []
 
         for factor, factor_provides in ops:
-
             # If any factor is zero, return
             if isinstance(factor, Zero):
                 return (zero_expr(x), set())
@@ -202,7 +201,9 @@ def division(self, x):
 
         # Check for Arguments in the denominator
         if _expr_has_terminal_types(denominator, Argument):
-            raise ValueError(f"Found Argument in denominator of {ufl_err_str(x)}, this is an invalid expression.")
+            raise ValueError(
+                f"Found Argument in denominator of {ufl_err_str(x)}, this is an invalid expression."
+            )
 
         # Visit numerator
         numerator_parts, provides = self.visit(numerator)
@@ -281,18 +282,20 @@ def list_tensor(self, x, *ops):
 
         # Extract the most arguments provided by any of the components
         most_provides = ops[0][1]
-        for (component, provides) in ops:
-            if (provides - most_provides):
+        for component, provides in ops:
+            if provides - most_provides:
                 most_provides = provides
 
         # Check that all components either provide the same arguments
         # or vanish. (This check is here b/c it is not obvious what to
         # return if the components provide different arguments, at
         # least with the current transformer design.)
-        for (component, provides) in ops:
-            if (provides != most_provides and not isinstance(component, Zero)):
-                raise ValueError("PartExtracter does not know how to handle list_tensors with "
-                                 "non-zero components providing fewer arguments")
+        for component, provides in ops:
+            if provides != most_provides and not isinstance(component, Zero):
+                raise ValueError(
+                    "PartExtracter does not know how to handle list_tensors with "
+                    "non-zero components providing fewer arguments"
+                )
 
         # Return components
         components = [op[0] for op in ops]
@@ -327,6 +330,7 @@ def _transform(e):
         if provides == sub_arguments:
             return e
         return Zero()
+
     return map_integrands(_transform, form)
 
 
@@ -341,7 +345,6 @@ def compute_form_arities(form):
 
     arities = set()
     for arity in range(len(arguments) + 1):
-
         # Compute parts with arity "arity"
         parts = compute_form_with_arity(form, arity, arguments)
 
@@ -432,13 +435,17 @@ def compute_energy_norm(form, coefficient):
     U = u.ufl_function_space()
     V = v.ufl_function_space()
     if U != V:
-        raise ValueError(f"Expecting equal finite elements for test and trial functions, got '{U}' and '{V}'.")
+        raise ValueError(
+            f"Expecting equal finite elements for test and trial functions, got '{U}' and '{V}'."
+        )
     if coefficient is None:
         coefficient = Coefficient(V)
     else:
         if coefficient.ufl_function_space() != U:
-            raise ValueError("Trying to compute action of form on a "
-                  "coefficient in an incompatible element space.")
+            raise ValueError(
+                "Trying to compute action of form on a "
+                "coefficient in an incompatible element space."
+            )
     return action(action(form, coefficient), coefficient)
 
 
@@ -462,10 +469,8 @@ def compute_form_adjoint(form, reordered_arguments=None):
         raise ValueError("Mistaken assumption in code!")
 
     if reordered_arguments is None:
-        reordered_u = Argument(u.ufl_function_space(), number=v.number(),
-                               part=v.part())
-        reordered_v = Argument(v.ufl_function_space(), number=u.number(),
-                               part=u.part())
+        reordered_u = Argument(u.ufl_function_space(), number=v.number(), part=v.part())
+        reordered_v = Argument(v.ufl_function_space(), number=u.number(), part=u.part())
     else:
         reordered_u, reordered_v = reordered_arguments
 
diff --git a/ufl/algorithms/map_integrands.py b/ufl/algorithms/map_integrands.py
index 55266dfb9..0a6da1817 100644
--- a/ufl/algorithms/map_integrands.py
+++ b/ufl/algorithms/map_integrands.py
@@ -1,4 +1,4 @@
-"""Basic algorithms for applying functions to subexpressions."""
+"""Basic algorithms for applying functions to sub-expressions."""
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
@@ -20,12 +20,18 @@
 
 
 def map_integrands(function, form, only_integral_type=None):
-    """Apply transform(expression) to each integrand expression in form, or to form if it is an Expr."""
+    """Map integrands.
+
+    Apply transform(expression) to each integrand expression in form, or
+    to form if it is an Expr.
+    """
     if isinstance(form, Form):
-        mapped_integrals = [map_integrands(function, itg, only_integral_type)
-                            for itg in form.integrals()]
-        nonzero_integrals = [itg for itg in mapped_integrals
-                             if not isinstance(itg.integrand(), Zero)]
+        mapped_integrals = [
+            map_integrands(function, itg, only_integral_type) for itg in form.integrals()
+        ]
+        nonzero_integrals = [
+            itg for itg in mapped_integrals if not isinstance(itg.integrand(), Zero)
+        ]
         return Form(nonzero_integrals)
     elif isinstance(form, Integral):
         itg = form
@@ -34,11 +40,16 @@ def map_integrands(function, form, only_integral_type=None):
         else:
             return itg
     elif isinstance(form, FormSum):
-        mapped_components = [map_integrands(function, component, only_integral_type)
-                             for component in form.components()]
-        nonzero_components = [(component, w) for component, w in zip(mapped_components, form.weights())
-                              # Catch ufl.Zero and ZeroBaseForm
-                              if component != 0]
+        mapped_components = [
+            map_integrands(function, component, only_integral_type)
+            for component in form.components()
+        ]
+        nonzero_components = [
+            (component, w)
+            for component, w in zip(mapped_components, form.weights())
+            # Catch ufl.Zero and ZeroBaseForm
+            if component != 0
+        ]
 
         # Simplify case with one nonzero component and the corresponding weight is 1
         if len(nonzero_components) == 1 and nonzero_components[0][1] == 1:
@@ -59,7 +70,9 @@ def map_integrands(function, form, only_integral_type=None):
         # Zeros are caught inside `Action.__new__`
         return Action(left, right)
     elif isinstance(form, ZeroBaseForm):
-        arguments = tuple(map_integrands(function, arg, only_integral_type) for arg in form._arguments)
+        arguments = tuple(
+            map_integrands(function, arg, only_integral_type) for arg in form._arguments
+        )
         return ZeroBaseForm(arguments)
     elif isinstance(form, (Expr, BaseForm)):
         integrand = form
@@ -70,5 +83,6 @@ def map_integrands(function, form, only_integral_type=None):
 
 def map_integrand_dags(function, form, only_integral_type=None, compress=True):
     """Map integrand dags."""
-    return map_integrands(lambda expr: map_expr_dag(function, expr, compress),
-                          form, only_integral_type)
+    return map_integrands(
+        lambda expr: map_expr_dag(function, expr, compress), form, only_integral_type
+    )
diff --git a/ufl/algorithms/remove_complex_nodes.py b/ufl/algorithms/remove_complex_nodes.py
index 7d97a5731..99b646205 100644
--- a/ufl/algorithms/remove_complex_nodes.py
+++ b/ufl/algorithms/remove_complex_nodes.py
@@ -1,4 +1,4 @@
-"""Algorithm for removing conj, real, and imag nodes from a form for when the user is in 'real mode'."""
+"""Remove conj, real, and imag nodes from a form."""
 
 from ufl.algorithms.map_integrands import map_integrand_dags
 from ufl.constantvalue import ComplexValue
@@ -7,6 +7,7 @@
 
 class ComplexNodeRemoval(MultiFunction):
     """Replaces complex operator nodes with their children."""
+
     expr = MultiFunction.reuse_if_untouched
 
     def conj(self, o, a):
@@ -24,7 +25,7 @@ def imag(self, o, a):
     def terminal(self, t, *ops):
         """Apply to terminal."""
         if isinstance(t, ComplexValue):
-            raise ValueError('Unexpected complex value in real expression.')
+            raise ValueError("Unexpected complex value in real expression.")
         else:
             return t
 
@@ -32,8 +33,8 @@ def terminal(self, t, *ops):
 def remove_complex_nodes(expr):
     """Replaces complex operator nodes with their children.
 
-    This is called during compute_form_data if the compiler wishes to compile
-    real-valued forms. In essence this strips all trace of complex
-    support from the preprocessed form.
+    This is called during compute_form_data if the compiler wishes to
+    compile real-valued forms. In essence this strips all trace of
+    complex support from the preprocessed form.
     """
     return map_integrand_dags(ComplexNodeRemoval(), expr)
diff --git a/ufl/algorithms/renumbering.py b/ufl/algorithms/renumbering.py
index 303457dd6..87e08203d 100644
--- a/ufl/algorithms/renumbering.py
+++ b/ufl/algorithms/renumbering.py
@@ -35,7 +35,8 @@ def variable(self, o):
 class IndexRenumberingTransformer(VariableRenumberingTransformer):
     """Index renumbering transformer.
 
-    This is a poorly designed algorithm. It is used in some tests, please do not use for anything else.
+    This is a poorly designed algorithm. It is used in some tests,
+    please do not use for anything else.
     """
 
     def __init__(self):
@@ -79,5 +80,8 @@ def renumber_indices(expr):
 
     if isinstance(expr, Expr):
         if num_free_indices != len(result.ufl_free_indices):
-            raise ValueError("The number of free indices left in expression should be invariant w.r.t. renumbering.")
+            raise ValueError(
+                "The number of free indices left in expression "
+                "should be invariant w.r.t. renumbering."
+            )
     return result
diff --git a/ufl/algorithms/replace.py b/ufl/algorithms/replace.py
index e96ecc577..5f3616949 100644
--- a/ufl/algorithms/replace.py
+++ b/ufl/algorithms/replace.py
@@ -33,7 +33,9 @@ def get_shape(x):
             return x.ufl_shape
 
         if not all(get_shape(k) == get_shape(v) for k, v in mapping.items()):
-            raise ValueError("Replacement expressions must have the same shape as what they replace.")
+            raise ValueError(
+                "Replacement expressions must have the same shape as what they replace."
+            )
 
     def ufl_type(self, o, *args):
         """Replace a ufl_type."""
@@ -88,6 +90,7 @@ def replace(e, mapping):
     if has_exact_type(e, CoefficientDerivative):
         # Hack to avoid circular dependencies
         from ufl.algorithms.ad import expand_derivatives
+
         e = expand_derivatives(e)
 
     return map_integrand_dags(Replacer(mapping2), e)
diff --git a/ufl/algorithms/replace_derivative_nodes.py b/ufl/algorithms/replace_derivative_nodes.py
index 9c822fafb..9d373407e 100644
--- a/ufl/algorithms/replace_derivative_nodes.py
+++ b/ufl/algorithms/replace_derivative_nodes.py
@@ -22,18 +22,20 @@ def __init__(self, mapping, **derivative_kwargs):
     def coefficient_derivative(self, cd, o, coefficients, arguments, coefficient_derivatives):
         """Apply to coefficient_derivative."""
         der_kwargs = self.der_kwargs
-        new_coefficients = tuple(self.mapping[c] if c in self.mapping.keys() else c for c in coefficients.ufl_operands)
+        new_coefficients = tuple(
+            self.mapping[c] if c in self.mapping.keys() else c for c in coefficients.ufl_operands
+        )
 
         # Ensure type compatibility for arguments!
-        if 'argument' not in der_kwargs.keys():
+        if "argument" not in der_kwargs.keys():
             # Argument's number/part can be retrieved from the former coefficient derivative.
             arguments = arguments.ufl_operands
             new_arguments = ()
             for c, a in zip(new_coefficients, arguments):
                 if isinstance(a, ListTensor):
-                    a, = extract_arguments(a)
+                    (a,) = extract_arguments(a)
                 new_arguments += (type(a)(c.ufl_function_space(), a.number(), a.part()),)
-            der_kwargs.update({'argument': new_arguments})
+            der_kwargs.update({"argument": new_arguments})
 
         return ufl.derivative(o, new_coefficients, **der_kwargs)
 
@@ -44,8 +46,9 @@ def replace_derivative_nodes(expr, mapping, **derivative_kwargs):
     Replaces the variable with respect to which the derivative is taken.
     This is called during apply_derivatives to treat delayed derivatives.
 
-    Example: Let u be a Coefficient, N an ExternalOperator independent of u (i.e. N's operands don't depend on u),
-             and let uhat and Nhat be Arguments.
+    Example: Let u be a Coefficient, N an ExternalOperator independent
+        of u (i.e. N's operands don't depend on u),
+        and let uhat and Nhat be Arguments.
 
         F = u ** 2 * N * dx
         dFdu = derivative(F, u, uhat)
@@ -59,8 +62,8 @@ def replace_derivative_nodes(expr, mapping, **derivative_kwargs):
     Args:
         expr: An Expr or BaseForm.
         mapping: A dict with from:to replacements to perform.
-        derivative_kwargs: A dict containing the keyword arguments for derivative
-            (i.e. `argument` and `coefficient_derivatives`).
+        derivative_kwargs: A dict containing the keyword arguments for
+            derivative (i.e. `argument` and `coefficient_derivatives`).
     """
     mapping2 = dict((k, as_ufl(v)) for (k, v) in mapping.items())
     return map_integrand_dags(DerivativeNodeReplacer(mapping2, **derivative_kwargs), expr)
diff --git a/ufl/algorithms/signature.py b/ufl/algorithms/signature.py
index 7f9dca8b8..807fa5c00 100644
--- a/ufl/algorithms/signature.py
+++ b/ufl/algorithms/signature.py
@@ -8,8 +8,18 @@
 import hashlib
 
 from ufl.algorithms.domain_analysis import canonicalize_metadata
-from ufl.classes import (Argument, Coefficient, Constant, ConstantValue, ExprList, ExprMapping, GeometricQuantity,
-                         Index, Label, MultiIndex)
+from ufl.classes import (
+    Argument,
+    Coefficient,
+    Constant,
+    ConstantValue,
+    ExprList,
+    ExprMapping,
+    GeometricQuantity,
+    Index,
+    Label,
+    MultiIndex,
+)
 from ufl.corealg.traversal import traverse_unique_terminals, unique_post_traversal
 
 
@@ -43,7 +53,6 @@ def compute_terminal_hashdata(expressions, renumbering):
     index_numbering = {}
     for expression in expressions:
         for expr in traverse_unique_terminals(expression):
-
             if isinstance(expr, MultiIndex):
                 # Indices need a canonical numbering for a stable
                 # signature, thus this algorithm
@@ -131,8 +140,7 @@ def compute_form_signature(form, renumbering):  # FIXME: Fix callers
     hashdata = []
     for integral in integrals:
         # Compute hash data for expression, this is the expensive part
-        integrand_hashdata = compute_expression_hashdata(integral.integrand(),
-                                                         terminal_hashdata)
+        integrand_hashdata = compute_expression_hashdata(integral.integrand(), terminal_hashdata)
 
         domain_hashdata = integral.ufl_domain()._ufl_signature_data_(renumbering)
 
diff --git a/ufl/algorithms/strip_terminal_data.py b/ufl/algorithms/strip_terminal_data.py
index 4909febe4..a270d3273 100644
--- a/ufl/algorithms/strip_terminal_data.py
+++ b/ufl/algorithms/strip_terminal_data.py
@@ -4,8 +4,18 @@
 """
 
 from ufl.algorithms.replace import replace
-from ufl.classes import (Argument, Coefficient, Constant, Form, FunctionSpace, Integral, Mesh, MeshView,
-                         MixedFunctionSpace, TensorProductFunctionSpace)
+from ufl.classes import (
+    Argument,
+    Coefficient,
+    Constant,
+    Form,
+    FunctionSpace,
+    Integral,
+    Mesh,
+    MeshView,
+    MixedFunctionSpace,
+    TensorProductFunctionSpace,
+)
 from ufl.corealg.map_dag import map_expr_dag
 from ufl.corealg.multifunction import MultiFunction
 
@@ -20,20 +30,17 @@ def __init__(self):
 
     def argument(self, o):
         """Apply to argument."""
-        o_new = Argument(strip_function_space(o.ufl_function_space()),
-                         o.number(), o.part())
+        o_new = Argument(strip_function_space(o.ufl_function_space()), o.number(), o.part())
         return self.mapping.setdefault(o, o_new)
 
     def coefficient(self, o):
         """Apply to coefficient."""
-        o_new = Coefficient(strip_function_space(o.ufl_function_space()),
-                            o.count())
+        o_new = Coefficient(strip_function_space(o.ufl_function_space()), o.count())
         return self.mapping.setdefault(o, o_new)
 
     def constant(self, o):
         """Apply to constant."""
-        o_new = Constant(strip_domain(o.ufl_domain()), o.ufl_shape,
-                         o.count())
+        o_new = Constant(strip_domain(o.ufl_domain()), o.ufl_shape, o.count())
         return self.mapping.setdefault(o, o_new)
 
     expr = MultiFunction.reuse_if_untouched
@@ -102,8 +109,9 @@ def replace_terminal_data(o, mapping):
 def strip_function_space(function_space):
     """Return a new function space with all non-UFL information removed."""
     if isinstance(function_space, FunctionSpace):
-        return FunctionSpace(strip_domain(function_space.ufl_domain()),
-                             function_space.ufl_element())
+        return FunctionSpace(
+            strip_domain(function_space.ufl_domain()), function_space.ufl_element()
+        )
     elif isinstance(function_space, TensorProductFunctionSpace):
         subspaces = [strip_function_space(sub) for sub in function_space.ufl_sub_spaces()]
         return TensorProductFunctionSpace(*subspaces)
@@ -119,7 +127,8 @@ def strip_domain(domain):
     if isinstance(domain, Mesh):
         return Mesh(domain.ufl_coordinate_element(), domain.ufl_id())
     elif isinstance(domain, MeshView):
-        return MeshView(strip_domain(domain.ufl_mesh()),
-                        domain.topological_dimension(), domain.ufl_id())
+        return MeshView(
+            strip_domain(domain.ufl_mesh()), domain.topological_dimension(), domain.ufl_id()
+        )
     else:
         raise NotImplementedError(f"{type(domain)} cannot be stripped")
diff --git a/ufl/algorithms/transformer.py b/ufl/algorithms/transformer.py
index e6eed85c3..6a3328c8a 100644
--- a/ufl/algorithms/transformer.py
+++ b/ufl/algorithms/transformer.py
@@ -34,6 +34,7 @@ class Transformer(object):
     Base class for a visitor-like algorithm design pattern used to
     transform expression trees from one representation to another.
     """
+
     _handlers_cache = {}
 
     def __init__(self, variable_cache=None):
@@ -64,17 +65,16 @@ def __init__(self, variable_cache=None):
                         handler_name = UFLType._ufl_handler_name_
                     function = getattr(self, handler_name, None)
                     if function:
-                        cache_data[
-                            classobject.
-                            _ufl_typecode_] = handler_name, is_post_handler(
-                                function)
+                        cache_data[classobject._ufl_typecode_] = (
+                            handler_name,
+                            is_post_handler(function),
+                        )
                         break
             Transformer._handlers_cache[type(self)] = cache_data
 
         # Build handler list for this particular class (get functions
         # bound to self)
-        self._handlers = [(getattr(self, name), post)
-                          for (name, post) in cache_data]
+        self._handlers = [(getattr(self, name), post) for (name, post) in cache_data]
         # Keep a stack of objects visit is called on, to ease
         # backtracking
         self._visit_stack = []
@@ -236,9 +236,12 @@ def variable(self, o):
 
 
 def apply_transformer(e, transformer, integral_type=None):
-    """Apply transformer.visit(expression) to each integrand expression in form, or to form if it is an Expr."""
-    return map_integrands(lambda expr: transformer.visit(expr), e,
-                          integral_type)
+    """Apply transforms.
+
+    Apply transformer.visit(expression) to each integrand expression in
+    form, or to form if it is an Expr.
+    """
+    return map_integrands(lambda expr: transformer.visit(expr), e, integral_type)
 
 
 def strip_variables(e):
diff --git a/ufl/algorithms/traversal.py b/ufl/algorithms/traversal.py
index 78a0f1b2f..5f6688086 100644
--- a/ufl/algorithms/traversal.py
+++ b/ufl/algorithms/traversal.py
@@ -16,7 +16,7 @@
 
 
 def iter_expressions(a):
-    """Utility function to handle Form, Integral and any Expr the same way when inspecting expressions.
+    """Handle Form, Integral and any Expr the same way when inspecting expressions.
 
     Returns an iterable over Expr instances:
     - a is an Expr: (a,)
diff --git a/ufl/argument.py b/ufl/argument.py
index 804615b07..82a23f570 100644
--- a/ufl/argument.py
+++ b/ufl/argument.py
@@ -29,6 +29,7 @@
 
 # --- Class representing an argument (basis function) in a form ---
 
+
 class BaseArgument(object):
     """UFL value: Representation of an argument to a form."""
 
@@ -94,7 +95,11 @@ def ufl_domains(self):
         return self._ufl_function_space.ufl_domains()
 
     def _ufl_signature_data_(self, renumbering):
-        """Signature data for form arguments depend on the global numbering of the form arguments and domains."""
+        """Signature data.
+
+        Signature data for form arguments depend on the global numbering
+        of the form arguments and domains.
+        """
         fsdata = self._ufl_function_space._ufl_signature_data_(renumbering)
         return ("Argument", self._number, self._part, fsdata)
 
@@ -132,8 +137,10 @@ def __eq__(self, other):
         are the same ufl element but different dolfin function spaces.
         """
         return (
-            type(self) is type(other) and self._number == other._number and  # noqa: W504
-            self._part == other._part and self._ufl_function_space == other._ufl_function_space
+            type(self) is type(other)
+            and self._number == other._number
+            and self._part == other._part
+            and self._ufl_function_space == other._ufl_function_space
         )
 
 
@@ -169,7 +176,10 @@ def __init__(self, function_space, number, part=None):
         BaseArgument.__init__(self, function_space, number, part)
 
         self._repr = "Argument(%s, %s, %s)" % (
-            repr(self._ufl_function_space), repr(self._number), repr(self._part))
+            repr(self._ufl_function_space),
+            repr(self._number),
+            repr(self._part),
+        )
 
     def ufl_domains(self):
         """Return UFL domains."""
@@ -193,7 +203,7 @@ class Coargument(BaseForm, BaseArgument):
         "_number",
         "_part",
         "_repr",
-        "_hash"
+        "_hash",
     )
 
     _primal = False
@@ -202,8 +212,10 @@ class Coargument(BaseForm, BaseArgument):
     def __new__(cls, *args, **kw):
         """Create a new Coargument."""
         if args[0] and is_primal(args[0]):
-            raise ValueError("ufl.Coargument takes in a dual space! If you want to define an argument "
-                             "in the primal space you should use ufl.Argument.")
+            raise ValueError(
+                "ufl.Coargument takes in a dual space! If you want to define an argument "
+                "in the primal space you should use ufl.Argument."
+            )
         return super().__new__(cls)
 
     def __init__(self, function_space, number, part=None):
@@ -214,7 +226,10 @@ def __init__(self, function_space, number, part=None):
         self.ufl_operands = ()
         self._hash = None
         self._repr = "Coargument(%s, %s, %s)" % (
-            repr(self._ufl_function_space), repr(self._number), repr(self._part))
+            repr(self._ufl_function_space),
+            repr(self._number),
+            repr(self._part),
+        )
 
     def arguments(self, outer_form=None):
         """Return all Argument objects found in form."""
@@ -228,8 +243,9 @@ def _analyze_form_arguments(self, outer_form=None):
         self._coefficients = ()
         # Coarguments map from V* to V*, i.e. V* -> V*, or equivalently V* x V -> R.
         # So they have one argument in the primal space and one in the dual space.
-        # However, when they are composed with linear forms with dual arguments, such as BaseFormOperators,
-        # the primal argument is discarded when analysing the argument as Coarguments.
+        # However, when they are composed with linear forms with dual
+        # arguments, such as BaseFormOperators, the primal argument is
+        # discarded when analysing the argument as Coarguments.
         if not outer_form:
             self._arguments = (Argument(self.ufl_function_space().dual(), 0), self)
         else:
@@ -245,15 +261,16 @@ def equals(self, other):
             return False
         if self is other:
             return True
-        return (self._ufl_function_space == other._ufl_function_space and  # noqa: W504
-                self._number == other._number and self._part == other._part)
+        return (
+            self._ufl_function_space == other._ufl_function_space
+            and self._number == other._number
+            and self._part == other._part
+        )
 
     def __hash__(self):
         """Hash."""
-        return hash(("Coargument",
-                     hash(self._ufl_function_space),
-                     self._number,
-                     self._part))
+        return hash(("Coargument", hash(self._ufl_function_space), self._number, self._part))
+
 
 # --- Helper functions for pretty syntax ---
 
@@ -270,14 +287,17 @@ def TrialFunction(function_space, part=None):
 
 # --- Helper functions for creating subfunctions on mixed elements ---
 
+
 def Arguments(function_space, number):
     """Create an Argument in a mixed space.
 
     Returns a tuple with the function components corresponding to the subelements.
     """
     if isinstance(function_space, MixedFunctionSpace):
-        return [Argument(function_space.ufl_sub_space(i), number, i)
-                for i in range(function_space.num_sub_spaces())]
+        return [
+            Argument(function_space.ufl_sub_space(i), number, i)
+            for i in range(function_space.num_sub_spaces())
+        ]
     else:
         return split(Argument(function_space, number))
 
@@ -285,7 +305,8 @@ def Arguments(function_space, number):
 def TestFunctions(function_space):
     """Create a TestFunction in a mixed space.
 
-    Returns a tuple with the function components corresponding to the subelements.
+    Returns a tuple with the function components corresponding to the
+    subelements.
     """
     return Arguments(function_space, 0)
 
@@ -293,6 +314,7 @@ def TestFunctions(function_space):
 def TrialFunctions(function_space):
     """Create a TrialFunction in a mixed space.
 
-    Returns a tuple with the function components corresponding to the subelements.
+    Returns a tuple with the function components corresponding to the
+    subelements.
     """
     return Arguments(function_space, 1)
diff --git a/ufl/averaging.py b/ufl/averaging.py
index 899cc3ca8..5c04c8912 100644
--- a/ufl/averaging.py
+++ b/ufl/averaging.py
@@ -11,10 +11,9 @@
 from ufl.core.ufl_type import ufl_type
 
 
-@ufl_type(inherit_shape_from_operand=0,
-          inherit_indices_from_operand=0,
-          num_ops=1,
-          is_evaluation=True)
+@ufl_type(
+    inherit_shape_from_operand=0, inherit_indices_from_operand=0, num_ops=1, is_evaluation=True
+)
 class CellAvg(Operator):
     """Cell average."""
 
@@ -37,18 +36,16 @@ def ufl_shape(self):
 
     def evaluate(self, x, mapping, component, index_values):
         """Performs an approximate symbolic evaluation, since we don't have a cell."""
-        return self.ufl_operands[0].evaluate(x, mapping, component,
-                                             index_values)
+        return self.ufl_operands[0].evaluate(x, mapping, component, index_values)
 
     def __str__(self):
         """Format as a string."""
         return f"cell_avg({self.ufl_operands[0]})"
 
 
-@ufl_type(inherit_shape_from_operand=0,
-          inherit_indices_from_operand=0,
-          num_ops=1,
-          is_evaluation=True)
+@ufl_type(
+    inherit_shape_from_operand=0, inherit_indices_from_operand=0, num_ops=1, is_evaluation=True
+)
 class FacetAvg(Operator):
     """Facet average."""
 
diff --git a/ufl/cell.py b/ufl/cell.py
index 3eebad7dd..d85c305e5 100644
--- a/ufl/cell.py
+++ b/ufl/cell.py
@@ -36,7 +36,11 @@ def has_simplex_facets(self) -> bool:
 
     @abstractmethod
     def _lt(self, other) -> bool:
-        """Define an arbitrarily chosen but fixed sort order for all instances of this type with the same dimensions."""
+        """Less than operator.
+
+        Define an arbitrarily chosen but fixed sort order for all
+        instances of this type with the same dimensions.
+        """
 
     @abstractmethod
     def num_sub_entities(self, dim: int) -> int:
@@ -181,29 +185,70 @@ def peak_types(self) -> typing.Tuple[AbstractCell, ...]:
 
 
 _sub_entity_celltypes = {
-    "vertex": [("vertex", )],
-    "interval": [tuple("vertex" for i in range(2)), ("interval", )],
-    "triangle": [tuple("vertex" for i in range(3)), tuple("interval" for i in range(3)), ("triangle", )],
-    "quadrilateral": [tuple("vertex" for i in range(4)), tuple("interval" for i in range(4)), ("quadrilateral", )],
-    "tetrahedron": [tuple("vertex" for i in range(4)), tuple("interval" for i in range(6)),
-                    tuple("triangle" for i in range(4)), ("tetrahedron", )],
-    "hexahedron": [tuple("vertex" for i in range(8)), tuple("interval" for i in range(12)),
-                   tuple("quadrilateral" for i in range(6)), ("hexahedron", )],
-    "prism": [tuple("vertex" for i in range(6)), tuple("interval" for i in range(9)),
-              ("triangle", "quadrilateral", "quadrilateral", "quadrilateral", "triangle"), ("prism", )],
-    "pyramid": [tuple("vertex" for i in range(5)), tuple("interval" for i in range(8)),
-                ("quadrilateral", "triangle", "triangle", "triangle", "triangle"), ("pyramid", )],
-    "pentatope": [tuple("vertex" for i in range(5)), tuple("interval" for i in range(10)),
-                  tuple("triangle" for i in range(10)), tuple("tetrahedron" for i in range(5)), ("pentatope", )],
-    "tesseract": [tuple("vertex" for i in range(16)), tuple("interval" for i in range(32)),
-                  tuple("quadrilateral" for i in range(24)), tuple("hexahedron" for i in range(8)), ("tesseract", )],
+    "vertex": [("vertex",)],
+    "interval": [tuple("vertex" for i in range(2)), ("interval",)],
+    "triangle": [
+        tuple("vertex" for i in range(3)),
+        tuple("interval" for i in range(3)),
+        ("triangle",),
+    ],
+    "quadrilateral": [
+        tuple("vertex" for i in range(4)),
+        tuple("interval" for i in range(4)),
+        ("quadrilateral",),
+    ],
+    "tetrahedron": [
+        tuple("vertex" for i in range(4)),
+        tuple("interval" for i in range(6)),
+        tuple("triangle" for i in range(4)),
+        ("tetrahedron",),
+    ],
+    "hexahedron": [
+        tuple("vertex" for i in range(8)),
+        tuple("interval" for i in range(12)),
+        tuple("quadrilateral" for i in range(6)),
+        ("hexahedron",),
+    ],
+    "prism": [
+        tuple("vertex" for i in range(6)),
+        tuple("interval" for i in range(9)),
+        ("triangle", "quadrilateral", "quadrilateral", "quadrilateral", "triangle"),
+        ("prism",),
+    ],
+    "pyramid": [
+        tuple("vertex" for i in range(5)),
+        tuple("interval" for i in range(8)),
+        ("quadrilateral", "triangle", "triangle", "triangle", "triangle"),
+        ("pyramid",),
+    ],
+    "pentatope": [
+        tuple("vertex" for i in range(5)),
+        tuple("interval" for i in range(10)),
+        tuple("triangle" for i in range(10)),
+        tuple("tetrahedron" for i in range(5)),
+        ("pentatope",),
+    ],
+    "tesseract": [
+        tuple("vertex" for i in range(16)),
+        tuple("interval" for i in range(32)),
+        tuple("quadrilateral" for i in range(24)),
+        tuple("hexahedron" for i in range(8)),
+        ("tesseract",),
+    ],
 }
 
 
 class Cell(AbstractCell):
     """Representation of a named finite element cell with known structure."""
-    __slots__ = ("_cellname", "_tdim", "_num_cell_entities", "_sub_entity_types",
-                 "_sub_entities", "_sub_entity_types")
+
+    __slots__ = (
+        "_cellname",
+        "_tdim",
+        "_num_cell_entities",
+        "_sub_entity_types",
+        "_sub_entities",
+        "_sub_entity_types",
+    )
 
     def __init__(self, cellname: str):
         """Initialise.
@@ -220,11 +265,12 @@ def __init__(self, cellname: str):
         self._tdim = len(self._sub_entity_celltypes) - 1
 
         self._num_cell_entities = [len(i) for i in self._sub_entity_celltypes]
-        self._sub_entities = [tuple(Cell(t) for t in se_types)
-                              for se_types in self._sub_entity_celltypes[:-1]]
+        self._sub_entities = [
+            tuple(Cell(t) for t in se_types) for se_types in self._sub_entity_celltypes[:-1]
+        ]
         self._sub_entity_types = [tuple(set(i)) for i in self._sub_entities]
-        self._sub_entities.append((weakref.proxy(self), ))
-        self._sub_entity_types.append((weakref.proxy(self), ))
+        self._sub_entities.append((weakref.proxy(self),))
+        self._sub_entity_types.append((weakref.proxy(self),))
 
         if not isinstance(self._tdim, numbers.Integral):
             raise ValueError("Expecting integer topological_dimension.")
@@ -285,7 +331,7 @@ def __repr__(self) -> str:
 
     def _ufl_hash_data_(self) -> typing.Hashable:
         """UFL hash data."""
-        return (self._cellname, )
+        return (self._cellname,)
 
     def reconstruct(self, **kwargs: typing.Any) -> Cell:
         """Reconstruct this cell, overwriting properties by those in kwargs."""
@@ -341,8 +387,9 @@ def num_sub_entities(self, dim: int) -> int:
         if dim == 0:
             return functools.reduce(lambda x, y: x * y, [c.num_vertices() for c in self._cells])
         if dim == self._tdim - 1:
-            # Note: This is not the number of facets that the cell has, but I'm leaving it here for now
-            # to not change past behaviour
+            # Note: This is not the number of facets that the cell has,
+            # but I'm leaving it here for now to not change past
+            # behaviour
             return sum(c.num_facets() for c in self._cells if c.topological_dimension() > 0)
         if dim == self._tdim:
             return 1
diff --git a/ufl/checks.py b/ufl/checks.py
index 5b4dc8ce1..09ae4453b 100644
--- a/ufl/checks.py
+++ b/ufl/checks.py
@@ -27,7 +27,9 @@ def is_ufl_scalar(expression):
 
 def is_true_ufl_scalar(expression):
     """Return True iff expression is scalar-valued, with no free indices."""
-    return isinstance(expression, Expr) and not (expression.ufl_shape or expression.ufl_free_indices)
+    return isinstance(expression, Expr) and not (
+        expression.ufl_shape or expression.ufl_free_indices
+    )
 
 
 def is_cellwise_constant(expr):
diff --git a/ufl/classes.py b/ufl/classes.py
index b65c802d4..b8f48516c 100644
--- a/ufl/classes.py
+++ b/ufl/classes.py
@@ -88,6 +88,7 @@ def populate_namespace_with_expr_classes(namespace):
 
 # Semi-automated imports of non-expr classes:
 
+
 def populate_namespace_with_module_classes(mod, loc):
     """Export the classes that submodules list in __all_classes__."""
     names = mod.__all_classes__
diff --git a/ufl/coefficient.py b/ufl/coefficient.py
index 956cd5159..8dbcfdb5a 100644
--- a/ufl/coefficient.py
+++ b/ufl/coefficient.py
@@ -47,8 +47,7 @@ def __init__(self, function_space, count=None):
         self._ufl_function_space = function_space
         self._ufl_shape = function_space.value_shape
 
-        self._repr = "BaseCoefficient(%s, %s)" % (
-            repr(self._ufl_function_space), repr(self._count))
+        self._repr = "BaseCoefficient(%s, %s)" % (repr(self._ufl_function_space), repr(self._count))
 
     @property
     def ufl_shape(self):
@@ -76,7 +75,11 @@ def ufl_domains(self):
         return self._ufl_function_space.ufl_domains()
 
     def _ufl_signature_data_(self, renumbering):
-        """Signature data for form arguments depend on the global numbering of the form arguments and domains."""
+        """Signature data.
+
+        Signature data for form arguments depend on the global numbering
+        of the form arguments and domains.
+        """
         count = renumbering[self]
         fsdata = self._ufl_function_space._ufl_signature_data_(renumbering)
         return ("Coefficient", count, fsdata)
@@ -111,7 +114,7 @@ class Cofunction(BaseCoefficient, BaseForm):
         "ufl_operands",
         "_repr",
         "_ufl_shape",
-        "_hash"
+        "_hash",
     )
     _primal = False
     _dual = True
@@ -121,8 +124,10 @@ class Cofunction(BaseCoefficient, BaseForm):
     def __new__(cls, *args, **kw):
         """Create a new Cofunction."""
         if args[0] and is_primal(args[0]):
-            raise ValueError("ufl.Cofunction takes in a dual space. If you want to define a coefficient "
-                             "in the primal space you should use ufl.Coefficient.")
+            raise ValueError(
+                "ufl.Cofunction takes in a dual space. If you want to define a coefficient "
+                "in the primal space you should use ufl.Coefficient."
+            )
         return super().__new__(cls)
 
     def __init__(self, function_space, count=None):
@@ -132,8 +137,7 @@ def __init__(self, function_space, count=None):
 
         self.ufl_operands = ()
         self._hash = None
-        self._repr = "Cofunction(%s, %s)" % (
-            repr(self._ufl_function_space), repr(self._count))
+        self._repr = "Cofunction(%s, %s)" % (repr(self._ufl_function_space), repr(self._count))
 
     def equals(self, other):
         """Check equality."""
@@ -145,9 +149,7 @@ def equals(self, other):
 
     def __hash__(self):
         """Hash."""
-        return hash(("Cofunction",
-                     hash(self._ufl_function_space),
-                     self._count))
+        return hash(("Cofunction", hash(self._ufl_function_space), self._count))
 
     def _analyze_form_arguments(self):
         """Analyze which Argument and Coefficient objects can be found in the form."""
@@ -180,8 +182,7 @@ def __init__(self, function_space, count=None):
         FormArgument.__init__(self)
         BaseCoefficient.__init__(self, function_space, count)
 
-        self._repr = "Coefficient(%s, %s)" % (
-            repr(self._ufl_function_space), repr(self._count))
+        self._repr = "Coefficient(%s, %s)" % (repr(self._ufl_function_space), repr(self._count))
 
     def ufl_domains(self):
         """Get the UFL domains."""
@@ -202,13 +203,16 @@ def __repr__(self):
 
 # --- Helper functions for subfunctions on mixed elements ---
 
+
 def Coefficients(function_space):
     """Create a Coefficient in a mixed space.
 
     Returns a tuple with the function components corresponding to the subelements.
     """
     if isinstance(function_space, MixedFunctionSpace):
-        return [Coefficient(fs) if is_primal(fs) else Cofunction(fs)
-                for fs in function_space.num_sub_spaces()]
+        return [
+            Coefficient(fs) if is_primal(fs) else Cofunction(fs)
+            for fs in function_space.num_sub_spaces()
+        ]
     else:
         return split(Coefficient(function_space))
diff --git a/ufl/compound_expressions.py b/ufl/compound_expressions.py
index 6b9c63402..5eedfdedf 100644
--- a/ufl/compound_expressions.py
+++ b/ufl/compound_expressions.py
@@ -1,4 +1,4 @@
-"""Functions implementing compound expressions as equivalent representations using basic operators."""
+"""Support for compound expressions as equivalent representations using basic operators."""
 # Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL (https://www.fenicsproject.org)
@@ -31,6 +31,7 @@ def cross_expr(a, b):
 
     def c(i, j):
         return a[i] * b[j] - a[j] * b[i]
+
     return as_vector((c(1, 2), c(2, 0), c(0, 1)))
 
 
@@ -114,9 +115,16 @@ def determinant_expr_2x2(B):
 
 def old_determinant_expr_3x3(A):
     """Determinant of a 3 by 3 matrix."""
-    warnings.warn("The use of old_determinant_expr_3x3 is deprecated and will be removed after December 2023. "
-                  "Please, use determinant_expr_3x3 instead", FutureWarning)
-    return A[0, 0] * _det_2x2(A, 1, 2, 1, 2) + A[0, 1] * _det_2x2(A, 1, 2, 2, 0) + A[0, 2] * _det_2x2(A, 1, 2, 0, 1)
+    warnings.warn(
+        "The use of old_determinant_expr_3x3 is deprecated and will be removed "
+        "after December 2023. Please, use determinant_expr_3x3 instead",
+        FutureWarning,
+    )
+    return (
+        A[0, 0] * _det_2x2(A, 1, 2, 1, 2)
+        + A[0, 1] * _det_2x2(A, 1, 2, 2, 0)
+        + A[0, 2] * _det_2x2(A, 1, 2, 0, 1)
+    )
 
 
 def determinant_expr_3x3(A):
@@ -139,8 +147,8 @@ def codeterminant_expr_nxn(A, rows, cols):
     r = rows[0]
     subrows = rows[1:]
     for i, c in enumerate(cols):
-        subcols = cols[:i] + cols[i + 1:]
-        codet += (-1)**i * A[r, c] * codeterminant_expr_nxn(A, subrows, subcols)
+        subcols = cols[:i] + cols[i + 1 :]
+        codet += (-1) ** i * A[r, c] * codeterminant_expr_nxn(A, subrows, subcols)
     return codet
 
 
@@ -176,50 +184,142 @@ def adj_expr(A):
 
 def adj_expr_2x2(A):
     """Adjoint of a 2 by 2 matrix."""
-    return as_matrix([[A[1, 1], -A[0, 1]],
-                      [-A[1, 0], A[0, 0]]])
+    return as_matrix([[A[1, 1], -A[0, 1]], [-A[1, 0], A[0, 0]]])
 
 
 def adj_expr_3x3(A):
     """Adjoint of a 3 by 3 matrix."""
-    return as_matrix([[
-        A[2, 2] * A[1, 1] - A[1, 2] * A[2, 1],
-        -A[0, 1] * A[2, 2] + A[0, 2] * A[2, 1],
-        A[0, 1] * A[1, 2] - A[0, 2] * A[1, 1],
-    ], [
-        -A[2, 2] * A[1, 0] + A[1, 2] * A[2, 0],
-        -A[0, 2] * A[2, 0] + A[2, 2] * A[0, 0],
-        A[0, 2] * A[1, 0] - A[1, 2] * A[0, 0],
-    ], [
-        A[1, 0] * A[2, 1] - A[2, 0] * A[1, 1],
-        A[0, 1] * A[2, 0] - A[0, 0] * A[2, 1],
-        A[0, 0] * A[1, 1] - A[0, 1] * A[1, 0],
-    ]])
+    return as_matrix(
+        [
+            [
+                A[2, 2] * A[1, 1] - A[1, 2] * A[2, 1],
+                -A[0, 1] * A[2, 2] + A[0, 2] * A[2, 1],
+                A[0, 1] * A[1, 2] - A[0, 2] * A[1, 1],
+            ],
+            [
+                -A[2, 2] * A[1, 0] + A[1, 2] * A[2, 0],
+                -A[0, 2] * A[2, 0] + A[2, 2] * A[0, 0],
+                A[0, 2] * A[1, 0] - A[1, 2] * A[0, 0],
+            ],
+            [
+                A[1, 0] * A[2, 1] - A[2, 0] * A[1, 1],
+                A[0, 1] * A[2, 0] - A[0, 0] * A[2, 1],
+                A[0, 0] * A[1, 1] - A[0, 1] * A[1, 0],
+            ],
+        ]
+    )
 
 
 def adj_expr_4x4(A):
     """Adjoint of a 4 by 4 matrix."""
-    return as_matrix([[
-        -A[3, 3] * A[2, 1] * A[1, 2] + A[1, 2] * A[3, 1] * A[2, 3] + A[1, 1] * A[3, 3] * A[2, 2] - A[3, 1] * A[2, 2] * A[1, 3] + A[2, 1] * A[1, 3] * A[3, 2] - A[1, 1] * A[3, 2] * A[2, 3],  # noqa: E501
-        -A[3, 1] * A[0, 2] * A[2, 3] + A[0, 1] * A[3, 2] * A[2, 3] - A[0, 3] * A[2, 1] * A[3, 2] + A[3, 3] * A[2, 1] * A[0, 2] - A[3, 3] * A[0, 1] * A[2, 2] + A[0, 3] * A[3, 1] * A[2, 2],  # noqa: E501
-        A[3, 1] * A[1, 3] * A[0, 2] + A[1, 1] * A[0, 3] * A[3, 2] - A[0, 3] * A[1, 2] * A[3, 1] - A[0, 1] * A[1, 3] * A[3, 2] + A[3, 3] * A[1, 2] * A[0, 1] - A[1, 1] * A[3, 3] * A[0, 2],  # noqa: E501
-        A[1, 1] * A[0, 2] * A[2, 3] - A[2, 1] * A[1, 3] * A[0, 2] + A[0, 3] * A[2, 1] * A[1, 2] - A[1, 2] * A[0, 1] * A[2, 3] - A[1, 1] * A[0, 3] * A[2, 2] + A[0, 1] * A[2, 2] * A[1, 3],  # noqa: E501
-    ], [
-        A[3, 3] * A[1, 2] * A[2, 0] - A[3, 0] * A[1, 2] * A[2, 3] + A[1, 0] * A[3, 2] * A[2, 3] - A[3, 3] * A[1, 0] * A[2, 2] - A[1, 3] * A[3, 2] * A[2, 0] + A[3, 0] * A[2, 2] * A[1, 3],  # noqa: E501
-        A[0, 3] * A[3, 2] * A[2, 0] - A[0, 3] * A[3, 0] * A[2, 2] + A[3, 3] * A[0, 0] * A[2, 2] + A[3, 0] * A[0, 2] * A[2, 3] - A[0, 0] * A[3, 2] * A[2, 3] - A[3, 3] * A[0, 2] * A[2, 0],  # noqa: E501
-        -A[3, 3] * A[0, 0] * A[1, 2] + A[0, 0] * A[1, 3] * A[3, 2] - A[3, 0] * A[1, 3] * A[0, 2] + A[3, 3] * A[1, 0] * A[0, 2] + A[0, 3] * A[3, 0] * A[1, 2] - A[0, 3] * A[1, 0] * A[3, 2],  # noqa: E501
-        A[0, 3] * A[1, 0] * A[2, 2] + A[1, 3] * A[0, 2] * A[2, 0] - A[0, 0] * A[2, 2] * A[1, 3] - A[0, 3] * A[1, 2] * A[2, 0] + A[0, 0] * A[1, 2] * A[2, 3] - A[1, 0] * A[0, 2] * A[2, 3],  # noqa: E501
-    ], [
-        A[3, 1] * A[1, 3] * A[2, 0] + A[3, 3] * A[2, 1] * A[1, 0] + A[1, 1] * A[3, 0] * A[2, 3] - A[1, 0] * A[3, 1] * A[2, 3] - A[3, 0] * A[2, 1] * A[1, 3] - A[1, 1] * A[3, 3] * A[2, 0],  # noqa: E501
-        A[3, 3] * A[0, 1] * A[2, 0] - A[3, 3] * A[0, 0] * A[2, 1] - A[0, 3] * A[3, 1] * A[2, 0] - A[3, 0] * A[0, 1] * A[2, 3] + A[0, 0] * A[3, 1] * A[2, 3] + A[0, 3] * A[3, 0] * A[2, 1],  # noqa: E501
-        -A[0, 0] * A[3, 1] * A[1, 3] + A[0, 3] * A[1, 0] * A[3, 1] - A[3, 3] * A[1, 0] * A[0, 1] + A[1, 1] * A[3, 3] * A[0, 0] - A[1, 1] * A[0, 3] * A[3, 0] + A[3, 0] * A[0, 1] * A[1, 3],  # noqa: E501
-        A[0, 0] * A[2, 1] * A[1, 3] + A[1, 0] * A[0, 1] * A[2, 3] - A[0, 3] * A[2, 1] * A[1, 0] + A[1, 1] * A[0, 3] * A[2, 0] - A[1, 1] * A[0, 0] * A[2, 3] - A[0, 1] * A[1, 3] * A[2, 0],  # noqa: E501
-    ], [
-        -A[1, 2] * A[3, 1] * A[2, 0] - A[2, 1] * A[1, 0] * A[3, 2] + A[3, 0] * A[2, 1] * A[1, 2] - A[1, 1] * A[3, 0] * A[2, 2] + A[1, 0] * A[3, 1] * A[2, 2] + A[1, 1] * A[3, 2] * A[2, 0],  # noqa: E501
-        -A[3, 0] * A[2, 1] * A[0, 2] - A[0, 1] * A[3, 2] * A[2, 0] + A[3, 1] * A[0, 2] * A[2, 0] - A[0, 0] * A[3, 1] * A[2, 2] + A[3, 0] * A[0, 1] * A[2, 2] + A[0, 0] * A[2, 1] * A[3, 2],  # noqa: E501
-        A[0, 0] * A[1, 2] * A[3, 1] - A[1, 0] * A[3, 1] * A[0, 2] + A[1, 1] * A[3, 0] * A[0, 2] + A[1, 0] * A[0, 1] * A[3, 2] - A[3, 0] * A[1, 2] * A[0, 1] - A[1, 1] * A[0, 0] * A[3, 2],  # noqa: E501
-        -A[1, 1] * A[0, 2] * A[2, 0] + A[2, 1] * A[1, 0] * A[0, 2] + A[1, 2] * A[0, 1] * A[2, 0] + A[1, 1] * A[0, 0] * A[2, 2] - A[1, 0] * A[0, 1] * A[2, 2] - A[0, 0] * A[2, 1] * A[1, 2],  # noqa: E501
-    ]])
+    return as_matrix(
+        [
+            [
+                -A[3, 3] * A[2, 1] * A[1, 2]
+                + A[1, 2] * A[3, 1] * A[2, 3]
+                + A[1, 1] * A[3, 3] * A[2, 2]
+                - A[3, 1] * A[2, 2] * A[1, 3]
+                + A[2, 1] * A[1, 3] * A[3, 2]
+                - A[1, 1] * A[3, 2] * A[2, 3],
+                -A[3, 1] * A[0, 2] * A[2, 3]
+                + A[0, 1] * A[3, 2] * A[2, 3]
+                - A[0, 3] * A[2, 1] * A[3, 2]
+                + A[3, 3] * A[2, 1] * A[0, 2]
+                - A[3, 3] * A[0, 1] * A[2, 2]
+                + A[0, 3] * A[3, 1] * A[2, 2],
+                A[3, 1] * A[1, 3] * A[0, 2]
+                + A[1, 1] * A[0, 3] * A[3, 2]
+                - A[0, 3] * A[1, 2] * A[3, 1]
+                - A[0, 1] * A[1, 3] * A[3, 2]
+                + A[3, 3] * A[1, 2] * A[0, 1]
+                - A[1, 1] * A[3, 3] * A[0, 2],
+                A[1, 1] * A[0, 2] * A[2, 3]
+                - A[2, 1] * A[1, 3] * A[0, 2]
+                + A[0, 3] * A[2, 1] * A[1, 2]
+                - A[1, 2] * A[0, 1] * A[2, 3]
+                - A[1, 1] * A[0, 3] * A[2, 2]
+                + A[0, 1] * A[2, 2] * A[1, 3],
+            ],
+            [
+                A[3, 3] * A[1, 2] * A[2, 0]
+                - A[3, 0] * A[1, 2] * A[2, 3]
+                + A[1, 0] * A[3, 2] * A[2, 3]
+                - A[3, 3] * A[1, 0] * A[2, 2]
+                - A[1, 3] * A[3, 2] * A[2, 0]
+                + A[3, 0] * A[2, 2] * A[1, 3],
+                A[0, 3] * A[3, 2] * A[2, 0]
+                - A[0, 3] * A[3, 0] * A[2, 2]
+                + A[3, 3] * A[0, 0] * A[2, 2]
+                + A[3, 0] * A[0, 2] * A[2, 3]
+                - A[0, 0] * A[3, 2] * A[2, 3]
+                - A[3, 3] * A[0, 2] * A[2, 0],
+                -A[3, 3] * A[0, 0] * A[1, 2]
+                + A[0, 0] * A[1, 3] * A[3, 2]
+                - A[3, 0] * A[1, 3] * A[0, 2]
+                + A[3, 3] * A[1, 0] * A[0, 2]
+                + A[0, 3] * A[3, 0] * A[1, 2]
+                - A[0, 3] * A[1, 0] * A[3, 2],
+                A[0, 3] * A[1, 0] * A[2, 2]
+                + A[1, 3] * A[0, 2] * A[2, 0]
+                - A[0, 0] * A[2, 2] * A[1, 3]
+                - A[0, 3] * A[1, 2] * A[2, 0]
+                + A[0, 0] * A[1, 2] * A[2, 3]
+                - A[1, 0] * A[0, 2] * A[2, 3],
+            ],
+            [
+                A[3, 1] * A[1, 3] * A[2, 0]
+                + A[3, 3] * A[2, 1] * A[1, 0]
+                + A[1, 1] * A[3, 0] * A[2, 3]
+                - A[1, 0] * A[3, 1] * A[2, 3]
+                - A[3, 0] * A[2, 1] * A[1, 3]
+                - A[1, 1] * A[3, 3] * A[2, 0],
+                A[3, 3] * A[0, 1] * A[2, 0]
+                - A[3, 3] * A[0, 0] * A[2, 1]
+                - A[0, 3] * A[3, 1] * A[2, 0]
+                - A[3, 0] * A[0, 1] * A[2, 3]
+                + A[0, 0] * A[3, 1] * A[2, 3]
+                + A[0, 3] * A[3, 0] * A[2, 1],
+                -A[0, 0] * A[3, 1] * A[1, 3]
+                + A[0, 3] * A[1, 0] * A[3, 1]
+                - A[3, 3] * A[1, 0] * A[0, 1]
+                + A[1, 1] * A[3, 3] * A[0, 0]
+                - A[1, 1] * A[0, 3] * A[3, 0]
+                + A[3, 0] * A[0, 1] * A[1, 3],
+                A[0, 0] * A[2, 1] * A[1, 3]
+                + A[1, 0] * A[0, 1] * A[2, 3]
+                - A[0, 3] * A[2, 1] * A[1, 0]
+                + A[1, 1] * A[0, 3] * A[2, 0]
+                - A[1, 1] * A[0, 0] * A[2, 3]
+                - A[0, 1] * A[1, 3] * A[2, 0],
+            ],
+            [
+                -A[1, 2] * A[3, 1] * A[2, 0]
+                - A[2, 1] * A[1, 0] * A[3, 2]
+                + A[3, 0] * A[2, 1] * A[1, 2]
+                - A[1, 1] * A[3, 0] * A[2, 2]
+                + A[1, 0] * A[3, 1] * A[2, 2]
+                + A[1, 1] * A[3, 2] * A[2, 0],
+                -A[3, 0] * A[2, 1] * A[0, 2]
+                - A[0, 1] * A[3, 2] * A[2, 0]
+                + A[3, 1] * A[0, 2] * A[2, 0]
+                - A[0, 0] * A[3, 1] * A[2, 2]
+                + A[3, 0] * A[0, 1] * A[2, 2]
+                + A[0, 0] * A[2, 1] * A[3, 2],
+                A[0, 0] * A[1, 2] * A[3, 1]
+                - A[1, 0] * A[3, 1] * A[0, 2]
+                + A[1, 1] * A[3, 0] * A[0, 2]
+                + A[1, 0] * A[0, 1] * A[3, 2]
+                - A[3, 0] * A[1, 2] * A[0, 1]
+                - A[1, 1] * A[0, 0] * A[3, 2],
+                -A[1, 1] * A[0, 2] * A[2, 0]
+                + A[2, 1] * A[1, 0] * A[0, 2]
+                + A[1, 2] * A[0, 1] * A[2, 0]
+                + A[1, 1] * A[0, 0] * A[2, 2]
+                - A[1, 0] * A[0, 1] * A[2, 2]
+                - A[0, 0] * A[2, 1] * A[1, 2],
+            ],
+        ]
+    )
 
 
 def cofactor_expr(A):
@@ -240,50 +340,142 @@ def cofactor_expr(A):
 
 def cofactor_expr_2x2(A):
     """Cofactor of a 2 by 2 matrix."""
-    return as_matrix([[A[1, 1], -A[1, 0]],
-                      [-A[0, 1], A[0, 0]]])
+    return as_matrix([[A[1, 1], -A[1, 0]], [-A[0, 1], A[0, 0]]])
 
 
 def cofactor_expr_3x3(A):
     """Cofactor of a 3 by 3 matrix."""
-    return as_matrix([[
-        A[1, 1] * A[2, 2] - A[2, 1] * A[1, 2],
-        A[2, 0] * A[1, 2] - A[1, 0] * A[2, 2],
-        -A[2, 0] * A[1, 1] + A[1, 0] * A[2, 1],
-    ], [
-        A[2, 1] * A[0, 2] - A[0, 1] * A[2, 2],
-        A[0, 0] * A[2, 2] - A[2, 0] * A[0, 2],
-        -A[0, 0] * A[2, 1] + A[2, 0] * A[0, 1],
-    ], [
-        A[0, 1] * A[1, 2] - A[1, 1] * A[0, 2],
-        A[1, 0] * A[0, 2] - A[0, 0] * A[1, 2],
-        -A[1, 0] * A[0, 1] + A[0, 0] * A[1, 1],
-    ]])
+    return as_matrix(
+        [
+            [
+                A[1, 1] * A[2, 2] - A[2, 1] * A[1, 2],
+                A[2, 0] * A[1, 2] - A[1, 0] * A[2, 2],
+                -A[2, 0] * A[1, 1] + A[1, 0] * A[2, 1],
+            ],
+            [
+                A[2, 1] * A[0, 2] - A[0, 1] * A[2, 2],
+                A[0, 0] * A[2, 2] - A[2, 0] * A[0, 2],
+                -A[0, 0] * A[2, 1] + A[2, 0] * A[0, 1],
+            ],
+            [
+                A[0, 1] * A[1, 2] - A[1, 1] * A[0, 2],
+                A[1, 0] * A[0, 2] - A[0, 0] * A[1, 2],
+                -A[1, 0] * A[0, 1] + A[0, 0] * A[1, 1],
+            ],
+        ]
+    )
 
 
 def cofactor_expr_4x4(A):
     """Cofactor of a 4 by 4 matrix."""
-    return as_matrix([[
-        -A[3, 1] * A[2, 2] * A[1, 3] - A[3, 2] * A[2, 3] * A[1, 1] + A[1, 3] * A[3, 2] * A[2, 1] + A[3, 1] * A[2, 3] * A[1, 2] + A[2, 2] * A[1, 1] * A[3, 3] - A[3, 3] * A[2, 1] * A[1, 2],  # noqa: E501
-        -A[1, 0] * A[2, 2] * A[3, 3] + A[2, 0] * A[3, 3] * A[1, 2] + A[2, 2] * A[1, 3] * A[3, 0] - A[2, 3] * A[3, 0] * A[1, 2] + A[1, 0] * A[3, 2] * A[2, 3] - A[1, 3] * A[3, 2] * A[2, 0],  # noqa: E501
-        A[1, 0] * A[3, 3] * A[2, 1] + A[2, 3] * A[1, 1] * A[3, 0] - A[2, 0] * A[1, 1] * A[3, 3] - A[1, 3] * A[3, 0] * A[2, 1] - A[1, 0] * A[3, 1] * A[2, 3] + A[3, 1] * A[1, 3] * A[2, 0],  # noqa: E501
-        A[3, 0] * A[2, 1] * A[1, 2] + A[1, 0] * A[3, 1] * A[2, 2] + A[3, 2] * A[2, 0] * A[1, 1] - A[2, 2] * A[1, 1] * A[3, 0] - A[3, 1] * A[2, 0] * A[1, 2] - A[1, 0] * A[3, 2] * A[2, 1],  # noqa: E501
-    ], [
-        A[3, 1] * A[2, 2] * A[0, 3] + A[0, 2] * A[3, 3] * A[2, 1] + A[0, 1] * A[3, 2] * A[2, 3] - A[3, 1] * A[0, 2] * A[2, 3] - A[0, 1] * A[2, 2] * A[3, 3] - A[3, 2] * A[0, 3] * A[2, 1],  # noqa: E501
-        -A[2, 2] * A[0, 3] * A[3, 0] - A[0, 2] * A[2, 0] * A[3, 3] - A[3, 2] * A[2, 3] * A[0, 0] + A[2, 2] * A[3, 3] * A[0, 0] + A[0, 2] * A[2, 3] * A[3, 0] + A[3, 2] * A[2, 0] * A[0, 3],  # noqa: E501
-        A[3, 1] * A[2, 3] * A[0, 0] - A[0, 1] * A[2, 3] * A[3, 0] - A[3, 1] * A[2, 0] * A[0, 3] - A[3, 3] * A[0, 0] * A[2, 1] + A[0, 3] * A[3, 0] * A[2, 1] + A[0, 1] * A[2, 0] * A[3, 3],  # noqa: E501
-        A[3, 2] * A[0, 0] * A[2, 1] - A[0, 2] * A[3, 0] * A[2, 1] + A[0, 1] * A[2, 2] * A[3, 0] + A[3, 1] * A[0, 2] * A[2, 0] - A[0, 1] * A[3, 2] * A[2, 0] - A[3, 1] * A[2, 2] * A[0, 0],  # noqa: E501
-    ], [
-        A[3, 1] * A[1, 3] * A[0, 2] - A[0, 2] * A[1, 1] * A[3, 3] - A[3, 1] * A[0, 3] * A[1, 2] + A[3, 2] * A[1, 1] * A[0, 3] + A[0, 1] * A[3, 3] * A[1, 2] - A[0, 1] * A[1, 3] * A[3, 2],  # noqa: E501
-        A[1, 3] * A[3, 2] * A[0, 0] - A[1, 0] * A[3, 2] * A[0, 3] - A[1, 3] * A[0, 2] * A[3, 0] + A[0, 3] * A[3, 0] * A[1, 2] + A[1, 0] * A[0, 2] * A[3, 3] - A[3, 3] * A[0, 0] * A[1, 2],  # noqa: E501
-        -A[1, 0] * A[0, 1] * A[3, 3] + A[0, 1] * A[1, 3] * A[3, 0] - A[3, 1] * A[1, 3] * A[0, 0] - A[1, 1] * A[0, 3] * A[3, 0] + A[1, 0] * A[3, 1] * A[0, 3] + A[1, 1] * A[3, 3] * A[0, 0],  # noqa: E501
-        A[0, 2] * A[1, 1] * A[3, 0] - A[3, 2] * A[1, 1] * A[0, 0] - A[0, 1] * A[3, 0] * A[1, 2] - A[1, 0] * A[3, 1] * A[0, 2] + A[3, 1] * A[0, 0] * A[1, 2] + A[1, 0] * A[0, 1] * A[3, 2],  # noqa: E501
-    ], [
-        A[0, 3] * A[2, 1] * A[1, 2] + A[0, 2] * A[2, 3] * A[1, 1] + A[0, 1] * A[2, 2] * A[1, 3] - A[2, 2] * A[1, 1] * A[0, 3] - A[1, 3] * A[0, 2] * A[2, 1] - A[0, 1] * A[2, 3] * A[1, 2],  # noqa: E501
-        A[1, 0] * A[2, 2] * A[0, 3] + A[1, 3] * A[0, 2] * A[2, 0] - A[1, 0] * A[0, 2] * A[2, 3] - A[2, 0] * A[0, 3] * A[1, 2] - A[2, 2] * A[1, 3] * A[0, 0] + A[2, 3] * A[0, 0] * A[1, 2],  # noqa: E501
-        -A[0, 1] * A[1, 3] * A[2, 0] + A[2, 0] * A[1, 1] * A[0, 3] + A[1, 3] * A[0, 0] * A[2, 1] - A[1, 0] * A[0, 3] * A[2, 1] + A[1, 0] * A[0, 1] * A[2, 3] - A[2, 3] * A[1, 1] * A[0, 0],  # noqa: E501
-        A[1, 0] * A[0, 2] * A[2, 1] - A[0, 2] * A[2, 0] * A[1, 1] + A[0, 1] * A[2, 0] * A[1, 2] + A[2, 2] * A[1, 1] * A[0, 0] - A[1, 0] * A[0, 1] * A[2, 2] - A[0, 0] * A[2, 1] * A[1, 2],  # noqa: E501
-    ]])
+    return as_matrix(
+        [
+            [
+                -A[3, 1] * A[2, 2] * A[1, 3]
+                - A[3, 2] * A[2, 3] * A[1, 1]
+                + A[1, 3] * A[3, 2] * A[2, 1]
+                + A[3, 1] * A[2, 3] * A[1, 2]
+                + A[2, 2] * A[1, 1] * A[3, 3]
+                - A[3, 3] * A[2, 1] * A[1, 2],
+                -A[1, 0] * A[2, 2] * A[3, 3]
+                + A[2, 0] * A[3, 3] * A[1, 2]
+                + A[2, 2] * A[1, 3] * A[3, 0]
+                - A[2, 3] * A[3, 0] * A[1, 2]
+                + A[1, 0] * A[3, 2] * A[2, 3]
+                - A[1, 3] * A[3, 2] * A[2, 0],
+                A[1, 0] * A[3, 3] * A[2, 1]
+                + A[2, 3] * A[1, 1] * A[3, 0]
+                - A[2, 0] * A[1, 1] * A[3, 3]
+                - A[1, 3] * A[3, 0] * A[2, 1]
+                - A[1, 0] * A[3, 1] * A[2, 3]
+                + A[3, 1] * A[1, 3] * A[2, 0],
+                A[3, 0] * A[2, 1] * A[1, 2]
+                + A[1, 0] * A[3, 1] * A[2, 2]
+                + A[3, 2] * A[2, 0] * A[1, 1]
+                - A[2, 2] * A[1, 1] * A[3, 0]
+                - A[3, 1] * A[2, 0] * A[1, 2]
+                - A[1, 0] * A[3, 2] * A[2, 1],
+            ],
+            [
+                A[3, 1] * A[2, 2] * A[0, 3]
+                + A[0, 2] * A[3, 3] * A[2, 1]
+                + A[0, 1] * A[3, 2] * A[2, 3]
+                - A[3, 1] * A[0, 2] * A[2, 3]
+                - A[0, 1] * A[2, 2] * A[3, 3]
+                - A[3, 2] * A[0, 3] * A[2, 1],
+                -A[2, 2] * A[0, 3] * A[3, 0]
+                - A[0, 2] * A[2, 0] * A[3, 3]
+                - A[3, 2] * A[2, 3] * A[0, 0]
+                + A[2, 2] * A[3, 3] * A[0, 0]
+                + A[0, 2] * A[2, 3] * A[3, 0]
+                + A[3, 2] * A[2, 0] * A[0, 3],
+                A[3, 1] * A[2, 3] * A[0, 0]
+                - A[0, 1] * A[2, 3] * A[3, 0]
+                - A[3, 1] * A[2, 0] * A[0, 3]
+                - A[3, 3] * A[0, 0] * A[2, 1]
+                + A[0, 3] * A[3, 0] * A[2, 1]
+                + A[0, 1] * A[2, 0] * A[3, 3],
+                A[3, 2] * A[0, 0] * A[2, 1]
+                - A[0, 2] * A[3, 0] * A[2, 1]
+                + A[0, 1] * A[2, 2] * A[3, 0]
+                + A[3, 1] * A[0, 2] * A[2, 0]
+                - A[0, 1] * A[3, 2] * A[2, 0]
+                - A[3, 1] * A[2, 2] * A[0, 0],
+            ],
+            [
+                A[3, 1] * A[1, 3] * A[0, 2]
+                - A[0, 2] * A[1, 1] * A[3, 3]
+                - A[3, 1] * A[0, 3] * A[1, 2]
+                + A[3, 2] * A[1, 1] * A[0, 3]
+                + A[0, 1] * A[3, 3] * A[1, 2]
+                - A[0, 1] * A[1, 3] * A[3, 2],
+                A[1, 3] * A[3, 2] * A[0, 0]
+                - A[1, 0] * A[3, 2] * A[0, 3]
+                - A[1, 3] * A[0, 2] * A[3, 0]
+                + A[0, 3] * A[3, 0] * A[1, 2]
+                + A[1, 0] * A[0, 2] * A[3, 3]
+                - A[3, 3] * A[0, 0] * A[1, 2],
+                -A[1, 0] * A[0, 1] * A[3, 3]
+                + A[0, 1] * A[1, 3] * A[3, 0]
+                - A[3, 1] * A[1, 3] * A[0, 0]
+                - A[1, 1] * A[0, 3] * A[3, 0]
+                + A[1, 0] * A[3, 1] * A[0, 3]
+                + A[1, 1] * A[3, 3] * A[0, 0],
+                A[0, 2] * A[1, 1] * A[3, 0]
+                - A[3, 2] * A[1, 1] * A[0, 0]
+                - A[0, 1] * A[3, 0] * A[1, 2]
+                - A[1, 0] * A[3, 1] * A[0, 2]
+                + A[3, 1] * A[0, 0] * A[1, 2]
+                + A[1, 0] * A[0, 1] * A[3, 2],
+            ],
+            [
+                A[0, 3] * A[2, 1] * A[1, 2]
+                + A[0, 2] * A[2, 3] * A[1, 1]
+                + A[0, 1] * A[2, 2] * A[1, 3]
+                - A[2, 2] * A[1, 1] * A[0, 3]
+                - A[1, 3] * A[0, 2] * A[2, 1]
+                - A[0, 1] * A[2, 3] * A[1, 2],
+                A[1, 0] * A[2, 2] * A[0, 3]
+                + A[1, 3] * A[0, 2] * A[2, 0]
+                - A[1, 0] * A[0, 2] * A[2, 3]
+                - A[2, 0] * A[0, 3] * A[1, 2]
+                - A[2, 2] * A[1, 3] * A[0, 0]
+                + A[2, 3] * A[0, 0] * A[1, 2],
+                -A[0, 1] * A[1, 3] * A[2, 0]
+                + A[2, 0] * A[1, 1] * A[0, 3]
+                + A[1, 3] * A[0, 0] * A[2, 1]
+                - A[1, 0] * A[0, 3] * A[2, 1]
+                + A[1, 0] * A[0, 1] * A[2, 3]
+                - A[2, 3] * A[1, 1] * A[0, 0],
+                A[1, 0] * A[0, 2] * A[2, 1]
+                - A[0, 2] * A[2, 0] * A[1, 1]
+                + A[0, 1] * A[2, 0] * A[1, 2]
+                + A[2, 2] * A[1, 1] * A[0, 0]
+                - A[1, 0] * A[0, 1] * A[2, 2]
+                - A[0, 0] * A[2, 1] * A[1, 2],
+            ],
+        ]
+    )
 
 
 def deviatoric_expr(A):
@@ -302,12 +494,20 @@ def deviatoric_expr(A):
 
 def deviatoric_expr_2x2(A):
     """Deviatoric of a 2 by 2 matrix."""
-    return as_matrix([[-1. / 2 * A[1, 1] + 1. / 2 * A[0, 0], A[0, 1]],
-                      [A[1, 0], 1. / 2 * A[1, 1] - 1. / 2 * A[0, 0]]])
+    return as_matrix(
+        [
+            [-1.0 / 2 * A[1, 1] + 1.0 / 2 * A[0, 0], A[0, 1]],
+            [A[1, 0], 1.0 / 2 * A[1, 1] - 1.0 / 2 * A[0, 0]],
+        ]
+    )
 
 
 def deviatoric_expr_3x3(A):
     """Deviatoric of a 3 by 3 matrix."""
-    return as_matrix([[-1. / 3 * A[1, 1] - 1. / 3 * A[2, 2] + 2. / 3 * A[0, 0], A[0, 1], A[0, 2]],
-                      [A[1, 0], 2. / 3 * A[1, 1] - 1. / 3 * A[2, 2] - 1. / 3 * A[0, 0], A[1, 2]],
-                      [A[2, 0], A[2, 1], -1. / 3 * A[1, 1] + 2. / 3 * A[2, 2] - 1. / 3 * A[0, 0]]])
+    return as_matrix(
+        [
+            [-1.0 / 3 * A[1, 1] - 1.0 / 3 * A[2, 2] + 2.0 / 3 * A[0, 0], A[0, 1], A[0, 2]],
+            [A[1, 0], 2.0 / 3 * A[1, 1] - 1.0 / 3 * A[2, 2] - 1.0 / 3 * A[0, 0], A[1, 2]],
+            [A[2, 0], A[2, 1], -1.0 / 3 * A[1, 1] + 2.0 / 3 * A[2, 2] - 1.0 / 3 * A[0, 0]],
+        ]
+    )
diff --git a/ufl/conditional.py b/ufl/conditional.py
index 5d0fb910d..117808c2b 100644
--- a/ufl/conditional.py
+++ b/ufl/conditional.py
@@ -43,7 +43,7 @@ def __bool__(self):
 class BinaryCondition(Condition):
     """Binary condition."""
 
-    __slots__ = ('_name',)
+    __slots__ = ("_name",)
 
     def __init__(self, name, left, right):
         """Initialise."""
@@ -54,13 +54,13 @@ def __init__(self, name, left, right):
 
         self._name = name
 
-        if name in ('!=', '=='):
+        if name in ("!=", "=="):
             # Since equals and not-equals are used for comparing
             # representations, we have to allow any shape here. The
             # scalar properties must be checked when used in
             # conditional instead!
             pass
-        elif name in ('&&', '||'):
+        elif name in ("&&", "||"):
             # Binary operators acting on boolean expressions allow
             # only conditions
             for arg in (left, right):
@@ -76,8 +76,11 @@ def __init__(self, name, left, right):
 
     def __str__(self):
         """Format as a string."""
-        return "%s %s %s" % (parstr(self.ufl_operands[0], self),
-                             self._name, parstr(self.ufl_operands[1], self))
+        return "%s %s %s" % (
+            parstr(self.ufl_operands[0], self),
+            self._name,
+            parstr(self.ufl_operands[1], self),
+        )
 
 
 # Not associating with __eq__, the concept of equality with == is
@@ -254,8 +257,7 @@ def __str__(self):
         return "!(%s)" % (str(self.ufl_operands[0]),)
 
 
-@ufl_type(num_ops=3, inherit_shape_from_operand=1,
-          inherit_indices_from_operand=1)
+@ufl_type(num_ops=3, inherit_shape_from_operand=1, inherit_indices_from_operand=1)
 class Conditional(Operator):
     """Conditional expression.
 
@@ -279,10 +281,14 @@ def __init__(self, condition, true_value, false_value):
         if tfi != ffi:
             raise ValueError("Free index mismatch between conditional branches.")
         if isinstance(condition, (EQ, NE)):
-            if not all((condition.ufl_operands[0].ufl_shape == (),
-                        condition.ufl_operands[0].ufl_free_indices == (),
-                        condition.ufl_operands[1].ufl_shape == (),
-                        condition.ufl_operands[1].ufl_free_indices == ())):
+            if not all(
+                (
+                    condition.ufl_operands[0].ufl_shape == (),
+                    condition.ufl_operands[0].ufl_free_indices == (),
+                    condition.ufl_operands[1].ufl_shape == (),
+                    condition.ufl_operands[1].ufl_free_indices == (),
+                )
+            ):
                 raise ValueError("Non-scalar == or != is not allowed.")
 
         Operator.__init__(self, (condition, true_value, false_value))
@@ -303,6 +309,7 @@ def __str__(self):
 
 # --- Specific functions higher level than a conditional ---
 
+
 @ufl_type(is_scalar=True, num_ops=1)
 class MinValue(Operator):
     """Take the minimum of two values."""
@@ -323,7 +330,7 @@ def evaluate(self, x, mapping, component, index_values):
         try:
             res = min(a, b)
         except ValueError:
-            warnings.warn('Value error in evaluation of min() of %s and %s.' % self.ufl_operands)
+            warnings.warn("Value error in evaluation of min() of %s and %s." % self.ufl_operands)
             raise
         return res
 
@@ -352,7 +359,7 @@ def evaluate(self, x, mapping, component, index_values):
         try:
             res = max(a, b)
         except ValueError:
-            warnings.warn('Value error in evaluation of max() of %s and %s.' % self.ufl_operands)
+            warnings.warn("Value error in evaluation of max() of %s and %s." % self.ufl_operands)
             raise
         return res
 
diff --git a/ufl/constant.py b/ufl/constant.py
index 74eb81932..e9d658fcc 100644
--- a/ufl/constant.py
+++ b/ufl/constant.py
@@ -1,4 +1,4 @@
-"""This module defines classes representing non-literal values which are constant with respect to a domain."""
+"""Support fpr non-literal values which are constant with respect to a domain."""
 
 # Copyright (C) 2019 Michal Habera
 #
@@ -29,7 +29,8 @@ def __init__(self, domain, shape=(), count=None):
         # Repr string is build in such way, that reconstruction
         # with eval() is possible
         self._repr = "Constant({}, {}, {})".format(
-            repr(self._ufl_domain), repr(self._ufl_shape), repr(self._count))
+            repr(self._ufl_domain), repr(self._ufl_shape), repr(self._count)
+        )
 
     @property
     def ufl_shape(self):
@@ -42,7 +43,7 @@ def ufl_domain(self):
 
     def ufl_domains(self):
         """Get the UFL domains."""
-        return (self.ufl_domain(), )
+        return (self.ufl_domain(),)
 
     def is_cellwise_constant(self):
         """Return True if the function is cellwise constant."""
@@ -62,23 +63,30 @@ def __eq__(self, other):
             return False
         if self is other:
             return True
-        return (self._count == other._count and self._ufl_domain == other._ufl_domain and   # noqa: W504
-                self._ufl_shape == self._ufl_shape)
+        return (
+            self._count == other._count
+            and self._ufl_domain == other._ufl_domain
+            and self._ufl_shape == self._ufl_shape
+        )
 
     def _ufl_signature_data_(self, renumbering):
         """Signature data for constant depends on renumbering."""
         return "Constant({}, {}, {})".format(
-            self._ufl_domain._ufl_signature_data_(renumbering), repr(self._ufl_shape),
-            repr(renumbering[self]))
+            self._ufl_domain._ufl_signature_data_(renumbering),
+            repr(self._ufl_shape),
+            repr(renumbering[self]),
+        )
 
 
 def VectorConstant(domain, count=None):
     """Vector constant."""
     domain = as_domain(domain)
-    return Constant(domain, shape=(domain.geometric_dimension(), ), count=count)
+    return Constant(domain, shape=(domain.geometric_dimension(),), count=count)
 
 
 def TensorConstant(domain, count=None):
     """Tensor constant."""
     domain = as_domain(domain)
-    return Constant(domain, shape=(domain.geometric_dimension(), domain.geometric_dimension()), count=count)
+    return Constant(
+        domain, shape=(domain.geometric_dimension(), domain.geometric_dimension()), count=count
+    )
diff --git a/ufl/constantvalue.py b/ufl/constantvalue.py
index 82d9ed84e..0aa320d8f 100644
--- a/ufl/constantvalue.py
+++ b/ufl/constantvalue.py
@@ -12,6 +12,7 @@
 from math import atan2
 
 import ufl
+
 # --- Helper functions imported here for compatibility---
 from ufl.checks import is_python_scalar, is_true_ufl_scalar, is_ufl_scalar  # noqa: F401
 from ufl.core.expr import Expr
@@ -33,6 +34,7 @@ def format_float(x):
 
 # --- Base classes for constant types ---
 
+
 @ufl_type(is_abstract=True)
 class ConstantValue(Terminal):
     """Constant value."""
@@ -99,16 +101,23 @@ def _init(self, shape=(), free_indices=(), index_dimensions=None):
             self.ufl_free_indices = ()
             self.ufl_index_dimensions = ()
         elif all(isinstance(i, Index) for i in free_indices):  # Handle old input format
-            if not isinstance(index_dimensions, dict) and all(isinstance(i, Index) for i in index_dimensions.keys()):
+            if not isinstance(index_dimensions, dict) and all(
+                isinstance(i, Index) for i in index_dimensions.keys()
+            ):
                 raise ValueError(f"Expecting tuple of index dimensions, not {index_dimensions}")
             self.ufl_free_indices = tuple(sorted(i.count() for i in free_indices))
             self.ufl_index_dimensions = tuple(
-                d for i, d in sorted(index_dimensions.items(), key=lambda x: x[0].count()))
+                d for i, d in sorted(index_dimensions.items(), key=lambda x: x[0].count())
+            )
         else:  # Handle new input format
             if not all(isinstance(i, int) for i in free_indices):
                 raise ValueError(f"Expecting tuple of integer free index ids, not {free_indices}")
-            if not isinstance(index_dimensions, tuple) and all(isinstance(i, int) for i in index_dimensions):
-                raise ValueError(f"Expecting tuple of integer index dimensions, not {index_dimensions}")
+            if not isinstance(index_dimensions, tuple) and all(
+                isinstance(i, int) for i in index_dimensions
+            ):
+                raise ValueError(
+                    f"Expecting tuple of integer index dimensions, not {index_dimensions}"
+                )
 
             # Assuming sorted now to avoid this cost, enable for debugging:
             # if sorted(free_indices) != list(free_indices):
@@ -136,7 +145,8 @@ def __repr__(self):
         r = "Zero(%s, %s, %s)" % (
             repr(self.ufl_shape),
             repr(self.ufl_free_indices),
-            repr(self.ufl_index_dimensions))
+            repr(self.ufl_index_dimensions),
+        )
         return r
 
     def __eq__(self, other):
@@ -144,9 +154,11 @@ def __eq__(self, other):
         if isinstance(other, Zero):
             if self is other:
                 return True
-            return (self.ufl_shape == other.ufl_shape and  # noqa: W504
-                    self.ufl_free_indices == other.ufl_free_indices and  # noqa: W504
-                    self.ufl_index_dimensions == other.ufl_index_dimensions)
+            return (
+                self.ufl_shape == other.ufl_shape
+                and self.ufl_free_indices == other.ufl_free_indices
+                and self.ufl_index_dimensions == other.ufl_index_dimensions
+            )
         elif isinstance(other, (int, float)):
             return other == 0
         else:
@@ -189,6 +201,7 @@ def zero(*shape):
 
 # --- Scalar value types ---
 
+
 @ufl_type(is_abstract=True, is_scalar=True)
 class ScalarValue(ConstantValue):
     """A constant scalar value."""
@@ -345,6 +358,7 @@ def __repr__(self):
 @ufl_type(wraps_type=int, is_literal=True)
 class IntValue(RealValue):
     """Representation of a constant scalar integer value."""
+
     __slots__ = ()
 
     _cache = {}
@@ -387,9 +401,11 @@ def __repr__(self):
 
 # --- Identity matrix ---
 
+
 @ufl_type()
 class Identity(ConstantValue):
     """Representation of an identity matrix."""
+
     __slots__ = ("_dim", "ufl_shape")
 
     def __init__(self, dim):
@@ -427,6 +443,7 @@ def __eq__(self, other):
 
 # --- Permutation symbol ---
 
+
 @ufl_type()
 class PermutationSymbol(ConstantValue):
     """Representation of a permutation symbol.
@@ -497,4 +514,5 @@ def as_ufl(expression):
         return IntValue(expression)
     else:
         raise ValueError(
-            f"Invalid type conversion: {expression} can not be converted to any UFL type.")
+            f"Invalid type conversion: {expression} can not be converted to any UFL type."
+        )
diff --git a/ufl/core/base_form_operator.py b/ufl/core/base_form_operator.py
index a136244cb..90bc23dd0 100644
--- a/ufl/core/base_form_operator.py
+++ b/ufl/core/base_form_operator.py
@@ -1,7 +1,8 @@
 """Base form operator.
 
-This module defines the BaseFormOperator class, which is the base class for objects that can be seen as forms
-and as operators such as ExternalOperator or Interpolate.
+This module defines the BaseFormOperator class, which is the base class
+for objects that can be seen as forms and as operators such as
+ExternalOperator or Interpolate.
 """
 
 # Copyright (C) 2019 Nacime Bouziani
@@ -36,9 +37,11 @@ def __init__(self, *operands, function_space, derivatives=None, argument_slots=(
 
         Args:
             operands: operands on which acts the operator.
-            function_space: the FunctionSpace or MixedFunctionSpace on which to build this Function.
-            derivatives: tuple specifiying the derivative multiindex.
-            argument_slots: tuple composed containing expressions with ufl.Argument or ufl.Coefficient objects.
+            function_space: the FunctionSpace or MixedFunctionSpace on
+                which to build this Function.
+            derivatives: tuple specifying the derivative multiindex.
+            argument_slots: tuple composed containing expressions with
+                ufl.Argument or ufl.Coefficient objects.
         """
         BaseForm.__init__(self)
         ufl_operands = tuple(map(as_ufl, operands))
@@ -73,12 +76,14 @@ def __init__(self, *operands, function_space, derivatives=None, argument_slots=(
     def argument_slots(self, outer_form=False):
         """Returns a tuple of expressions containing argument and coefficient based expressions.
 
-        We get an argument uhat when we take the Gateaux derivative in the direction uhat:
-        d/du N(u; v*) = dNdu(u; uhat, v*) where uhat is a ufl.Argument and v* a ufl.Coargument
-        Applying the action replace the last argument by coefficient:
-        action(dNdu(u; uhat, v*), w) = dNdu(u; w, v*) where du is a ufl.Coefficient.
+        We get an argument uhat when we take the Gateaux derivative in
+        the direction uhat: d/du N(u; v*) = dNdu(u; uhat, v*) where uhat
+        is a ufl.Argument and v* a ufl.Coargument Applying the action
+        replace the last argument by coefficient: action(dNdu(u; uhat,
+        v*), w) = dNdu(u; w, v*) where du is a ufl.Coefficient.
         """
         from ufl.algorithms.analysis import extract_arguments
+
         if not outer_form:
             return self._argument_slots
         # Takes into account argument contraction when a base form operator is in an outer form:
@@ -96,14 +101,19 @@ def coefficients(self):
     def _analyze_form_arguments(self):
         """Analyze which Argument and Coefficient objects can be found in the base form."""
         from ufl.algorithms.analysis import extract_arguments, extract_coefficients, extract_type
+
         dual_arg, *arguments = self.argument_slots()
-        # When coarguments are treated as BaseForms, they have two arguments (one primal and one dual)
-        # as they map from V* to V* => V* x V -> R. However, when they are treated as mere "arguments",
-        # the primal space argument is discarded and we only have the dual space argument (Coargument).
-        # This is the exact same situation than BaseFormOperator's arguments which are different depending on
-        # whether the BaseFormOperator is used in an outer form or not.
-        arguments = (tuple(extract_type(dual_arg, Coargument))
-                     + tuple(a for arg in arguments for a in extract_arguments(arg)))
+        # When coarguments are treated as BaseForms, they have two
+        # arguments (one primal and one dual) as they map from V* to V*
+        # => V* x V -> R. However, when they are treated as mere
+        # "arguments", the primal space argument is discarded and we
+        # only have the dual space argument (Coargument). This is the
+        # exact same situation than BaseFormOperator's arguments which
+        # are different depending on whether the BaseFormOperator is
+        # used in an outer form or not.
+        arguments = tuple(extract_type(dual_arg, Coargument)) + tuple(
+            a for arg in arguments for a in extract_arguments(arg)
+        )
         coefficients = tuple(c for op in self.ufl_operands for c in extract_coefficients(op))
         # Define canonical numbering of arguments and coefficients
         # 1) Need concept of order since we may have arguments with the same number
@@ -132,11 +142,16 @@ def ufl_function_space(self):
         """
         return self.arguments()[0]._ufl_function_space.dual()
 
-    def _ufl_expr_reconstruct_(self, *operands, function_space=None, derivatives=None, argument_slots=None):
+    def _ufl_expr_reconstruct_(
+        self, *operands, function_space=None, derivatives=None, argument_slots=None
+    ):
         """Return a new object of the same type with new operands."""
-        return type(self)(*operands, function_space=function_space or self.ufl_function_space(),
-                          derivatives=derivatives or self.derivatives,
-                          argument_slots=argument_slots or self.argument_slots())
+        return type(self)(
+            *operands,
+            function_space=function_space or self.ufl_function_space(),
+            derivatives=derivatives or self.derivatives,
+            argument_slots=argument_slots or self.argument_slots(),
+        )
 
     def __repr__(self):
         """Default repr string construction for base form operators."""
@@ -149,11 +164,13 @@ def __repr__(self):
 
     def __hash__(self):
         """Hash code for use in dicts."""
-        hashdata = (type(self),
-                    tuple(hash(op) for op in self.ufl_operands),
-                    tuple(hash(arg) for arg in self._argument_slots),
-                    self.derivatives,
-                    hash(self.ufl_function_space()))
+        hashdata = (
+            type(self),
+            tuple(hash(op) for op in self.ufl_operands),
+            tuple(hash(arg) for arg in self._argument_slots),
+            self.derivatives,
+            hash(self.ufl_function_space()),
+        )
         return hash(hashdata)
 
     def __eq__(self, other):
diff --git a/ufl/core/expr.py b/ufl/core/expr.py
index e6b2ce3d8..cef955f0e 100644
--- a/ufl/core/expr.py
+++ b/ufl/core/expr.py
@@ -169,13 +169,10 @@ def __init__(self):
     _ufl_required_properties_ = (
         # A tuple of operands, all of them Expr instances.
         "ufl_operands",
-
         # A tuple of ints, the value shape of the expression.
         "ufl_shape",
-
         # A tuple of free index counts.
         "ufl_free_indices",
-
         # A tuple providing the int dimension for each free index.
         "ufl_index_dimensions",
     )
@@ -186,24 +183,19 @@ def __init__(self):
     _ufl_required_methods_ = (
         # To compute the hash on demand, this method is called.
         "_ufl_compute_hash_",
-
         # The data returned from this method is used to compute the
         # signature of a form
         "_ufl_signature_data_",
-
         # The == operator must be implemented to compare for identical
         # representation, used by set() and dict(). The __hash__
         # operator is added by ufl_type.
         "__eq__",
-
         # To reconstruct an object of the same type with operands or
         # properties changed.
         "_ufl_expr_reconstruct_",  # Implemented in Operator and Terminal so this should never fail
-
         "ufl_domains",
         # "ufl_cell",
         # "ufl_domain",
-
         # "__str__",
         # "__repr__",
     )
@@ -259,16 +251,22 @@ def _ufl_expr_reconstruct_(self, *operands):
 
     def ufl_domains(self):
         """Return all domains this expression is defined on."""
-        warnings.warn("Expr.ufl_domains() is deprecated, please "
-                      "use extract_domains(expr) instead.", DeprecationWarning)
+        warnings.warn(
+            "Expr.ufl_domains() is deprecated, please use extract_domains(expr) instead.",
+            DeprecationWarning,
+        )
         from ufl.domain import extract_domains
+
         return extract_domains(self)
 
     def ufl_domain(self):
         """Return the single unique domain this expression is defined on, or throw an error."""
-        warnings.warn("Expr.ufl_domain() is deprecated, please "
-                      "use extract_unique_domain(expr) instead.", DeprecationWarning)
+        warnings.warn(
+            "Expr.ufl_domain() is deprecated, please use extract_unique_domain(expr) instead.",
+            DeprecationWarning,
+        )
         from ufl.domain import extract_unique_domain
+
         return extract_unique_domain(self)
 
     # --- Functions for float evaluation ---
diff --git a/ufl/core/external_operator.py b/ufl/core/external_operator.py
index ecd736391..3a9304854 100644
--- a/ufl/core/external_operator.py
+++ b/ufl/core/external_operator.py
@@ -1,8 +1,9 @@
 """External operator.
 
-This module defines the ``ExternalOperator`` class, which symbolically represents operators that are not
-straightforwardly expressible in UFL. Subclasses of ``ExternalOperator`` must define
-how this operator should be evaluated as well as its derivatives from a given set of operands.
+This module defines the ``ExternalOperator`` class, which symbolically
+represents operators that are not straightforwardly expressible in UFL.
+Subclasses of ``ExternalOperator`` must define how this operator should
+be evaluated as well as its derivatives from a given set of operands.
 """
 # Copyright (C) 2019 Nacime Bouziani
 #
@@ -29,26 +30,34 @@ def __init__(self, *operands, function_space, derivatives=None, argument_slots=(
 
         Args:
             operands: operands on which acts the ExternalOperator.
-            function_space: the FunctionSpace, or MixedFunctionSpace on which to build this Function.
-            derivatives: tuple specifiying the derivative multiindex.
-            argument_slots: tuple composed containing expressions with ufl.Argument or ufl.Coefficient objects.
+            function_space: the FunctionSpace, or MixedFunctionSpace on
+                which to build this Function.
+            derivatives: tuple specifying the derivative multiindex.
+                argument_slots: tuple composed containing expressions with
+                ufl.Argument or ufl.Coefficient objects.
+            argument_slots: TODO
         """
         # -- Derivatives -- #
         if derivatives is not None:
             if not isinstance(derivatives, tuple):
-                raise TypeError(f"Expecting a tuple for derivatives and not {derivatives}")
+                raise TypeError(f"Expecting a tuple for derivatives and not {derivatives}.")
             if not len(derivatives) == len(operands):
-                raise ValueError(f"Expecting a size of {len(operands)} for {derivatives}")
+                raise ValueError(f"Expecting a size of {len(operands)} for {derivatives}.")
             if not all(isinstance(d, int) for d in derivatives) or any(d < 0 for d in derivatives):
                 raise ValueError(
-                    f"Expecting a derivative multi-index with nonnegative indices and not {str(derivatives)}")
+                    "Expecting a derivative multi-index with nonnegative indices, "
+                    f"not {derivatives}."
+                )
         else:
             derivatives = (0,) * len(operands)
 
-        BaseFormOperator.__init__(self, *operands,
-                                  function_space=function_space,
-                                  derivatives=derivatives,
-                                  argument_slots=argument_slots)
+        BaseFormOperator.__init__(
+            self,
+            *operands,
+            function_space=function_space,
+            derivatives=derivatives,
+            argument_slots=argument_slots,
+        )
 
     def ufl_element(self):
         """Shortcut to get the finite element of the function space of the external operator."""
@@ -57,28 +66,38 @@ def ufl_element(self):
 
     def grad(self):
         """Returns the symbolic grad of the external operator."""
-        # By default, differential rules produce `grad(assembled_o)` `where assembled_o`
-        # is the `Coefficient` resulting from assembling the external operator since
-        # the external operator may not be smooth enough for chain rule to hold.
-        # Symbolic gradient (`grad(ExternalOperator)`) depends on the operator considered
-        # and its implementation may be needed in some cases (e.g. convolution operator).
-        raise NotImplementedError('Symbolic gradient not defined for the external operator considered!')
+        # By default, differential rules produce `grad(assembled_o)`
+        # `where assembled_o` is the `Coefficient` resulting from
+        # assembling the external operator since the external operator
+        # may not be smooth enough for chain rule to hold. Symbolic
+        # gradient (`grad(ExternalOperator)`) depends on the operator
+        # considered and its implementation may be needed in some cases
+        # (e.g. convolution operator).
+        raise NotImplementedError(
+            "Symbolic gradient not defined for the external operator considered."
+        )
 
     def assemble(self, *args, **kwargs):
         """Assemble the external operator."""
-        raise NotImplementedError(f"Symbolic evaluation of {self._ufl_class_.__name__} not available.")
+        raise NotImplementedError(
+            f"Symbolic evaluation of {self._ufl_class_.__name__} not available."
+        )
 
-    def _ufl_expr_reconstruct_(self, *operands, function_space=None, derivatives=None,
-                               argument_slots=None, add_kwargs={}):
+    def _ufl_expr_reconstruct_(
+        self, *operands, function_space=None, derivatives=None, argument_slots=None, add_kwargs={}
+    ):
         """Return a new object of the same type with new operands."""
-        return type(self)(*operands, function_space=function_space or self.ufl_function_space(),
-                          derivatives=derivatives or self.derivatives,
-                          argument_slots=argument_slots or self.argument_slots(),
-                          **add_kwargs)
+        return type(self)(
+            *operands,
+            function_space=function_space or self.ufl_function_space(),
+            derivatives=derivatives or self.derivatives,
+            argument_slots=argument_slots or self.argument_slots(),
+            **add_kwargs,
+        )
 
     def __str__(self):
         """Default str string for ExternalOperator operators."""
-        d = '\N{PARTIAL DIFFERENTIAL}'
+        d = "\N{PARTIAL DIFFERENTIAL}"
         derivatives = self.derivatives
         d_ops = "".join(d + "o" + str(i + 1) for i, di in enumerate(derivatives) for j in range(di))
         e = "e("
@@ -92,8 +111,10 @@ def __eq__(self, other):
         """Check for equality."""
         if self is other:
             return True
-        return (type(self) is type(other) and
-                all(a == b for a, b in zip(self.ufl_operands, other.ufl_operands)) and
-                all(a == b for a, b in zip(self._argument_slots, other._argument_slots)) and
-                self.derivatives == other.derivatives and
-                self.ufl_function_space() == other.ufl_function_space())
+        return (
+            type(self) is type(other)
+            and all(a == b for a, b in zip(self.ufl_operands, other.ufl_operands))
+            and all(a == b for a, b in zip(self._argument_slots, other._argument_slots))
+            and self.derivatives == other.derivatives
+            and self.ufl_function_space() == other.ufl_function_space()
+        )
diff --git a/ufl/core/interpolate.py b/ufl/core/interpolate.py
index 86198c680..57e1506fd 100644
--- a/ufl/core/interpolate.py
+++ b/ufl/core/interpolate.py
@@ -39,10 +39,12 @@ def __init__(self, expr, v):
 
         if isinstance(v, AbstractFunctionSpace):
             if is_dual(v):
-                raise ValueError('Expecting a primal function space.')
+                raise ValueError("Expecting a primal function space.")
             v = Argument(v.dual(), 0)
         elif not isinstance(v, dual_args):
-            raise ValueError("Expecting the second argument to be FunctionSpace, FiniteElement or dual.")
+            raise ValueError(
+                "Expecting the second argument to be FunctionSpace, FiniteElement or dual."
+            )
 
         expr = as_ufl(expr)
         if isinstance(expr, dual_args):
@@ -55,8 +57,9 @@ def __init__(self, expr, v):
         function_space = vv.ufl_function_space().dual()
         # Set the operand as `expr` for DAG traversal purpose.
         operand = expr
-        BaseFormOperator.__init__(self, operand, function_space=function_space,
-                                  argument_slots=argument_slots)
+        BaseFormOperator.__init__(
+            self, operand, function_space=function_space, argument_slots=argument_slots
+        )
 
     def _ufl_expr_reconstruct_(self, expr, v=None, **add_kwargs):
         """Return a new object of the same type with new operands."""
@@ -81,9 +84,11 @@ def __eq__(self, other):
         """Check for equality."""
         if self is other:
             return True
-        return (type(self) is type(other) and
-                all(a == b for a, b in zip(self._argument_slots, other._argument_slots)) and
-                self.ufl_function_space() == other.ufl_function_space())
+        return (
+            type(self) is type(other)
+            and all(a == b for a, b in zip(self._argument_slots, other._argument_slots))
+            and self.ufl_function_space() == other.ufl_function_space()
+        )
 
 
 # Helper function
diff --git a/ufl/core/multiindex.py b/ufl/core/multiindex.py
index 81409ce7d..523d21d20 100644
--- a/ufl/core/multiindex.py
+++ b/ufl/core/multiindex.py
@@ -19,6 +19,7 @@
 
 class IndexBase(object):
     """Base class for all indices."""
+
     __slots__ = ()
 
     def __init__(self):
@@ -27,6 +28,7 @@ def __init__(self):
 
 class FixedIndex(IndexBase):
     """UFL value: An index with a specific value assigned."""
+
     __slots__ = ("_value", "_hash")
 
     _cache = {}
@@ -112,6 +114,7 @@ def __repr__(self):
 @ufl_type()
 class MultiIndex(Terminal):
     """Represents a sequence of indices, either fixed or free."""
+
     __slots__ = ("_indices",)
 
     _cache = {}
@@ -164,8 +167,7 @@ def _ufl_compute_hash_(self):
 
     def __eq__(self, other):
         """Check equality."""
-        return isinstance(other, MultiIndex) and \
-            self._indices == other._indices
+        return isinstance(other, MultiIndex) and self._indices == other._indices
 
     def evaluate(self, x, mapping, component, index_values):
         """Evaluate index."""
diff --git a/ufl/core/terminal.py b/ufl/core/terminal.py
index f258a1c04..47c6c16d9 100644
--- a/ufl/core/terminal.py
+++ b/ufl/core/terminal.py
@@ -54,10 +54,12 @@ def evaluate(self, x, mapping, component, index_values, derivatives=()):
             except Exception:
                 pass
             # If it has an ufl_evaluate function, call it
-            if hasattr(self, 'ufl_evaluate'):
+            if hasattr(self, "ufl_evaluate"):
                 return self.ufl_evaluate(x, component, derivatives)
             # Take component if any
-            warnings.warn(f"Couldn't map '{self}' to a float, returning ufl object without evaluation.")
+            warnings.warn(
+                f"Couldn't map '{self}' to a float, returning ufl object without evaluation."
+            )
             f = self
             if component:
                 f = f[component]
@@ -93,9 +95,11 @@ def __eq__(self, other):
 
 # --- Subgroups of terminals ---
 
+
 @ufl_type(is_abstract=True)
 class FormArgument(Terminal):
     """An abstract class for a form argument (a thing in a primal finite element space)."""
+
     __slots__ = ()
 
     def __init__(self):
diff --git a/ufl/core/ufl_id.py b/ufl/core/ufl_id.py
index bc1206761..34cbda859 100644
--- a/ufl/core/ufl_id.py
+++ b/ufl/core/ufl_id.py
@@ -51,6 +51,7 @@ def init_ufl_id(self, ufl_id):
                 ufl_id = cls._ufl_global_id
             cls._ufl_global_id = max(ufl_id, cls._ufl_global_id) + 1
             return ufl_id
+
         return init_ufl_id
 
     # Modify class:
diff --git a/ufl/core/ufl_type.py b/ufl/core/ufl_type.py
index e19a9c340..c409d05fb 100644
--- a/ufl/core/ufl_type.py
+++ b/ufl/core/ufl_type.py
@@ -59,7 +59,8 @@ def get_base_attr(cls, name):
 def set_trait(cls, basename, value, inherit=False):
     """Assign a trait to class with namespacing ``_ufl_basename_`` applied.
 
-    If trait value is ``None``, optionally inherit it from the closest base class that has it.
+    If trait value is ``None``, optionally inherit it from the closest
+    base class that has it.
     """
     name = "_ufl_" + basename + "_"
     if value is None and inherit:
@@ -88,14 +89,18 @@ def determine_num_ops(cls, num_ops, unop, binop, rbinop):
 def check_is_terminal_consistency(cls):
     """Check for consistency in ``is_terminal`` trait among superclasses."""
     if cls._ufl_is_terminal_ is None:
-        msg = (f"Class {cls.__name__} has not specified the is_terminal trait."
-               " Did you forget to inherit from Terminal or Operator?")
+        msg = (
+            f"Class {cls.__name__} has not specified the is_terminal trait."
+            " Did you forget to inherit from Terminal or Operator?"
+        )
         raise TypeError(msg)
 
     base_is_terminal = get_base_attr(cls, "_ufl_is_terminal_")
     if base_is_terminal is not None and cls._ufl_is_terminal_ != base_is_terminal:
-        msg = (f"Conflicting given and automatic 'is_terminal' trait for class {cls.__name__}."
-               " Check if you meant to inherit from Terminal or Operator.")
+        msg = (
+            f"Conflicting given and automatic 'is_terminal' trait for class {cls.__name__}."
+            " Check if you meant to inherit from Terminal or Operator."
+        )
         raise TypeError(msg)
 
 
@@ -105,8 +110,10 @@ def check_abstract_trait_consistency(cls):
         if base is core.expr.Expr:
             break
         if not issubclass(base, core.expr.Expr) and base._ufl_is_abstract_:
-            msg = ("Base class {0.__name__} of class {1.__name__} "
-                   "is not an abstract subclass of {2.__name__}.")
+            msg = (
+                "Base class {0.__name__} of class {1.__name__} "
+                "is not an abstract subclass of {2.__name__}."
+            )
             raise TypeError(msg.format(base, cls, core.expr.Expr))
 
 
@@ -116,15 +123,16 @@ def check_has_slots(cls):
         return
 
     if "__slots__" not in cls.__dict__:
-        msg = ("Class {0.__name__} is missing the __slots__ "
-               "attribute and is not marked with _ufl_noslots_.")
+        msg = (
+            "Class {0.__name__} is missing the __slots__ "
+            "attribute and is not marked with _ufl_noslots_."
+        )
         raise TypeError(msg.format(cls))
 
     # Check base classes for __slots__ as well, skipping object which is the last one
     for base in cls.mro()[1:-1]:
         if "__slots__" not in base.__dict__:
-            msg = ("Class {0.__name__} is has a base class "
-                   "{1.__name__} with __slots__ missing.")
+            msg = "Class {0.__name__} is has a base class {1.__name__} with __slots__ missing."
             raise TypeError(msg.format(cls, base))
 
 
@@ -202,22 +210,30 @@ def attach_implementations_of_indexing_interface(
     # operands.  This simplifies refactoring because a lot of types do
     # this.
     if inherit_shape_from_operand is not None:
+
         def _inherited_ufl_shape(self):
             return self.ufl_operands[inherit_shape_from_operand].ufl_shape
+
         cls.ufl_shape = property(_inherited_ufl_shape)
 
     if inherit_indices_from_operand is not None:
+
         def _inherited_ufl_free_indices(self):
             return self.ufl_operands[inherit_indices_from_operand].ufl_free_indices
 
         def _inherited_ufl_index_dimensions(self):
             return self.ufl_operands[inherit_indices_from_operand].ufl_index_dimensions
+
         cls.ufl_free_indices = property(_inherited_ufl_free_indices)
         cls.ufl_index_dimensions = property(_inherited_ufl_index_dimensions)
 
 
 def update_global_expr_attributes(cls):
-    """Update global ``Expr`` attributes, mainly by adding *cls* to global collections of ufl types."""
+    """Update global attributres.
+
+    Update global ``Expr`` attributes, mainly by adding *cls* to global
+    collections of ufl types.
+    """
     if cls._ufl_is_terminal_modifier_:
         core.expr.Expr._ufl_terminal_modifiers_.append(cls)
 
@@ -249,20 +265,34 @@ def update_ufl_type_attributes(cls):
 
 
 def ufl_type(
-    is_abstract=False, is_terminal=None,  is_scalar=False, is_index_free=False, is_shaping=False,
-    is_literal=False, is_terminal_modifier=False, is_in_reference_frame=False, is_restriction=False,
-    is_evaluation=False, is_differential=None, use_default_hash=True, num_ops=None,
-    inherit_shape_from_operand=None, inherit_indices_from_operand=None, wraps_type=None, unop=None,
-    binop=None, rbinop=None
+    is_abstract=False,
+    is_terminal=None,
+    is_scalar=False,
+    is_index_free=False,
+    is_shaping=False,
+    is_literal=False,
+    is_terminal_modifier=False,
+    is_in_reference_frame=False,
+    is_restriction=False,
+    is_evaluation=False,
+    is_differential=None,
+    use_default_hash=True,
+    num_ops=None,
+    inherit_shape_from_operand=None,
+    inherit_indices_from_operand=None,
+    wraps_type=None,
+    unop=None,
+    binop=None,
+    rbinop=None,
 ):
-    """This decorator is to be applied to every subclass in the UFL ``Expr`` and ``BaseForm`` hierarchy.
+    """Decorator to apply to every subclass in the UFL ``Expr`` and ``BaseForm`` hierarchy.
 
-    This decorator contains a number of checks that are
-    intended to enforce uniform behaviour across UFL types.
+    This decorator contains a number of checks that are intended to
+    enforce uniform behaviour across UFL types.
 
-    The rationale behind the checks and the meaning of the
-    optional arguments should be sufficiently documented
-    in the source code below.
+    The rationale behind the checks and the meaning of the optional
+    arguments should be sufficiently documented in the source code
+    below.
     """
 
     def _ufl_type_decorator_(cls):
@@ -285,11 +315,9 @@ def _ufl_type_decorator_(cls):
 
         set_trait(cls, "is_terminal", is_terminal, inherit=True)
         set_trait(cls, "is_literal", is_literal, inherit=True)
-        set_trait(cls, "is_terminal_modifier", is_terminal_modifier,
-                  inherit=True)
+        set_trait(cls, "is_terminal_modifier", is_terminal_modifier, inherit=True)
         set_trait(cls, "is_shaping", is_shaping, inherit=True)
-        set_trait(cls, "is_in_reference_frame", is_in_reference_frame,
-                  inherit=True)
+        set_trait(cls, "is_in_reference_frame", is_in_reference_frame, inherit=True)
         set_trait(cls, "is_restriction", is_restriction, inherit=True)
         set_trait(cls, "is_evaluation", is_evaluation, inherit=True)
         set_trait(cls, "is_differential", is_differential, inherit=True)
@@ -305,7 +333,8 @@ def _ufl_type_decorator_(cls):
         """# These are currently handled in the as_ufl implementation in constantvalue.py
         if wraps_type is not None:
             if not isinstance(wraps_type, type):
-                msg = "Expecting a type, not a {0.__name__} for the wraps_type argument in definition of {1.__name__}."
+                msg = "Expecting a type, not a {0.__name__} for the
+                wraps_type argument in definition of {1.__name__}."
                 raise TypeError(msg.format(type(wraps_type), cls))
 
             def _ufl_from_type_(value):
@@ -352,9 +381,9 @@ def _ufl_expr_rbinop_(self, other):
         # class!  This approach significantly reduces the amount of
         # small functions to implement across all the types but of
         # course it's a bit more opaque.
-        attach_implementations_of_indexing_interface(cls,
-                                                     inherit_shape_from_operand,
-                                                     inherit_indices_from_operand)
+        attach_implementations_of_indexing_interface(
+            cls, inherit_shape_from_operand, inherit_indices_from_operand
+        )
 
         # Update Expr
         update_global_expr_attributes(cls)
diff --git a/ufl/corealg/map_dag.py b/ufl/corealg/map_dag.py
index f299130c1..9b9196f17 100644
--- a/ufl/corealg/map_dag.py
+++ b/ufl/corealg/map_dag.py
@@ -12,10 +12,10 @@
 from ufl.corealg.traversal import cutoff_unique_post_traversal, unique_post_traversal
 
 
-def map_expr_dag(function, expression,  compress=True, vcache=None, rcache=None):
+def map_expr_dag(function, expression, compress=True, vcache=None, rcache=None):
     """Apply a function to each subexpression node in an expression DAG.
 
-    If the same funtion is called multiple times in a transformation
+    If the same function is called multiple times in a transformation
     (as for example in apply_derivatives), then to reuse caches across
     the call, use the arguments vcache and rcache.
 
@@ -25,32 +25,33 @@ def map_expr_dag(function, expression,  compress=True, vcache=None, rcache=None)
         compress: If True (default), the output object from
             the function is cached in a dict and reused such that the
             resulting expression DAG does not contain duplicate objects
-        vcache: Optional dict for caching results of intermediate transformations
+        vcache: Optional dict for caching results of intermediate
+            transformations
         rcache: Optional dict for caching results for compression
 
     Returns:
         The result of the final function call
     """
-    result, = map_expr_dags(function, [expression], compress=compress,
-                            vcache=vcache,
-                            rcache=rcache)
+    (result,) = map_expr_dags(
+        function, [expression], compress=compress, vcache=vcache, rcache=rcache
+    )
     return result
 
 
 def map_expr_dags(function, expressions, compress=True, vcache=None, rcache=None):
-    """Apply a function to each subexpression node in an expression DAG.
+    """Apply a function to each sub-expression node in an expression DAG.
 
     If *compress* is ``True`` (default) the output object from
     the function is cached in a ``dict`` and reused such that the
     resulting expression DAG does not contain duplicate objects.
 
-    If the same funtion is called multiple times in a transformation
+    If the same function is called multiple times in a transformation
     (as for example in apply_derivatives), then to reuse caches across
     the call, use the arguments vcache and rcache.
 
     Args:
         function: The function
-        expression: An expression
+        expressions: An expression
         compress: If True (default), the output object from
             the function is cached in a dict and reused such that the
             resulting expression DAG does not contain duplicate objects
@@ -80,9 +81,11 @@ def map_expr_dags(function, expressions, compress=True, vcache=None, rcache=None
 
     # Pick faster traversal algorithm if we have no cutoffs
     if any(cutoff_types):
+
         def traversal(expression):
             return cutoff_unique_post_traversal(expression, cutoff_types, visited)
     else:
+
         def traversal(expression):
             return unique_post_traversal(expression, visited)
 
diff --git a/ufl/corealg/multifunction.py b/ufl/corealg/multifunction.py
index 1c57c2928..fc6e45136 100644
--- a/ufl/corealg/multifunction.py
+++ b/ufl/corealg/multifunction.py
@@ -29,6 +29,7 @@ def _memoized_handler(self, o):
             r = handler(self, o)
             c[o] = r
         return r
+
     return _memoized_handler
 
 
@@ -76,8 +77,7 @@ def __init__(self):
                     if hasattr(self, handler_name):
                         handler_names[classobject._ufl_typecode_] = handler_name
                         break
-            is_cutoff_type = [get_num_args(getattr(self, name)) == 2
-                              for name in handler_names]
+            is_cutoff_type = [get_num_args(getattr(self, name)) == 2 for name in handler_names]
             cache_data = (handler_names, is_cutoff_type)
             MultiFunction._handlers_cache[algorithm_class] = cache_data
 
diff --git a/ufl/corealg/traversal.py b/ufl/corealg/traversal.py
index 782e16999..64c81deaa 100644
--- a/ufl/corealg/traversal.py
+++ b/ufl/corealg/traversal.py
@@ -39,7 +39,11 @@ def post_traversal(expr):
 
 
 def cutoff_post_traversal(expr, cutofftypes):
-    """Yield ``o`` for each node ``o`` in *expr*, child before parent, but skipping subtrees of the cutofftypes."""
+    """Cut-off post-tranversal.
+
+    Yield ``o`` for each node ``o`` in *expr*, child before parent, but
+    skipping subtrees of the cutofftypes.
+    """
     lifo = [(expr, list(reversed(expr.ufl_operands)))]
     while lifo:
         expr, deps = lifo[-1]
diff --git a/ufl/differentiation.py b/ufl/differentiation.py
index 34c003b85..74e33617d 100644
--- a/ufl/differentiation.py
+++ b/ufl/differentiation.py
@@ -24,8 +24,7 @@
 # --- Basic differentiation objects ---
 
 
-@ufl_type(is_abstract=True,
-          is_differential=True)
+@ufl_type(is_abstract=True, is_differential=True)
 class Derivative(Operator):
     """Base class for all derivative types."""
 
@@ -36,15 +35,13 @@ def __init__(self, operands):
         Operator.__init__(self, operands)
 
 
-@ufl_type(num_ops=4, inherit_shape_from_operand=0,
-          inherit_indices_from_operand=0)
+@ufl_type(num_ops=4, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class CoefficientDerivative(Derivative):
-    """Derivative of the integrand of a form w.r.t. the degrees of freedom in a discrete Coefficient."""
+    """Derivative of form integrand w.r.t. the degrees of freedom in a discrete Coefficient."""
 
     __slots__ = ()
 
-    def __new__(cls, integrand, coefficients, arguments,
-                coefficient_derivatives):
+    def __new__(cls, integrand, coefficients, arguments, coefficient_derivatives):
         """Create a new CoefficientDerivative."""
         if not isinstance(coefficients, ExprList):
             raise ValueError("Expecting ExprList instance with Coefficients.")
@@ -56,23 +53,23 @@ def __new__(cls, integrand, coefficients, arguments,
             return integrand
         return Derivative.__new__(cls)
 
-    def __init__(self, integrand, coefficients, arguments,
-                 coefficient_derivatives):
+    def __init__(self, integrand, coefficients, arguments, coefficient_derivatives):
         """Initalise."""
         if not isinstance(coefficient_derivatives, ExprMapping):
             coefficient_derivatives = ExprMapping(coefficient_derivatives)
-        Derivative.__init__(self, (integrand, coefficients, arguments,
-                                   coefficient_derivatives))
+        Derivative.__init__(self, (integrand, coefficients, arguments, coefficient_derivatives))
 
     def __str__(self):
         """Format as a string."""
-        return "d/dfj { %s }, with fh=%s, dfh/dfj = %s, and coefficient derivatives %s"\
-            % (self.ufl_operands[0], self.ufl_operands[1],
-               self.ufl_operands[2], self.ufl_operands[3])
+        return "d/dfj { %s }, with fh=%s, dfh/dfj = %s, and coefficient derivatives %s" % (
+            self.ufl_operands[0],
+            self.ufl_operands[1],
+            self.ufl_operands[2],
+            self.ufl_operands[3],
+        )
 
 
-@ufl_type(num_ops=4, inherit_shape_from_operand=0,
-          inherit_indices_from_operand=0)
+@ufl_type(num_ops=4, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class CoordinateDerivative(CoefficientDerivative):
     """Derivative of the integrand of a form w.r.t. the SpatialCoordinates."""
 
@@ -80,82 +77,92 @@ class CoordinateDerivative(CoefficientDerivative):
 
     def __str__(self):
         """Format as a string."""
-        return "d/dfj { %s }, with fh=%s, dfh/dfj = %s, and coordinate derivatives %s"\
-            % (self.ufl_operands[0], self.ufl_operands[1],
-               self.ufl_operands[2], self.ufl_operands[3])
+        return "d/dfj { %s }, with fh=%s, dfh/dfj = %s, and coordinate derivatives %s" % (
+            self.ufl_operands[0],
+            self.ufl_operands[1],
+            self.ufl_operands[2],
+            self.ufl_operands[3],
+        )
 
 
-@ufl_type(num_ops=4, inherit_shape_from_operand=0,
-          inherit_indices_from_operand=0)
+@ufl_type(num_ops=4, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class BaseFormDerivative(CoefficientDerivative, BaseForm):
     """Derivative of a base form w.r.t the degrees of freedom in a discrete Coefficient."""
 
     _ufl_noslots_ = True
 
-    def __init__(self, base_form, coefficients, arguments,
-                 coefficient_derivatives):
+    def __init__(self, base_form, coefficients, arguments, coefficient_derivatives):
         """Initalise."""
-        CoefficientDerivative.__init__(self, base_form, coefficients, arguments,
-                                       coefficient_derivatives)
+        CoefficientDerivative.__init__(
+            self, base_form, coefficients, arguments, coefficient_derivatives
+        )
         BaseForm.__init__(self)
 
     def _analyze_form_arguments(self):
         """Collect the arguments of the corresponding BaseForm."""
         from ufl.algorithms.analysis import extract_coefficients, extract_type
+
         base_form, _, arguments, _ = self.ufl_operands
 
         def arg_type(x):
             if isinstance(x, BaseForm):
                 return Coargument
             return Argument
+
         # Each derivative arguments can either be a:
         # - `ufl.BaseForm`: if it contains a `ufl.Coargument`
         # - or a `ufl.Expr`: if it contains a `ufl.Argument`
-        # When a `Coargument` is encountered, it is treated as an argument (i.e. as V* -> V* and not V* x V -> R)
-        # and should result in one single argument (in the dual space).
-        base_form_args = base_form.arguments() + tuple(arg for a in arguments.ufl_operands
-                                                       for arg in extract_type(a, arg_type(a)))
+        # When a `Coargument` is encountered, it is treated as an
+        # argument (i.e. as V* -> V* and not V* x V -> R) and should
+        # result in one single argument (in the dual space).
+        base_form_args = base_form.arguments() + tuple(
+            arg for a in arguments.ufl_operands for arg in extract_type(a, arg_type(a))
+        )
         # BaseFormDerivative's arguments don't necessarily contain BaseArgument objects only
         # -> e.g. `derivative(u ** 2, u, u)` with `u` a Coefficient.
-        base_form_coeffs = base_form.coefficients() + tuple(arg for a in arguments.ufl_operands
-                                                            for arg in extract_coefficients(a))
+        base_form_coeffs = base_form.coefficients() + tuple(
+            arg for a in arguments.ufl_operands for arg in extract_coefficients(a)
+        )
         # Reconstruct arguments for correct numbering
-        self._arguments = tuple(type(arg)(arg.ufl_function_space(), arg.number(), arg.part()) for arg in base_form_args)
+        self._arguments = tuple(
+            type(arg)(arg.ufl_function_space(), arg.number(), arg.part()) for arg in base_form_args
+        )
         self._coefficients = base_form_coeffs
 
 
-@ufl_type(num_ops=4, inherit_shape_from_operand=0,
-          inherit_indices_from_operand=0)
+@ufl_type(num_ops=4, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class BaseFormCoordinateDerivative(BaseFormDerivative, CoordinateDerivative):
     """Derivative of a base form w.r.t. the SpatialCoordinates."""
 
     _ufl_noslots_ = True
 
-    def __init__(self, base_form, coefficients, arguments,
-                 coefficient_derivatives):
+    def __init__(self, base_form, coefficients, arguments, coefficient_derivatives):
         """Initalise."""
-        BaseFormDerivative.__init__(self, base_form, coefficients, arguments,
-                                    coefficient_derivatives)
+        BaseFormDerivative.__init__(
+            self, base_form, coefficients, arguments, coefficient_derivatives
+        )
 
 
-@ufl_type(num_ops=4, inherit_shape_from_operand=0,
-          inherit_indices_from_operand=0)
+@ufl_type(num_ops=4, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class BaseFormOperatorDerivative(BaseFormDerivative, BaseFormOperator):
     """Derivative of a base form operator w.r.t the degrees of freedom in a discrete Coefficient."""
+
     _ufl_noslots_ = True
 
     # BaseFormOperatorDerivative is only needed because of a different
     # differentiation procedure for BaseformOperator objects.
-    def __init__(self, base_form, coefficients, arguments,
-                 coefficient_derivatives):
+    def __init__(self, base_form, coefficients, arguments, coefficient_derivatives):
         """Initalise."""
-        BaseFormDerivative.__init__(self, base_form, coefficients, arguments,
-                                    coefficient_derivatives)
+        BaseFormDerivative.__init__(
+            self, base_form, coefficients, arguments, coefficient_derivatives
+        )
         self._argument_slots = base_form._argument_slots
 
-    # Enforce Operator reconstruction as Operator is a parent class of both: BaseFormDerivative and BaseFormOperator.
-    # Therfore the latter overwrites Operator reconstruction and we would have:
-    #   -> BaseFormOperatorDerivative._ufl_expr_reconstruct_ = BaseFormOperator._ufl_expr_reconstruct_
+    # Enforce Operator reconstruction as Operator is a parent class of
+    # both: BaseFormDerivative and BaseFormOperator.
+    # Therefore the latter overwrites Operator reconstruction and we would have:
+    #   -> BaseFormOperatorDerivative._ufl_expr_reconstruct_ =
+    #   BaseFormOperator._ufl_expr_reconstruct_
     _ufl_expr_reconstruct_ = Operator._ufl_expr_reconstruct_
     # Set __repr__
     __repr__ = Operator.__repr__
@@ -163,23 +170,25 @@ def __init__(self, base_form, coefficients, arguments,
     def argument_slots(self, outer_form=False):
         """Return a tuple of expressions containing argument and coefficient based expressions."""
         from ufl.algorithms.analysis import extract_arguments
+
         base_form, _, arguments, _ = self.ufl_operands
-        argument_slots = (base_form.argument_slots(outer_form)
-                          + tuple(arg for a in arguments for arg in extract_arguments(a)))
+        argument_slots = base_form.argument_slots(outer_form) + tuple(
+            arg for a in arguments for arg in extract_arguments(a)
+        )
         return argument_slots
 
 
-@ufl_type(num_ops=4, inherit_shape_from_operand=0,
-          inherit_indices_from_operand=0)
+@ufl_type(num_ops=4, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class BaseFormOperatorCoordinateDerivative(BaseFormOperatorDerivative, CoordinateDerivative):
     """Derivative of a base form operator w.r.t. the SpatialCoordinates."""
+
     _ufl_noslots_ = True
 
-    def __init__(self, base_form, coefficients, arguments,
-                 coefficient_derivatives):
+    def __init__(self, base_form, coefficients, arguments, coefficient_derivatives):
         """Initalise."""
-        BaseFormOperatorDerivative.__init__(self, base_form, coefficients, arguments,
-                                            coefficient_derivatives)
+        BaseFormOperatorDerivative.__init__(
+            self, base_form, coefficients, arguments, coefficient_derivatives
+        )
 
 
 @ufl_type(num_ops=2)
@@ -205,8 +214,7 @@ def __new__(cls, f, v):
         # Simplification
         # Return zero if expression is trivially independent of variable
         if f._ufl_is_terminal_ and f != v:
-            return Zero(f.ufl_shape + v.ufl_shape, f.ufl_free_indices,
-                        f.ufl_index_dimensions)
+            return Zero(f.ufl_shape + v.ufl_shape, f.ufl_free_indices, f.ufl_index_dimensions)
 
         # Construction
         return Derivative.__new__(cls)
@@ -222,12 +230,12 @@ def __str__(self):
         """Format as a string."""
         if isinstance(self.ufl_operands[0], Terminal):
             return "d%s/d[%s]" % (self.ufl_operands[0], self.ufl_operands[1])
-        return "d/d[%s] %s" % (self.ufl_operands[1],
-                               parstr(self.ufl_operands[0], self))
+        return "d/d[%s] %s" % (self.ufl_operands[1], parstr(self.ufl_operands[0], self))
 
 
 # --- Compound differentiation objects ---
 
+
 @ufl_type(is_abstract=True)
 class CompoundDerivative(Derivative):
     """Base class for all compound derivative types."""
@@ -250,8 +258,7 @@ def __new__(cls, f):
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
             dim = find_geometric_dimension(f)
-            return Zero(f.ufl_shape + (dim,), f.ufl_free_indices,
-                        f.ufl_index_dimensions)
+            return Zero(f.ufl_shape + (dim,), f.ufl_free_indices, f.ufl_index_dimensions)
         return CompoundDerivative.__new__(cls)
 
     def __init__(self, f):
@@ -266,17 +273,16 @@ def _ufl_expr_reconstruct_(self, op):
                 raise ValueError("Operand shape mismatch in Grad reconstruct.")
             if self.ufl_operands[0].ufl_free_indices != op.ufl_free_indices:
                 raise ValueError("Free index mismatch in Grad reconstruct.")
-            return Zero(self.ufl_shape, self.ufl_free_indices,
-                        self.ufl_index_dimensions)
+            return Zero(self.ufl_shape, self.ufl_free_indices, self.ufl_index_dimensions)
         return self._ufl_class_(op)
 
     def evaluate(self, x, mapping, component, index_values, derivatives=()):
         """Get child from mapping and return the component asked for."""
         component, i = component[:-1], component[-1]
         derivatives = derivatives + (i,)
-        result = self.ufl_operands[0].evaluate(x, mapping, component,
-                                               index_values,
-                                               derivatives=derivatives)
+        result = self.ufl_operands[0].evaluate(
+            x, mapping, component, index_values, derivatives=derivatives
+        )
         return result
 
     @property
@@ -289,20 +295,20 @@ def __str__(self):
         return "grad(%s)" % self.ufl_operands[0]
 
 
-@ufl_type(num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True,
-          is_in_reference_frame=True)
+@ufl_type(
+    num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True, is_in_reference_frame=True
+)
 class ReferenceGrad(CompoundDerivative):
     """Reference grad."""
 
-    __slots__ = ("_dim", )
+    __slots__ = ("_dim",)
 
     def __new__(cls, f):
         """Create a new ReferenceGrad."""
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
             dim = extract_unique_domain(f).topological_dimension()
-            return Zero(f.ufl_shape + (dim,), f.ufl_free_indices,
-                        f.ufl_index_dimensions)
+            return Zero(f.ufl_shape + (dim,), f.ufl_free_indices, f.ufl_index_dimensions)
         return CompoundDerivative.__new__(cls)
 
     def __init__(self, f):
@@ -317,17 +323,16 @@ def _ufl_expr_reconstruct_(self, op):
                 raise ValueError("Operand shape mismatch in ReferenceGrad reconstruct.")
             if self.ufl_operands[0].ufl_free_indices != op.ufl_free_indices:
                 raise ValueError("Free index mismatch in ReferenceGrad reconstruct.")
-            return Zero(self.ufl_shape, self.ufl_free_indices,
-                        self.ufl_index_dimensions)
+            return Zero(self.ufl_shape, self.ufl_free_indices, self.ufl_index_dimensions)
         return self._ufl_class_(op)
 
     def evaluate(self, x, mapping, component, index_values, derivatives=()):
         """Get child from mapping and return the component asked for."""
         component, i = component[:-1], component[-1]
         derivatives = derivatives + (i,)
-        result = self.ufl_operands[0].evaluate(x, mapping, component,
-                                               index_values,
-                                               derivatives=derivatives)
+        result = self.ufl_operands[0].evaluate(
+            x, mapping, component, index_values, derivatives=derivatives
+        )
         return result
 
     @property
@@ -371,8 +376,9 @@ def __str__(self):
         return "div(%s)" % self.ufl_operands[0]
 
 
-@ufl_type(num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True,
-          is_in_reference_frame=True)
+@ufl_type(
+    num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True, is_in_reference_frame=True
+)
 class ReferenceDiv(CompoundDerivative):
     """Reference divergence."""
 
@@ -414,8 +420,7 @@ def __new__(cls, f):
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
             dim = find_geometric_dimension(f)
-            return Zero((dim,) + f.ufl_shape, f.ufl_free_indices,
-                        f.ufl_index_dimensions)
+            return Zero((dim,) + f.ufl_shape, f.ufl_free_indices, f.ufl_index_dimensions)
         return CompoundDerivative.__new__(cls)
 
     def __init__(self, f):
@@ -430,8 +435,7 @@ def _ufl_expr_reconstruct_(self, op):
                 raise ValueError("Operand shape mismatch in NablaGrad reconstruct.")
             if self.ufl_operands[0].ufl_free_indices != op.ufl_free_indices:
                 raise ValueError("Free index mismatch in NablaGrad reconstruct.")
-            return Zero(self.ufl_shape, self.ufl_free_indices,
-                        self.ufl_index_dimensions)
+            return Zero(self.ufl_shape, self.ufl_free_indices, self.ufl_index_dimensions)
         return self._ufl_class_(op)
 
     @property
@@ -509,8 +513,9 @@ def __str__(self):
         return "curl(%s)" % self.ufl_operands[0]
 
 
-@ufl_type(num_ops=1, inherit_indices_from_operand=0,
-          is_terminal_modifier=True, is_in_reference_frame=True)
+@ufl_type(
+    num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True, is_in_reference_frame=True
+)
 class ReferenceCurl(CompoundDerivative):
     """Reference curl."""
 
diff --git a/ufl/domain.py b/ufl/domain.py
index 175507b39..50ee64d61 100644
--- a/ufl/domain.py
+++ b/ufl/domain.py
@@ -20,15 +20,22 @@
 
 
 class AbstractDomain(object):
-    """Symbolic representation of a geometric domain with only a geometric and topological dimension."""
+    """Symbolic representation of a geometric domain.
+
+    Domain has only a geometric and a topological dimension.
+    """
 
     def __init__(self, topological_dimension, geometric_dimension):
         """Initialise."""
         # Validate dimensions
         if not isinstance(geometric_dimension, numbers.Integral):
-            raise ValueError(f"Expecting integer geometric dimension, not {geometric_dimension.__class__}")
+            raise ValueError(
+                f"Expecting integer geometric dimension, not {geometric_dimension.__class__}"
+            )
         if not isinstance(topological_dimension, numbers.Integral):
-            raise ValueError(f"Expecting integer topological dimension, not {topological_dimension.__class__}")
+            raise ValueError(
+                f"Expecting integer topological dimension, not {topological_dimension.__class__}"
+            )
         if topological_dimension > geometric_dimension:
             raise ValueError("Topological dimension cannot be larger than geometric dimension.")
 
@@ -67,6 +74,7 @@ def __init__(self, coordinate_element, ufl_id=None, cargo=None):
 
         # No longer accepting coordinates provided as a Coefficient
         from ufl.coefficient import Coefficient
+
         if isinstance(coordinate_element, (Coefficient, AbstractCell)):
             raise ValueError("Expecting a coordinate element in the ufl.Mesh construct.")
 
@@ -74,7 +82,7 @@ def __init__(self, coordinate_element, ufl_id=None, cargo=None):
         self._ufl_coordinate_element = coordinate_element
 
         # Derive dimensions from element
-        gdim, = coordinate_element.reference_value_shape
+        (gdim,) = coordinate_element.reference_value_shape
         tdim = coordinate_element.cell.topological_dimension()
         AbstractDomain.__init__(self, tdim, gdim)
 
@@ -117,8 +125,7 @@ def _ufl_signature_data_(self, renumbering):
     def _ufl_sort_key_(self):
         """UFL sort key."""
         typespecific = (self._ufl_id, self._ufl_coordinate_element)
-        return (self.geometric_dimension(), self.topological_dimension(),
-                "Mesh", typespecific)
+        return (self.geometric_dimension(), self.topological_dimension(), "Mesh", typespecific)
 
 
 @attach_ufl_id
@@ -134,7 +141,7 @@ def __init__(self, mesh, topological_dimension, ufl_id=None):
 
         # Derive dimensions from element
         coordinate_element = mesh.ufl_coordinate_element()
-        gdim, = coordinate_element.value_shape
+        (gdim,) = coordinate_element.value_shape
         tdim = coordinate_element.cell.topological_dimension()
         AbstractDomain.__init__(self, tdim, gdim)
 
@@ -159,7 +166,10 @@ def __repr__(self):
     def __str__(self):
         """Format as a string."""
         return "<MeshView #%s of dimension %d over mesh %s>" % (
-            self._ufl_id, self.topological_dimension(), self._ufl_mesh)
+            self._ufl_id,
+            self.topological_dimension(),
+            self._ufl_mesh,
+        )
 
     def _ufl_hash_data_(self):
         """UFL hash data."""
@@ -167,16 +177,14 @@ def _ufl_hash_data_(self):
 
     def _ufl_signature_data_(self, renumbering):
         """UFL signature data."""
-        return ("MeshView", renumbering[self],
-                self._ufl_mesh._ufl_signature_data_(renumbering))
+        return ("MeshView", renumbering[self], self._ufl_mesh._ufl_signature_data_(renumbering))
 
     # NB! Dropped __lt__ here, don't want users to write 'mesh1 <
     # mesh2'.
     def _ufl_sort_key_(self):
         """UFL sort key."""
         typespecific = (self._ufl_id, self._ufl_mesh)
-        return (self.geometric_dimension(), self.topological_dimension(),
-                "MeshView", typespecific)
+        return (self.geometric_dimension(), self.topological_dimension(), "MeshView", typespecific)
 
 
 def as_domain(domain):
@@ -212,7 +220,7 @@ def join_domains(domains):
         gdims.add(domain.geometric_dimension())
     if len(gdims) != 1:
         raise ValueError("Found domains with different geometric dimensions.")
-    gdim, = gdims
+    (gdim,) = gdims
 
     # Split into legacy and modern style domains
     legacy_domains = []
@@ -226,14 +234,18 @@ def join_domains(domains):
 
     # Handle legacy domains checking
     if legacy_domains:
-        warnings.warn("The use of Legacy domains will be deprecated by December 2023. "
-                      "Please, use FunctionSpace instead", DeprecationWarning)
+        warnings.warn(
+            "The use of Legacy domains will be deprecated by December 2023. "
+            "Please, use FunctionSpace instead",
+            DeprecationWarning,
+        )
         if modern_domains:
             raise ValueError(
                 "Found both a new-style domain and a legacy default domain. "
                 "These should not be used interchangeably. To find the legacy "
                 "domain, note that it is automatically created from a cell so "
-                "look for constructors taking a cell.")
+                "look for constructors taking a cell."
+            )
         return tuple(legacy_domains)
 
     # Handle modern domains checking (assuming correct by construction)
@@ -242,6 +254,7 @@ def join_domains(domains):
 
 # TODO: Move these to an analysis module?
 
+
 def extract_domains(expr):
     """Return all domains expression is defined on."""
     domainlist = []
@@ -271,5 +284,5 @@ def find_geometric_dimension(expr):
 
     if len(gdims) != 1:
         raise ValueError("Cannot determine geometric dimension from expression.")
-    gdim, = gdims
+    (gdim,) = gdims
     return gdim
diff --git a/ufl/duals.py b/ufl/duals.py
index 1e017a547..22681440b 100644
--- a/ufl/duals.py
+++ b/ufl/duals.py
@@ -14,7 +14,7 @@ def is_primal(object):
     because a mixed function space containing both primal
     and dual components is neither primal nor dual.
     """
-    return hasattr(object, '_primal') and object._primal
+    return hasattr(object, "_primal") and object._primal
 
 
 def is_dual(object):
@@ -24,4 +24,4 @@ def is_dual(object):
     because a mixed function space containing both primal
     and dual components is neither primal nor dual.
     """
-    return hasattr(object, '_dual') and object._dual
+    return hasattr(object, "_dual") and object._dual
diff --git a/ufl/equation.py b/ufl/equation.py
index f36089abb..956ae80a1 100644
--- a/ufl/equation.py
+++ b/ufl/equation.py
@@ -41,6 +41,7 @@ def __bool__(self):
             return self.rhs.equals(self.lhs)
         else:
             raise ValueError("Either lhs or rhs of Equation must implement self.equals(other).")
+
     __nonzero__ = __bool__
 
     def __eq__(self, other):
diff --git a/ufl/exproperators.py b/ufl/exproperators.py
index 60eb87566..ff532e843 100644
--- a/ufl/exproperators.py
+++ b/ufl/exproperators.py
@@ -85,9 +85,13 @@ def _ne(self, other):
 def _as_tensor(self, indices):
     """A^indices := as_tensor(A, indices)."""
     if not isinstance(indices, tuple):
-        raise ValueError("Expecting a tuple of Index objects to A^indices := as_tensor(A, indices).")
+        raise ValueError(
+            "Expecting a tuple of Index objects to A^indices := as_tensor(A, indices)."
+        )
     if not all(isinstance(i, Index) for i in indices):
-        raise ValueError("Expecting a tuple of Index objects to A^indices := as_tensor(A, indices).")
+        raise ValueError(
+            "Expecting a tuple of Index objects to A^indices := as_tensor(A, indices)."
+        )
     return as_tensor(self, indices)
 
 
@@ -96,6 +100,7 @@ def _as_tensor(self, indices):
 
 # --- Helper functions for product handling ---
 
+
 def _mult(a, b):
     """Multiply."""
     # Discover repeated indices, which results in index sums
@@ -307,6 +312,7 @@ def _abs(self):
 
 # --- Extend Expr with restiction operators a("+"), a("-") ---
 
+
 def _restrict(self, side):
     """Restrict."""
     if side == "+":
@@ -324,6 +330,7 @@ def _eval(self, coord, mapping=None, component=()):
     """
     # Evaluate derivatives first
     from ufl.algorithms import expand_derivatives
+
     f = expand_derivatives(self)
 
     # Evaluate recursively
@@ -348,10 +355,12 @@ def _call(self, arg, mapping=None, component=()):
 
 # --- Extend Expr with the transpose operation A.T ---
 
+
 def _transpose(self):
     """Transpose a rank-2 tensor expression.
 
-    For more general transpose operations of higher order tensor expressions, use indexing and Tensor.
+    For more general transpose operations of higher order tensor
+    expressions, use indexing and Tensor.
     """
     return Transposed(self)
 
@@ -361,6 +370,7 @@ def _transpose(self):
 
 # --- Extend Expr with indexing operator a[i] ---
 
+
 def _getitem(self, component):
     """Get an item."""
     # Treat component consistently as tuple below
@@ -370,12 +380,16 @@ def _getitem(self, component):
     shape = self.ufl_shape
 
     # Analyse slices (:) and Ellipsis (...)
-    all_indices, slice_indices, repeated_indices = create_slice_indices(component, shape, self.ufl_free_indices)
+    all_indices, slice_indices, repeated_indices = create_slice_indices(
+        component, shape, self.ufl_free_indices
+    )
 
     # Check that we have the right number of indices for a tensor with
     # this shape
     if len(shape) != len(all_indices):
-        raise ValueError(f"Invalid number of indices {len(all_indices)} for expression of rank {len(shape)}.")
+        raise ValueError(
+            f"Invalid number of indices {len(all_indices)} for expression of rank {len(shape)}."
+        )
 
     # Special case for simplifying foo[...] => foo, foo[:] => foo or
     # similar
@@ -422,6 +436,7 @@ def _getitem(self, component):
 
 # --- Extend Expr with spatial differentiation operator a.dx(i) ---
 
+
 def _dx(self, *ii):
     """Return the partial derivative with respect to spatial variable number *ii*."""
     d = self
diff --git a/ufl/finiteelement.py b/ufl/finiteelement.py
index d306002f1..a5ffff6a6 100644
--- a/ufl/finiteelement.py
+++ b/ufl/finiteelement.py
@@ -31,12 +31,14 @@
 class AbstractFiniteElement(_abc.ABC):
     """Base class for all finite elements.
 
-    To make your element library compatible with UFL, you should make a subclass of AbstractFiniteElement
-    and provide implementions of all the abstract methods and properties. All methods and properties
-    that are not marked as abstract are implemented here and should not need to be overwritten in your
-    subclass.
-
-    An example of how the methods in your subclass could be implemented can be found in Basix; see
+    To make your element library compatible with UFL, you should make a
+    subclass of AbstractFiniteElement and provide implementions of all
+    the abstract methods and properties. All methods and properties that
+    are not marked as abstract are implemented here and should not need
+    to be overwritten in your subclass.
+
+    An example of how the methods in your subclass could be implemented
+    can be found in Basix; see
     https://github.com/FEniCS/basix/blob/main/python/basix/ufl.py
     """
 
@@ -66,29 +68,33 @@ def pullback(self) -> _AbstractPullback:
 
     @_abc.abstractproperty
     def embedded_superdegree(self) -> _typing.Union[int, None]:
-        """Return the degree of the minimum degree Lagrange space that spans this element.
+        """Degree of the minimum degree Lagrange space that spans this element.
 
-        This returns the degree of the lowest degree Lagrange space such that the polynomial
-        space of the Lagrange space is a superspace of this element's polynomial space. If this
-        element contains basis functions that are not in any Lagrange space, this function should
-        return None.
+        This returns the degree of the lowest degree Lagrange space such
+        that the polynomial space of the Lagrange space is a superspace
+        of this element's polynomial space. If this element contains
+        basis functions that are not in any Lagrange space, this
+        function should return None.
 
-        Note that on a simplex cells, the polynomial space of Lagrange space is a complete polynomial
-        space, but on other cells this is not true. For example, on quadrilateral cells, the degree 1
+        Note that on a simplex cells, the polynomial space of Lagrange
+        space is a complete polynomial space, but on other cells this is
+        not true. For example, on quadrilateral cells, the degree 1
         Lagrange space includes the degree 2 polynomial xy.
         """
 
     @_abc.abstractproperty
     def embedded_subdegree(self) -> int:
-        """Return the degree of the maximum degree Lagrange space that is spanned by this element.
+        """Degree of the maximum degree Lagrange space that is spanned by this element.
 
-        This returns the degree of the highest degree Lagrange space such that the polynomial
-        space of the Lagrange space is a subspace of this element's polynomial space. If this
-        element's polynomial space does not include the constant function, this function should
-        return -1.
+        This returns the degree of the highest degree Lagrange space
+        such that the polynomial space of the Lagrange space is a
+        subspace of this element's polynomial space. If this element's
+        polynomial space does not include the constant function, this
+        function should return -1.
 
-        Note that on a simplex cells, the polynomial space of Lagrange space is a complete polynomial
-        space, but on other cells this is not true. For example, on quadrilateral cells, the degree 1
+        Note that on a simplex cells, the polynomial space of Lagrange
+        space is a complete polynomial space, but on other cells this is
+        not true. For example, on quadrilateral cells, the degree 1
         Lagrange space includes the degree 2 polynomial xy.
         """
 
@@ -143,7 +149,7 @@ def components(self) -> _typing.Dict[_typing.Tuple[int, ...], int]:
         c_offset = 0
         for e in self.sub_elements:
             for i, j in enumerate(np.ndindex(e.value_shape)):
-                components[(offset + i, )] = c_offset + e.components[j]
+                components[(offset + i,)] = c_offset + e.components[j]
             c_offset += max(e.components.values()) + 1
             offset += e.value_size
         return components
@@ -165,15 +171,31 @@ def num_sub_elements(self) -> int:
 
 class FiniteElement(AbstractFiniteElement):
     """A directly defined finite element."""
-    __slots__ = ("_repr", "_str", "_family", "_cell", "_degree",
-                 "_reference_value_shape", "_pullback", "_sobolev_space",
-                 "_sub_elements", "_subdegree")
+
+    __slots__ = (
+        "_repr",
+        "_str",
+        "_family",
+        "_cell",
+        "_degree",
+        "_reference_value_shape",
+        "_pullback",
+        "_sobolev_space",
+        "_sub_elements",
+        "_subdegree",
+    )
 
     def __init__(
-        self, family: str, cell: _Cell, degree: int,
-        reference_value_shape: _typing.Tuple[int, ...], pullback: _AbstractPullback,
-        sobolev_space: _SobolevSpace, sub_elements=[],
-        _repr: _typing.Optional[str] = None, _str: _typing.Optional[str] = None,
+        self,
+        family: str,
+        cell: _Cell,
+        degree: int,
+        reference_value_shape: _typing.Tuple[int, ...],
+        pullback: _AbstractPullback,
+        sobolev_space: _SobolevSpace,
+        sub_elements=[],
+        _repr: _typing.Optional[str] = None,
+        _str: _typing.Optional[str] = None,
         subdegree: _typing.Optional[int] = None,
     ):
         """Initialise a finite element.
@@ -199,12 +221,14 @@ def __init__(
         if _repr is None:
             if len(sub_elements) > 0:
                 self._repr = (
-                    f"ufl.finiteelement.FiniteElement(\"{family}\", {cell}, {degree}, "
-                    f"{reference_value_shape}, {pullback}, {sobolev_space}, {sub_elements!r})")
+                    f'ufl.finiteelement.FiniteElement("{family}", {cell}, {degree}, '
+                    f"{reference_value_shape}, {pullback}, {sobolev_space}, {sub_elements!r})"
+                )
             else:
                 self._repr = (
-                    f"ufl.finiteelement.FiniteElement(\"{family}\", {cell}, {degree}, "
-                    f"{reference_value_shape}, {pullback}, {sobolev_space})")
+                    f'ufl.finiteelement.FiniteElement("{family}", {cell}, {degree}, '
+                    f"{reference_value_shape}, {pullback}, {sobolev_space})"
+                )
         else:
             self._repr = _repr
         if _str is None:
@@ -247,30 +271,34 @@ def pullback(self) -> _AbstractPullback:
 
     @property
     def embedded_superdegree(self) -> _typing.Union[int, None]:
-        """Return the degree of the minimum degree Lagrange space that spans this element.
+        """Degree of the minimum degree Lagrange space that spans this element.
 
-        This returns the degree of the lowest degree Lagrange space such that the polynomial
-        space of the Lagrange space is a superspace of this element's polynomial space. If this
-        element contains basis functions that are not in any Lagrange space, this function should
-        return None.
+        This returns the degree of the lowest degree Lagrange space such
+        that the polynomial space of the Lagrange space is a superspace
+        of this element's polynomial space. If this element contains
+        basis functions that are not in any Lagrange space, this
+        function should return None.
 
-        Note that on a simplex cells, the polynomial space of Lagrange space is a complete polynomial
-        space, but on other cells this is not true. For example, on quadrilateral cells, the degree 1
+        Note that on a simplex cells, the polynomial space of Lagrange
+        space is a complete polynomial space, but on other cells this is
+        not true. For example, on quadrilateral cells, the degree 1
         Lagrange space includes the degree 2 polynomial xy.
         """
         return self._degree
 
     @property
     def embedded_subdegree(self) -> int:
-        """Return the degree of the maximum degree Lagrange space that is spanned by this element.
+        """Degree of the maximum degree Lagrange space that is spanned by this element.
 
-        This returns the degree of the highest degree Lagrange space such that the polynomial
-        space of the Lagrange space is a subspace of this element's polynomial space. If this
-        element's polynomial space does not include the constant function, this function should
-        return -1.
+        This returns the degree of the highest degree Lagrange space
+        such that the polynomial space of the Lagrange space is a
+        subspace of this element's polynomial space. If this element's
+        polynomial space does not include the constant function, this
+        function should return -1.
 
-        Note that on a simplex cells, the polynomial space of Lagrange space is a complete polynomial
-        space, but on other cells this is not true. For example, on quadrilateral cells, the degree 1
+        Note that on a simplex cells, the polynomial space of Lagrange
+        space is a complete polynomial space, but on other cells this is
+        not true. For example, on quadrilateral cells, the degree 1
         Lagrange space includes the degree 2 polynomial xy.
         """
         return self._subdegree
@@ -289,8 +317,8 @@ def reference_value_shape(self) -> _typing.Tuple[int, ...]:
     def sub_elements(self) -> _typing.List:
         """Return list of sub-elements.
 
-        This function does not recurse: ie it does not extract the sub-elements
-        of sub-elements.
+        This function does not recurse: ie it does not extract the
+        sub-elements of sub-elements.
         """
         return self._sub_elements
 
@@ -301,7 +329,7 @@ class SymmetricElement(FiniteElement):
     def __init__(
         self,
         symmetry: _typing.Dict[_typing.Tuple[int, ...], int],
-        sub_elements: _typing.List[AbstractFiniteElement]
+        sub_elements: _typing.List[AbstractFiniteElement],
     ):
         """Initialise a symmetric element.
 
@@ -313,7 +341,7 @@ def __init__(
         """
         self._sub_elements = sub_elements
         pullback = _SymmetricPullback(self, symmetry)
-        reference_value_shape = (sum(e.reference_value_size for e in sub_elements), )
+        reference_value_shape = (sum(e.reference_value_size for e in sub_elements),)
         degree = max(e.embedded_superdegree for e in sub_elements)
         cell = sub_elements[0].cell
         for e in sub_elements:
@@ -322,10 +350,16 @@ def __init__(
         sobolev_space = max(e.sobolev_space for e in sub_elements)
 
         super().__init__(
-            "Symmetric element", cell, degree, reference_value_shape, pullback,
-            sobolev_space, sub_elements=sub_elements,
+            "Symmetric element",
+            cell,
+            degree,
+            reference_value_shape,
+            pullback,
+            sobolev_space,
+            sub_elements=sub_elements,
             _repr=(f"ufl.finiteelement.SymmetricElement({symmetry!r}, {sub_elements!r})"),
-            _str=f"<symmetric element on a {cell}>")
+            _str=f"<symmetric element on a {cell}>",
+        )
 
 
 class MixedElement(FiniteElement):
@@ -344,7 +378,7 @@ def __init__(self, sub_elements):
         for e in sub_elements:
             assert e.cell == cell
         degree = max(e.embedded_superdegree for e in sub_elements)
-        reference_value_shape = (sum(e.reference_value_size for e in sub_elements), )
+        reference_value_shape = (sum(e.reference_value_size for e in sub_elements),)
         if all(isinstance(e.pullback, _IdentityPullback) for e in sub_elements):
             pullback = _IdentityPullback()
         else:
@@ -352,7 +386,13 @@ def __init__(self, sub_elements):
         sobolev_space = max(e.sobolev_space for e in sub_elements)
 
         super().__init__(
-            "Mixed element", cell, degree, reference_value_shape, pullback, sobolev_space,
+            "Mixed element",
+            cell,
+            degree,
+            reference_value_shape,
+            pullback,
+            sobolev_space,
             sub_elements=sub_elements,
             _repr=f"ufl.finiteelement.MixedElement({sub_elements!r})",
-            _str=f"<MixedElement with {len(sub_elements)} sub-element(s)>")
+            _str=f"<MixedElement with {len(sub_elements)} sub-element(s)>",
+        )
diff --git a/ufl/form.py b/ufl/form.py
index 3f85b709d..34aa3d753 100644
--- a/ufl/form.py
+++ b/ufl/form.py
@@ -34,15 +34,20 @@
 
 
 def _sorted_integrals(integrals):
-    """Sort integrals by domain id, integral type, subdomain id for a more stable signature computation."""
+    """Sort integrals for a stable signature computation.
+
+    Sort integrals by domain id, integral type, subdomain id for a more
+    stable signature computation.
+    """
     # Group integrals in multilevel dict by keys
     # [domain][integral_type][subdomain_id]
-    integrals_dict = defaultdict(
-        lambda: defaultdict(lambda: defaultdict(list)))
+    integrals_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))
     for integral in integrals:
         d = integral.ufl_domain()
         if d is None:
-            raise ValueError("Each integral in a form must have a uniquely defined integration domain.")
+            raise ValueError(
+                "Each integral in a form must have a uniquely defined integration domain."
+            )
         it = integral.integral_type()
         si = integral.subdomain_id()
         integrals_dict[d][it][si] += [integral]
@@ -82,7 +87,7 @@ class BaseForm(object, metaclass=UFLType):
     # classes
     __slots__ = ()
     _ufl_is_abstract_ = True
-    _ufl_required_methods_ = ('_analyze_form_arguments', '_analyze_domains', "ufl_domains")
+    _ufl_required_methods_ = ("_analyze_form_arguments", "_analyze_domains", "ufl_domains")
 
     def __init__(self):
         """Initialise."""
@@ -191,6 +196,7 @@ def __mul__(self, coefficient):
         """Take the action of this form on the given coefficient."""
         if isinstance(coefficient, Expr):
             from ufl.formoperators import action
+
             return action(self, coefficient)
         return NotImplemented
 
@@ -201,6 +207,7 @@ def __ne__(self, other):
     def __call__(self, x):
         """Take the action of this form on ``x``."""
         from ufl.formoperators import action
+
         return action(self, x)
 
     def _ufl_compute_hash_(self):
@@ -221,7 +228,8 @@ class Form(BaseForm):
     """Description of a weak form consisting of a sum of integrals over subdomains."""
 
     __slots__ = (
-        # --- List of Integral objects (a Form is a sum of these Integrals, everything else is derived)
+        # --- List of Integral objects (a Form is a sum of these
+        # Integrals, everything else is derived)
         "_integrals",
         # --- Internal variables for caching various data
         "_integration_domains",
@@ -271,6 +279,7 @@ def __init__(self, integrals):
         self._base_form_operators = None
 
         from ufl.algorithms.analysis import extract_constants
+
         self._constants = extract_constants(self)
 
         # Internal variables for caching of hash and signature after
@@ -289,8 +298,9 @@ def integrals(self):
 
     def integrals_by_type(self, integral_type):
         """Return a sequence of all integrals with a particular domain type."""
-        return tuple(integral for integral in self.integrals()
-                     if integral.integral_type() == integral_type)
+        return tuple(
+            integral for integral in self.integrals() if integral.integral_type() == integral_type
+        )
 
     def integrals_by_domain(self, domain):
         """Return a sequence of all integrals with a particular integration domain."""
@@ -303,7 +313,8 @@ def empty(self):
     def ufl_domains(self):
         """Return the geometric integration domains occuring in the form.
 
-        NB! This does not include domains of coefficients defined on other meshes.
+        NB! This does not include domains of coefficients defined on
+        other meshes.
 
         The return type is a tuple even if only a single domain exists.
         """
@@ -324,26 +335,28 @@ def ufl_domain(self):
         Fails if multiple domains are found.
 
         NB! This does not include domains of coefficients defined on
-        other meshes, look at form data for that additional
-        information.
+        other meshes, look at form data for that additional information.
         """
         # Collect all domains
         domains = self.ufl_domains()
         # Check that all are equal TODO: don't return more than one if
         # all are equal?
         if not all(domain == domains[0] for domain in domains):
-            raise ValueError("Calling Form.ufl_domain() is only valid if all integrals share domain.")
+            raise ValueError(
+                "Calling Form.ufl_domain() is only valid if all integrals share domain."
+            )
 
         # Return the one and only domain
         return domains[0]
 
     def geometric_dimension(self):
         """Return the geometric dimension shared by all domains and functions in this form."""
-        gdims = tuple(
-            set(domain.geometric_dimension() for domain in self.ufl_domains()))
+        gdims = tuple(set(domain.geometric_dimension() for domain in self.ufl_domains()))
         if len(gdims) != 1:
-            raise ValueError("Expecting all domains and functions in a form "
-                             f"to share geometric dimension, got {tuple(sorted(gdims))}")
+            raise ValueError(
+                "Expecting all domains and functions in a form "
+                f"to share geometric dimension, got {tuple(sorted(gdims))}"
+            )
         return gdims[0]
 
     def domain_numbering(self):
@@ -477,9 +490,7 @@ def __add__(self, other):
             # Allow adding 0 or 0.0 as a no-op, needed for sum([a,b])
             return self
 
-        elif isinstance(
-                other,
-                Zero) and not (other.ufl_shape or other.ufl_free_indices):
+        elif isinstance(other, Zero) and not (other.ufl_shape or other.ufl_free_indices):
             # Allow adding ufl Zero as a no-op, needed for sum([a,b])
             return self
 
@@ -514,6 +525,7 @@ def __mul__(self, coefficient):
         """UFL form operator: Take the action of this form on the given coefficient."""
         if isinstance(coefficient, Expr):
             from ufl.formoperators import action
+
             return action(self, coefficient)
         return NotImplemented
 
@@ -559,6 +571,7 @@ def __call__(self, *args, **kwargs):
                     warnings.warn("Coefficient %s is not in form." % ufl_err_str(f))
         if repdict:
             from ufl.formoperators import replace
+
             return replace(self, repdict)
         else:
             return self
@@ -570,16 +583,18 @@ def __call__(self, *args, **kwargs):
     def __str__(self):
         """Compute shorter string representation of form. This can be huge for complicated forms."""
         # Warning used for making sure we don't use this in the general pipeline:
-        # warning("Calling str on form is potentially expensive and should be avoided except during debugging.")
-        # Not caching this because it can be huge
+        # warning("Calling str on form is potentially expensive and
+        # should be avoided except during debugging.") Not caching this
+        # because it can be huge
         s = "\n  +  ".join(str(itg) for itg in self.integrals())
         return s or "<empty Form>"
 
     def __repr__(self):
         """Compute repr string of form. This can be huge for complicated forms."""
         # Warning used for making sure we don't use this in the general pipeline:
-        # warning("Calling repr on form is potentially expensive and should be avoided except during debugging.")
-        # Not caching this because it can be huge
+        # warning("Calling repr on form is potentially expensive and
+        # should be avoided except during debugging.") Not caching this
+        # because it can be huge
         itgs = ", ".join(repr(itg) for itg in self.integrals())
         r = "Form([" + itgs + "])"
         return r
@@ -626,17 +641,17 @@ def _analyze_subdomain_data(self):
     def _analyze_form_arguments(self):
         """Analyze which Argument and Coefficient objects can be found in the form."""
         from ufl.algorithms.analysis import extract_arguments_and_coefficients
+
         arguments, coefficients = extract_arguments_and_coefficients(self)
 
         # Define canonical numbering of arguments and coefficients
-        self._arguments = tuple(
-            sorted(set(arguments), key=lambda x: x.number()))
-        self._coefficients = tuple(
-            sorted(set(coefficients), key=lambda x: x.count()))
+        self._arguments = tuple(sorted(set(arguments), key=lambda x: x.number()))
+        self._coefficients = tuple(sorted(set(coefficients), key=lambda x: x.count()))
 
     def _analyze_base_form_operators(self):
         """Analyze which BaseFormOperator objects can be found in the form."""
         from ufl.algorithms.analysis import extract_base_form_operators
+
         base_form_ops = extract_base_form_operators(self)
         self._base_form_operators = tuple(sorted(base_form_ops, key=lambda x: x.count()))
 
@@ -679,6 +694,7 @@ def _compute_renumbering(self):
     def _compute_signature(self):
         """Compute signature."""
         from ufl.algorithms.signature import compute_form_signature
+
         self._signature = compute_form_signature(self, self._compute_renumbering())
 
 
@@ -698,24 +714,28 @@ class FormSum(BaseForm):
     arg_weights is a list of tuples of component index and weight
     """
 
-    __slots__ = ("_arguments",
-                 "_coefficients",
-                 "_weights",
-                 "_components",
-                 "ufl_operands",
-                 "_domains",
-                 "_domain_numbering",
-                 "_hash")
-    _ufl_required_methods_ = ('_analyze_form_arguments')
+    __slots__ = (
+        "_arguments",
+        "_coefficients",
+        "_weights",
+        "_components",
+        "ufl_operands",
+        "_domains",
+        "_domain_numbering",
+        "_hash",
+    )
+    _ufl_required_methods_ = "_analyze_form_arguments"
 
     def __new__(cls, *args, **kwargs):
         """Create a new FormSum."""
         # All the components are `ZeroBaseForm`
         if all(component == 0 for component, _ in args):
-            # Assume that the arguments of all the components have consistent with each other  and select
-            # the first one to define the arguments of `ZeroBaseForm`.
-            # This might not always be true but `ZeroBaseForm`'s arguments are not checked anywhere
-            # because we can't reliably always infer them.
+            # Assume that the arguments of all the components have
+            # consistent with each other  and select the first one to
+            # define the arguments of `ZeroBaseForm`.
+            # This might not always be true but `ZeroBaseForm`'s
+            # arguments are not checked anywhere because we can't
+            # reliably always infer them.
             ((arg, _), *_) = args
             arguments = arg.arguments()
             return ZeroBaseForm(arguments)
@@ -731,7 +751,7 @@ def __init__(self, *components):
 
         weights = []
         full_components = []
-        for (component, w) in filtered_components:
+        for component, w in filtered_components:
             if isinstance(component, FormSum):
                 full_components.extend(component.components())
                 weights.extend([w * wc for wc in component.weights()])
@@ -762,7 +782,7 @@ def _sum_variational_components(self):
         var_forms = None
         other_components = []
         new_weights = []
-        for (i, component) in enumerate(self._components):
+        for i, component in enumerate(self._components):
             if isinstance(component, Form):
                 if var_forms:
                     var_forms = var_forms + (self._weights[i] * component)
@@ -785,10 +805,8 @@ def _analyze_form_arguments(self):
             arguments.extend(component.arguments())
             coefficients.extend(component.coefficients())
         # Define canonical numbering of arguments and coefficients
-        self._arguments = tuple(
-            sorted(set(arguments), key=lambda x: x.number()))
-        self._coefficients = tuple(
-            sorted(set(coefficients), key=lambda x: x.count()))
+        self._arguments = tuple(sorted(set(arguments), key=lambda x: x.number()))
+        self._coefficients = tuple(sorted(set(coefficients), key=lambda x: x.count()))
 
     def _analyze_domains(self):
         """Analyze which domains can be found in FormSum."""
@@ -809,13 +827,15 @@ def equals(self, other):
             return False
         if self is other:
             return True
-        return (len(self.components()) == len(other.components()) and  # noqa: W504
-                all(a == b for a, b in zip(self.components(), other.components())))
+        return len(self.components()) == len(other.components()) and all(
+            a == b for a, b in zip(self.components(), other.components())
+        )
 
     def __str__(self):
         """Compute shorter string representation of form. This can be huge for complicated forms."""
         # Warning used for making sure we don't use this in the general pipeline:
-        # warning("Calling str on form is potentially expensive and should be avoided except during debugging.")
+        # warning("Calling str on form is potentially expensive and
+        # should be avoided except during debugging.")
         # Not caching this because it can be huge
         s = "\n  +  ".join(str(component) for component in self.components())
         return s or "<empty FormSum>"
@@ -823,7 +843,8 @@ def __str__(self):
     def __repr__(self):
         """Compute repr string of form. This can be huge for complicated forms."""
         # Warning used for making sure we don't use this in the general pipeline:
-        # warning("Calling repr on form is potentially expensive and should be avoided except during debugging.")
+        # warning("Calling repr on form is potentially expensive and
+        # should be avoided except during debugging.")
         # Not caching this because it can be huge
         itgs = ", ".join(repr(component) for component in self.components())
         r = "FormSum([" + itgs + "])"
@@ -838,12 +859,14 @@ class ZeroBaseForm(BaseForm):
     used for sake of simplifying base-form expressions.
     """
 
-    __slots__ = ("_arguments",
-                 "_coefficients",
-                 "ufl_operands",
-                 "_hash",
-                 # Pyadjoint compatibility
-                 "form")
+    __slots__ = (
+        "_arguments",
+        "_coefficients",
+        "ufl_operands",
+        "_hash",
+        # Pyadjoint compatibility
+        "form",
+    )
 
     def __init__(self, arguments):
         """Initialise."""
@@ -867,7 +890,7 @@ def __eq__(self, other):
         if type(other) is ZeroBaseForm:
             if self is other:
                 return True
-            return (self._arguments == other._arguments)
+            return self._arguments == other._arguments
         elif isinstance(other, (int, float)):
             return other == 0
         else:
diff --git a/ufl/formatting/ufl2unicode.py b/ufl/formatting/ufl2unicode.py
index 0a5f0549f..0ed83ed1c 100644
--- a/ufl/formatting/ufl2unicode.py
+++ b/ufl/formatting/ufl2unicode.py
@@ -11,6 +11,7 @@
 
 try:
     import colorama
+
     has_colorama = True
 except ImportError:
     has_colorama = False
@@ -26,6 +27,7 @@ def __init__(self):
     def highest(self, o):
         """Return the highest precendence."""
         return 0
+
     terminal = highest
     list_tensor = highest
     component_tensor = highest
@@ -33,12 +35,14 @@ def highest(self, o):
     def restricted(self, o):
         """Return precedence of a restriced."""
         return 5
+
     cell_avg = restricted
     facet_avg = restricted
 
     def call(self, o):
         """Return precedence of a call."""
         return 10
+
     indexed = call
     min_value = call
     max_value = call
@@ -52,6 +56,7 @@ def power(self, o):
     def mathop(self, o):
         """Return precedence of a mathop."""
         return 15
+
     derivative = mathop
     trace = mathop
     deviatoric = mathop
@@ -66,6 +71,7 @@ def not_condition(self, o):
     def product(self, o):
         """Return precedence of a product."""
         return 30
+
     division = product
     # mod = product
     dot = product
@@ -76,12 +82,14 @@ def product(self, o):
     def add(self, o):
         """Return precedence of an add."""
         return 40
+
     # sub = add
     index_sum = add
 
     def lt(self, o):
         """Return precedence of a lt."""
         return 50
+
     le = lt
     gt = lt
     ge = lt
@@ -89,6 +97,7 @@ def lt(self, o):
     def eq(self, o):
         """Return precedence of an eq."""
         return 60
+
     ne = eq
 
     def and_condition(self, o):
@@ -106,6 +115,7 @@ def conditional(self, o):
     def lowest(self, o):
         """Return precedence of a lowest."""
         return 80
+
     operator = lowest
 
 
@@ -121,70 +131,70 @@ class UC:
     """An enum-like class for unicode characters."""
 
     # Letters in this alphabet have contiguous code point numbers
-    bold_math_a = u"𝐚"
-    bold_math_A = u"𝐀"
+    bold_math_a = "𝐚"
+    bold_math_A = "𝐀"
 
-    thin_space = u"\u2009"
+    thin_space = "\u2009"
 
-    superscript_plus = u"⁺"
-    superscript_minus = u"⁻"
-    superscript_equals = u"⁼"
-    superscript_left_paren = u"⁽"
-    superscript_right_paren = u"⁾"
+    superscript_plus = "⁺"
+    superscript_minus = "⁻"
+    superscript_equals = "⁼"
+    superscript_left_paren = "⁽"
+    superscript_right_paren = "⁾"
     superscript_digits = ["⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"]
 
-    subscript_plus = u"₊"
-    subscript_minus = u"₋"
-    subscript_equals = u"₌"
-    subscript_left_paren = u"₍"
-    subscript_right_paren = u"₎"
+    subscript_plus = "₊"
+    subscript_minus = "₋"
+    subscript_equals = "₌"
+    subscript_left_paren = "₍"
+    subscript_right_paren = "₎"
     subscript_digits = ["₀", "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉"]
 
-    sqrt = u"√"
-    transpose = u"ᵀ"
+    sqrt = "√"
+    transpose = "ᵀ"
 
-    integral = u"∫"
-    integral_double = u"∬"
-    integral_triple = u"∭"
-    integral_contour = u"∮"
-    integral_surface = u"∯"
-    integral_volume = u"∰"
+    integral = "∫"
+    integral_double = "∬"
+    integral_triple = "∭"
+    integral_contour = "∮"
+    integral_surface = "∯"
+    integral_volume = "∰"
 
-    sum = u"∑"
+    sum = "∑"
     division_slash = "∕"
-    partial = u"∂"
-    epsilon = u"ε"
-    omega = u"ω"
-    Omega = u"Ω"
-    gamma = u"γ"
-    Gamma = u"Γ"
-    nabla = u"∇"
-    for_all = u"∀"
-
-    dot = u"⋅"
-    cross_product = u"⨯"
-    circled_times = u"⊗"
-    nary_product = u"∏"
-
-    ne = u"≠"
-    lt = u"<"
-    le = u"≤"
-    gt = u">"
-    ge = u"≥"
-
-    logical_and = u"∧"
-    logical_or = u"∨"
-    logical_not = u"¬"
-
-    element_of = u"∈"
-    not_element_of = u"∉"
-
-    left_white_square_bracket = u"⟦"
-    right_white_squared_bracket = u"⟧"
-    left_angled_bracket = u"⟨"
-    right_angled_bracket = u"⟩"
-    left_double_angled_bracket = u"⟪"
-    right_double_angled_bracket = u"⟫"
+    partial = "∂"
+    epsilon = "ε"
+    omega = "ω"
+    Omega = "Ω"
+    gamma = "γ"
+    Gamma = "Γ"
+    nabla = "∇"
+    for_all = "∀"
+
+    dot = "⋅"
+    cross_product = "⨯"
+    circled_times = "⊗"
+    nary_product = "∏"
+
+    ne = "≠"
+    lt = "<"
+    le = "≤"
+    gt = ">"
+    ge = "≥"
+
+    logical_and = "∧"
+    logical_or = "∨"
+    logical_not = "¬"
+
+    element_of = "∈"
+    not_element_of = "∉"
+
+    left_white_square_bracket = "⟦"
+    right_white_squared_bracket = "⟧"
+    left_angled_bracket = "⟨"
+    right_angled_bracket = "⟩"
+    left_double_angled_bracket = "⟪"
+    right_double_angled_bracket = "⟫"
 
     combining_right_arrow_above = "\u20D7"
     combining_overline = "\u0305"
@@ -193,9 +203,9 @@ class UC:
 def bolden_letter(c):
     """Bolden a letter."""
     if ord("A") <= ord(c) <= ord("Z"):
-        c = chr(ord(c) - ord(u"A") + ord(UC.bold_math_A))
+        c = chr(ord(c) - ord("A") + ord(UC.bold_math_A))
     elif ord("a") <= ord(c) <= ord("z"):
-        c = chr(ord(c) - ord(u"a") + ord(UC.bold_math_a))
+        c = chr(ord(c) - ord("a") + ord(UC.bold_math_a))
     return c
 
 
@@ -211,12 +221,12 @@ def subscript_digit(digit):
 
 def bolden_string(s):
     """Bolden a string."""
-    return u"".join(bolden_letter(c) for c in s)
+    return "".join(bolden_letter(c) for c in s)
 
 
 def overline_string(f):
     """Overline a string."""
-    return u"".join(f"{c}{UC.combining_overline}" for c in f)
+    return "".join(f"{c}{UC.combining_overline}" for c in f)
 
 
 def subscript_number(number):
@@ -245,12 +255,7 @@ def measure_font(dx):
     return bolden_string(dx)
 
 
-integral_by_dim = {
-    3: UC.integral_triple,
-    2: UC.integral_double,
-    1: UC.integral,
-    0: UC.integral
-}
+integral_by_dim = {3: UC.integral_triple, 2: UC.integral_double, 1: UC.integral, 0: UC.integral}
 
 integral_type_to_codim = {
     "cell": 0,
@@ -366,8 +371,7 @@ def form2unicode(form, formdata):
     lines = []
     integrals = form.integrals()
     for itg in integrals:
-        integrand_string = expression2unicode(
-            itg.integrand(), argument_names, coefficient_names)
+        integrand_string = expression2unicode(itg.integrand(), argument_names, coefficient_names)
 
         istr, dxstr = get_integral_symbol(itg.integral_type(), itg.ufl_domain(), itg.subdomain_id())
 
@@ -783,7 +787,7 @@ def conditional(self, o, c, t, f):
         f = par(t)
         If = opfont("if")
         Else = opfont("else")
-        return " ".join((t, If, c, Else, f))
+        return f"{t} {If} {c} {Else} {f}"
 
     def min_value(self, o, a, b):
         """Format an min_value."""
diff --git a/ufl/formoperators.py b/ufl/formoperators.py
index d5cc31117..6616c7fff 100644
--- a/ufl/formoperators.py
+++ b/ufl/formoperators.py
@@ -11,17 +11,32 @@
 
 from ufl.action import Action
 from ufl.adjoint import Adjoint
-from ufl.algorithms import replace  # noqa: F401
-from ufl.algorithms import (compute_energy_norm, compute_form_action, compute_form_adjoint, compute_form_functional,
-                            compute_form_lhs, compute_form_rhs, expand_derivatives, extract_arguments, formsplitter)
+from ufl.algorithms import (
+    compute_energy_norm,
+    compute_form_action,
+    compute_form_adjoint,
+    compute_form_functional,
+    compute_form_lhs,
+    compute_form_rhs,
+    expand_derivatives,
+    extract_arguments,
+    formsplitter,
+    replace,  # noqa: F401
+)
 from ufl.argument import Argument
 from ufl.coefficient import Coefficient, Cofunction
 from ufl.constantvalue import as_ufl, is_true_ufl_scalar
 from ufl.core.base_form_operator import BaseFormOperator
 from ufl.core.expr import Expr, ufl_err_str
 from ufl.core.multiindex import FixedIndex, MultiIndex
-from ufl.differentiation import (BaseFormCoordinateDerivative, BaseFormDerivative, BaseFormOperatorCoordinateDerivative,
-                                 BaseFormOperatorDerivative, CoefficientDerivative, CoordinateDerivative)
+from ufl.differentiation import (
+    BaseFormCoordinateDerivative,
+    BaseFormDerivative,
+    BaseFormOperatorCoordinateDerivative,
+    BaseFormOperatorDerivative,
+    CoefficientDerivative,
+    CoordinateDerivative,
+)
 from ufl.exprcontainers import ExprList, ExprMapping
 from ufl.finiteelement import MixedElement
 from ufl.form import BaseForm, Form, FormSum, ZeroBaseForm, as_form
@@ -107,8 +122,9 @@ def action(form, coefficient=None, derivatives_expanded=None):
     become expensive -> `derivatives_expanded` enables to use caching mechanisms to avoid that.
     """
     form = as_form(form)
-    is_coefficient_valid = (not isinstance(coefficient, BaseForm) or
-                            (isinstance(coefficient, BaseFormOperator) and len(coefficient.arguments()) == 1))
+    is_coefficient_valid = not isinstance(coefficient, BaseForm) or (
+        isinstance(coefficient, BaseFormOperator) and len(coefficient.arguments()) == 1
+    )
     # Can't expand derivatives on objects that are not Form or Expr (e.g. Matrix)
     if isinstance(form, (Form, BaseFormOperator)) and is_coefficient_valid:
         if not derivatives_expanded:
@@ -191,8 +207,12 @@ def _handle_derivative_arguments(form, coefficient, argument):
 
     if argument is None:
         # Try to create argument if not provided
-        if not all(isinstance(c, (Coefficient, Cofunction, BaseFormOperator)) for c in coefficients):
-            raise ValueError("Can only create arguments automatically for non-indexed coefficients.")
+        if not all(
+            isinstance(c, (Coefficient, Cofunction, BaseFormOperator)) for c in coefficients
+        ):
+            raise ValueError(
+                "Can only create arguments automatically for non-indexed coefficients."
+            )
 
         # Get existing arguments from form and position the new one
         # with the next argument number
@@ -241,7 +261,7 @@ def _handle_derivative_arguments(form, coefficient, argument):
 
     # Build mapping from coefficient to argument
     m = {}
-    for (c, a) in zip(coefficients, arguments):
+    for c, a in zip(coefficients, arguments):
         if c.ufl_shape != a.ufl_shape:
             raise ValueError("Coefficient and argument shapes do not match!")
         if isinstance(c, (Coefficient, Cofunction, BaseFormOperator, SpatialCoordinate)):
@@ -297,12 +317,16 @@ def derivative(form, coefficient, argument=None, coefficient_derivatives=None):
     """
     if isinstance(form, FormSum):
         # Distribute derivative over FormSum components
-        return FormSum(*[(derivative(component, coefficient, argument, coefficient_derivatives), 1)
-                         for component in form.components()])
+        return FormSum(
+            *[
+                (derivative(component, coefficient, argument, coefficient_derivatives), 1)
+                for component in form.components()
+            ]
+        )
     elif isinstance(form, Adjoint):
         # Is `derivative(Adjoint(A), ...)` with A a 2-form even legal ?
         # -> If yes, what's the right thing to do here ?
-        raise NotImplementedError('Adjoint derivative is not supported.')
+        raise NotImplementedError("Adjoint derivative is not supported.")
     elif isinstance(form, Action):
         # Push derivative through Action slots
         left, right = form.ufl_operands
@@ -314,13 +338,15 @@ def derivative(form, coefficient, argument=None, coefficient_derivatives=None):
             dleft = derivative(left, coefficient, argument, coefficient_derivatives)
             dright = derivative(right, coefficient, argument, coefficient_derivatives)
             # Leibniz formula
-            return (action(adjoint(dleft, derivatives_expanded=True), right, derivatives_expanded=True)
-                    + action(left, dright, derivatives_expanded=True))
+            return action(
+                adjoint(dleft, derivatives_expanded=True), right, derivatives_expanded=True
+            ) + action(left, dright, derivatives_expanded=True)
         else:
-            raise NotImplementedError('Action derivative not supported when the left argument is not a 1-form.')
+            raise NotImplementedError(
+                "Action derivative not supported when the left argument is not a 1-form."
+            )
 
-    coefficients, arguments = _handle_derivative_arguments(form, coefficient,
-                                                           argument)
+    coefficients, arguments = _handle_derivative_arguments(form, coefficient, argument)
     if coefficient_derivatives is None:
         coefficient_derivatives = ExprMapping()
     else:
@@ -334,38 +360,46 @@ def derivative(form, coefficient, argument=None, coefficient_derivatives=None):
         integrals = []
         for itg in form.integrals():
             if isinstance(coefficient, SpatialCoordinate):
-                fd = CoordinateDerivative(itg.integrand(), coefficients,
-                                          arguments, coefficient_derivatives)
-            elif isinstance(coefficient, BaseForm) and not isinstance(coefficient, BaseFormOperator):
+                fd = CoordinateDerivative(
+                    itg.integrand(), coefficients, arguments, coefficient_derivatives
+                )
+            elif isinstance(coefficient, BaseForm) and not isinstance(
+                coefficient, BaseFormOperator
+            ):
                 # Make the `ZeroBaseForm` arguments
                 arguments = form.arguments() + coefficient.arguments()
                 return ZeroBaseForm(arguments)
             else:
-                fd = CoefficientDerivative(itg.integrand(), coefficients,
-                                           arguments, coefficient_derivatives)
+                fd = CoefficientDerivative(
+                    itg.integrand(), coefficients, arguments, coefficient_derivatives
+                )
             integrals.append(itg.reconstruct(fd))
         return Form(integrals)
 
     elif isinstance(form, BaseFormOperator):
         if not isinstance(coefficient, SpatialCoordinate):
-            return BaseFormOperatorDerivative(form, coefficients, arguments, coefficient_derivatives)
+            return BaseFormOperatorDerivative(
+                form, coefficients, arguments, coefficient_derivatives
+            )
         else:
-            return BaseFormOperatorCoordinateDerivative(form, coefficients, arguments, coefficient_derivatives)
+            return BaseFormOperatorCoordinateDerivative(
+                form, coefficients, arguments, coefficient_derivatives
+            )
 
     elif isinstance(form, BaseForm):
         if not isinstance(coefficient, SpatialCoordinate):
             return BaseFormDerivative(form, coefficients, arguments, coefficient_derivatives)
         else:
-            return BaseFormCoordinateDerivative(form, coefficients, arguments, coefficient_derivatives)
+            return BaseFormCoordinateDerivative(
+                form, coefficients, arguments, coefficient_derivatives
+            )
 
     elif isinstance(form, Expr):
         # What we got was in fact an integrand
         if not isinstance(coefficient, SpatialCoordinate):
-            return CoefficientDerivative(form, coefficients,
-                                         arguments, coefficient_derivatives)
+            return CoefficientDerivative(form, coefficients, arguments, coefficient_derivatives)
         else:
-            return CoordinateDerivative(form, coefficients,
-                                        arguments, coefficient_derivatives)
+            return CoordinateDerivative(form, coefficients, arguments, coefficient_derivatives)
 
     raise ValueError(f"Invalid argument type {type(form)}.")
 
@@ -397,8 +431,8 @@ def sensitivity_rhs(a, u, L, v):
     ::
 
         v = variable(v_expression)
-        L = IL(v)*dx
-        a = Ia(v)*dx
+        L = IL(v) * dx
+        a = Ia(v) * dx
 
     where ``IL`` and ``Ia`` are integrand expressions.
     Define a ``Coefficient u`` representing the solution
@@ -425,9 +459,17 @@ def sensitivity_rhs(a, u, L, v):
 
         dL = sensitivity_rhs(a, u, L, v)
     """
-    if not (isinstance(a, Form) and isinstance(u, Coefficient) and isinstance(L, Form) and isinstance(v, Variable)):
-        raise ValueError("Expecting (a, u, L, v), (bilinear form, function, linear form and scalar variable).")
+    if not (
+        isinstance(a, Form)
+        and isinstance(u, Coefficient)
+        and isinstance(L, Form)
+        and isinstance(v, Variable)
+    ):
+        raise ValueError(
+            "Expecting (a, u, L, v), (bilinear form, function, linear form and scalar variable)."
+        )
     if not is_true_ufl_scalar(v):
         raise ValueError("Expecting scalar variable.")
     from ufl.operators import diff
+
     return diff(L, v) - action(diff(a, v), u)
diff --git a/ufl/functionspace.py b/ufl/functionspace.py
index 38839bc20..cc047523c 100644
--- a/ufl/functionspace.py
+++ b/ufl/functionspace.py
@@ -49,7 +49,9 @@ def __init__(self, domain, element, label=""):
             try:
                 domain_cell = domain.ufl_cell()
             except AttributeError:
-                raise ValueError("Expected non-abstract domain for initalization of function space.")
+                raise ValueError(
+                    "Expected non-abstract domain for initalization of function space."
+                )
             else:
                 if element.cell != domain_cell:
                     raise ValueError("Non-matching cell of finite element and domain.")
@@ -199,14 +201,15 @@ def ufl_sub_spaces(self):
 
     def _ufl_hash_data_(self):
         """UFL hash data."""
-        return ("TensorProductFunctionSpace",) \
-            + tuple(V._ufl_hash_data_() for V in self.ufl_sub_spaces())
+        return ("TensorProductFunctionSpace",) + tuple(
+            V._ufl_hash_data_() for V in self.ufl_sub_spaces()
+        )
 
     def _ufl_signature_data_(self, renumbering):
         """UFL signature data."""
-        return ("TensorProductFunctionSpace",) \
-            + tuple(V._ufl_signature_data_(renumbering)
-                    for V in self.ufl_sub_spaces())
+        return ("TensorProductFunctionSpace",) + tuple(
+            V._ufl_signature_data_(renumbering) for V in self.ufl_sub_spaces()
+        )
 
     def __repr__(self):
         """Representation."""
@@ -232,10 +235,8 @@ def __init__(self, *args):
                 raise ValueError("Expecting BaseFunctionSpace objects")
 
         # A mixed FS is only primal/dual if all the subspaces are primal/dual"
-        self._primal = all([is_primal(subspace)
-                            for subspace in self._ufl_function_spaces])
-        self._dual = all([is_dual(subspace)
-                          for subspace in self._ufl_function_spaces])
+        self._primal = all([is_primal(subspace) for subspace in self._ufl_function_spaces])
+        self._dual = all([is_dual(subspace) for subspace in self._ufl_function_spaces])
 
     def ufl_sub_spaces(self):
         """Return ufl sub spaces."""
@@ -257,13 +258,13 @@ def dual(self, *args):
         the original components in the other positions.
         """
         if args:
-            spaces = [space.dual() if i in args else space
-                      for i, space in enumerate(self._ufl_function_spaces)]
+            spaces = [
+                space.dual() if i in args else space
+                for i, space in enumerate(self._ufl_function_spaces)
+            ]
             return MixedFunctionSpace(*spaces)
         else:
-            return MixedFunctionSpace(
-                *[space.dual()for space in self._ufl_function_spaces]
-            )
+            return MixedFunctionSpace(*[space.dual() for space in self._ufl_function_spaces])
 
     def ufl_elements(self):
         """Return ufl elements."""
@@ -277,7 +278,8 @@ def ufl_element(self):
             raise ValueError(
                 "Found multiple elements. Cannot return only one. "
                 "Consider building a FunctionSpace from a MixedElement "
-                "in case of homogeneous dimension.")
+                "in case of homogeneous dimension."
+            )
 
     def ufl_domains(self):
         """Return ufl domains."""
@@ -302,14 +304,13 @@ def num_sub_spaces(self):
 
     def _ufl_hash_data_(self):
         """UFL hash data."""
-        return ("MixedFunctionSpace",) \
-            + tuple(V._ufl_hash_data_() for V in self.ufl_sub_spaces())
+        return ("MixedFunctionSpace",) + tuple(V._ufl_hash_data_() for V in self.ufl_sub_spaces())
 
     def _ufl_signature_data_(self, renumbering):
         """UFL signature data."""
-        return ("MixedFunctionSpace",) \
-            + tuple(V._ufl_signature_data_(renumbering)
-                    for V in self.ufl_sub_spaces())
+        return ("MixedFunctionSpace",) + tuple(
+            V._ufl_signature_data_(renumbering) for V in self.ufl_sub_spaces()
+        )
 
     def __repr__(self):
         """Representation."""
diff --git a/ufl/geometry.py b/ufl/geometry.py
index 9566e8aa6..1acaf40a2 100644
--- a/ufl/geometry.py
+++ b/ufl/geometry.py
@@ -74,6 +74,7 @@
 
 # --- Expression node types
 
+
 @ufl_type(is_abstract=True)
 class GeometricQuantity(Terminal):
     """Geometric quantity."""
@@ -137,6 +138,7 @@ class GeometricFacetQuantity(GeometricQuantity):
 
 # --- Coordinate represented in different coordinate systems
 
+
 @ufl_type()
 class SpatialCoordinate(GeometricCellQuantity):
     """The coordinate in a domain.
@@ -244,6 +246,7 @@ def is_cellwise_constant(self):
 
 # --- Origin of coordinate systems in larger coordinate systems
 
+
 @ufl_type()
 class CellOrigin(GeometricCellQuantity):
     """The spatial coordinate corresponding to origin of a reference cell."""
@@ -292,6 +295,7 @@ def ufl_shape(self):
 
 # --- Jacobians of mappings between coordinate systems
 
+
 @ufl_type()
 class Jacobian(GeometricCellQuantity):
     r"""The Jacobian of the mapping from reference cell to spatial coordinates.
@@ -534,11 +538,13 @@ def is_cellwise_constant(self):
 
 # --- Determinants (signed or pseudo) of geometry mapping Jacobians
 
+
 @ufl_type()
 class JacobianDeterminant(GeometricCellQuantity):
     """The determinant of the Jacobian.
 
-    Represents the signed determinant of a square Jacobian or the pseudo-determinant of a non-square Jacobian.
+    Represents the signed determinant of a square Jacobian or the
+    pseudo-determinant of a non-square Jacobian.
     """
 
     __slots__ = ()
@@ -580,11 +586,13 @@ def is_cellwise_constant(self):
 
 # --- Inverses (signed or pseudo) of geometry mapping Jacobians
 
+
 @ufl_type()
 class JacobianInverse(GeometricCellQuantity):
     """The inverse of the Jacobian.
 
-    Represents the inverse of a square Jacobian or the pseudo-inverse of a non-square Jacobian.
+    Represents the inverse of a square Jacobian or the pseudo-inverse of
+    a non-square Jacobian.
     """
 
     __slots__ = ()
@@ -616,7 +624,9 @@ def __init__(self, domain):
         GeometricFacetQuantity.__init__(self, domain)
         t = self._domain.topological_dimension()
         if t < 2:
-            raise ValueError("FacetJacobianInverse is only defined for topological dimensions >= 2.")
+            raise ValueError(
+                "FacetJacobianInverse is only defined for topological dimensions >= 2."
+            )
 
     @property
     def ufl_shape(self):
@@ -644,7 +654,9 @@ def __init__(self, domain):
         GeometricFacetQuantity.__init__(self, domain)
         t = self._domain.topological_dimension()
         if t < 2:
-            raise ValueError("CellFacetJacobianInverse is only defined for topological dimensions >= 2.")
+            raise ValueError(
+                "CellFacetJacobianInverse is only defined for topological dimensions >= 2."
+            )
 
     @property
     def ufl_shape(self):
@@ -660,6 +672,7 @@ def is_cellwise_constant(self):
 
 # --- Types representing normal or tangent vectors
 
+
 @ufl_type()
 class FacetNormal(GeometricFacetQuantity):
     """The outwards pointing normal vector of the current facet."""
@@ -718,7 +731,9 @@ def ufl_shape(self):
         t = self._domain.topological_dimension()
         return (t,)
 
-# --- Types representing measures of the cell and entities of the cell, typically used for stabilisation terms
+
+# --- Types representing measures of the cell and entities of the cell,
+# typically used for stabilisation terms
 
 # TODO: Clean up this set of types? Document!
 
@@ -805,6 +820,7 @@ class MaxFacetEdgeLength(GeometricFacetQuantity):
 
 # --- Types representing other stuff
 
+
 @ufl_type()
 class CellOrientation(GeometricCellQuantity):
     """The orientation (+1/-1) of the current cell.
diff --git a/ufl/index_combination_utils.py b/ufl/index_combination_utils.py
index 1f7682ae0..8bd5087a8 100644
--- a/ufl/index_combination_utils.py
+++ b/ufl/index_combination_utils.py
@@ -233,4 +233,9 @@ def merge_overlapping_indices(afi, afid, bfi, bfid):
     if len(free_indices) + 2 * len(repeated_indices) != an + bn:
         raise ValueError("Expecting only twice repeated indices.")
 
-    return tuple(free_indices), tuple(index_dimensions), tuple(repeated_indices), tuple(repeated_index_dimensions)
+    return (
+        tuple(free_indices),
+        tuple(index_dimensions),
+        tuple(repeated_indices),
+        tuple(repeated_index_dimensions),
+    )
diff --git a/ufl/indexed.py b/ufl/indexed.py
index b22f3d7ef..9f6525863 100644
--- a/ufl/indexed.py
+++ b/ufl/indexed.py
@@ -63,10 +63,13 @@ def __init__(self, expression, multiindex):
         if len(shape) != len(multiindex):
             raise ValueError(
                 f"Invalid number of indices ({len(multiindex)}) for tensor "
-                f"expression of rank {len(expression.ufl_shape)}:\n    {ufl_err_str(expression)}")
-        if any(int(di) >= int(si) or int(di) < 0
-               for si, di in zip(shape, multiindex)
-               if isinstance(di, FixedIndex)):
+                f"expression of rank {len(expression.ufl_shape)}:\n    {ufl_err_str(expression)}"
+            )
+        if any(
+            int(di) >= int(si) or int(di) < 0
+            for si, di in zip(shape, multiindex)
+            if isinstance(di, FixedIndex)
+        ):
             raise ValueError("Fixed index out of range!")
 
         # Build tuples of free index ids and dimensions
@@ -99,8 +102,7 @@ def evaluate(self, x, mapping, component, index_values, derivatives=()):
 
     def __str__(self):
         """Format as a string."""
-        return "%s[%s]" % (parstr(self.ufl_operands[0], self),
-                           self.ufl_operands[1])
+        return "%s[%s]" % (parstr(self.ufl_operands[0], self), self.ufl_operands[1])
 
     def __getitem__(self, key):
         """Get an item."""
@@ -108,5 +110,7 @@ def __getitem__(self, key):
             # So that one doesn't have to special case indexing of
             # expressions without shape.
             return self
-        raise ValueError(f"Attempting to index with {ufl_err_str(key)}, "
-                         f"but object is already indexed: {ufl_err_str(self)}")
+        raise ValueError(
+            f"Attempting to index with {ufl_err_str(key)}, "
+            f"but object is already indexed: {ufl_err_str(self)}"
+        )
diff --git a/ufl/indexsum.py b/ufl/indexsum.py
index b13829484..df636b58c 100644
--- a/ufl/indexsum.py
+++ b/ufl/indexsum.py
@@ -36,25 +36,25 @@ def __new__(cls, summand, index):
         # Simplification to zero
         if isinstance(summand, Zero):
             sh = summand.ufl_shape
-            j, = index
+            (j,) = index
             fi = summand.ufl_free_indices
             fid = summand.ufl_index_dimensions
             pos = fi.index(j.count())
-            fi = fi[:pos] + fi[pos + 1:]
-            fid = fid[:pos] + fid[pos + 1:]
+            fi = fi[:pos] + fi[pos + 1 :]
+            fid = fid[:pos] + fid[pos + 1 :]
             return Zero(sh, fi, fid)
 
         return Operator.__new__(cls)
 
     def __init__(self, summand, index):
         """Initialise."""
-        j, = index
+        (j,) = index
         fi = summand.ufl_free_indices
         fid = summand.ufl_index_dimensions
         pos = fi.index(j.count())
         self._dimension = fid[pos]
-        self.ufl_free_indices = fi[:pos] + fi[pos + 1:]
-        self.ufl_index_dimensions = fid[:pos] + fid[pos + 1:]
+        self.ufl_free_indices = fi[:pos] + fi[pos + 1 :]
+        self.ufl_index_dimensions = fid[:pos] + fid[pos + 1 :]
         Operator.__init__(self, (summand, index))
 
     def index(self):
@@ -72,16 +72,14 @@ def ufl_shape(self):
 
     def evaluate(self, x, mapping, component, index_values):
         """Evaluate."""
-        i, = self.ufl_operands[1]
+        (i,) = self.ufl_operands[1]
         tmp = 0
         for k in range(self._dimension):
             index_values.push(i, k)
-            tmp += self.ufl_operands[0].evaluate(x, mapping, component,
-                                                 index_values)
+            tmp += self.ufl_operands[0].evaluate(x, mapping, component, index_values)
             index_values.pop()
         return tmp
 
     def __str__(self):
         """Format as a string."""
-        return "sum_{%s} %s " % (str(self.ufl_operands[1]),
-                                 parstr(self.ufl_operands[0], self))
+        return "sum_{%s} %s " % (str(self.ufl_operands[1]), parstr(self.ufl_operands[0], self))
diff --git a/ufl/integral.py b/ufl/integral.py
index d680f5a77..510f4ebd5 100644
--- a/ufl/integral.py
+++ b/ufl/integral.py
@@ -12,7 +12,6 @@
 import ufl
 from ufl.checks import is_python_scalar, is_scalar_constant_expression
 from ufl.core.expr import Expr
-from ufl.measure import Measure  # noqa
 from ufl.protocols import id_or_none
 
 # Export list for ufl.classes
@@ -22,11 +21,16 @@
 class Integral(object):
     """An integral over a single domain."""
 
-    __slots__ = ("_integrand", "_integral_type", "_ufl_domain", "_subdomain_id", "_metadata", "_subdomain_data")
+    __slots__ = (
+        "_integrand",
+        "_integral_type",
+        "_ufl_domain",
+        "_subdomain_id",
+        "_metadata",
+        "_subdomain_data",
+    )
 
-    def __init__(
-        self, integrand, integral_type, domain, subdomain_id, metadata, subdomain_data
-    ):
+    def __init__(self, integrand, integral_type, domain, subdomain_id, metadata, subdomain_data):
         """Initialise."""
         if not isinstance(integrand, Expr):
             raise ValueError("Expecting integrand to be an Expr instance.")
@@ -38,9 +42,13 @@ def __init__(
         self._subdomain_data = subdomain_data
 
     def reconstruct(
-        self, integrand=None,
-        integral_type=None, domain=None, subdomain_id=None,
-        metadata=None, subdomain_data=None
+        self,
+        integrand=None,
+        integral_type=None,
+        domain=None,
+        subdomain_id=None,
+        metadata=None,
+        subdomain_data=None,
     ):
         """Construct a new Integral object with some properties replaced with new values.
 
@@ -100,8 +108,9 @@ def __mul__(self, scalar):
     def __rmul__(self, scalar):
         """Multiply."""
         if not is_scalar_constant_expression(scalar):
-            raise ValueError("An integral can only be multiplied by a "
-                             "globally constant scalar expression.")
+            raise ValueError(
+                "An integral can only be multiplied by a globally constant scalar expression."
+            )
         return self.reconstruct(scalar * self._integrand)
 
     def __str__(self):
@@ -113,24 +122,33 @@ def __str__(self):
 
     def __repr__(self):
         """Representation."""
-        return (f"Integral({self._integrand!r}, {self._integral_type!r}, {self._ufl_domain!r}, "
-                f"{self._subdomain_id!r}, {self._metadata!r}, {self._subdomain_data!r})")
+        return (
+            f"Integral({self._integrand!r}, {self._integral_type!r}, {self._ufl_domain!r}, "
+            f"{self._subdomain_id!r}, {self._metadata!r}, {self._subdomain_data!r})"
+        )
 
     def __eq__(self, other):
         """Check equality."""
-        return (isinstance(other, Integral) and self._integral_type == other._integral_type and  # noqa: W504
-                self._ufl_domain == other._ufl_domain and self._subdomain_id == other._subdomain_id and  # noqa: W504
-                self._integrand == other._integrand and self._metadata == other._metadata and  # noqa: W504
-                id_or_none(self._subdomain_data) == id_or_none(other._subdomain_data))
+        return (
+            isinstance(other, Integral)
+            and self._integral_type == other._integral_type
+            and self._ufl_domain == other._ufl_domain
+            and self._subdomain_id == other._subdomain_id
+            and self._integrand == other._integrand
+            and self._metadata == other._metadata
+            and id_or_none(self._subdomain_data) == id_or_none(other._subdomain_data)
+        )
 
     def __hash__(self):
         """Hash."""
         # Assuming few collisions by ignoring hash(self._metadata) (a
         # dict is not hashable but we assume it is immutable in
         # practice)
-        hashdata = (hash(self._integrand),
-                    self._integral_type,
-                    hash(self._ufl_domain),
-                    self._subdomain_id,
-                    id_or_none(self._subdomain_data))
+        hashdata = (
+            hash(self._integrand),
+            self._integral_type,
+            hash(self._ufl_domain),
+            self._subdomain_id,
+            id_or_none(self._subdomain_data),
+        )
         return hash(hashdata)
diff --git a/ufl/mathfunctions.py b/ufl/mathfunctions.py
index 704304d6c..4c2d87996 100644
--- a/ufl/mathfunctions.py
+++ b/ufl/mathfunctions.py
@@ -13,8 +13,16 @@
 import numbers
 import warnings
 
-from ufl.constantvalue import (ComplexValue, ConstantValue, FloatValue, IntValue, RealValue, Zero, as_ufl,
-                               is_true_ufl_scalar)
+from ufl.constantvalue import (
+    ComplexValue,
+    ConstantValue,
+    FloatValue,
+    IntValue,
+    RealValue,
+    Zero,
+    as_ufl,
+    is_true_ufl_scalar,
+)
 from ufl.core.operator import Operator
 from ufl.core.ufl_type import ufl_type
 
@@ -42,6 +50,7 @@
 
 # --- Function representations ---
 
+
 @ufl_type(is_abstract=True, is_scalar=True, num_ops=1)
 class MathFunction(Operator):
     """Base class for all unary scalar math functions."""
@@ -65,7 +74,9 @@ def evaluate(self, x, mapping, component, index_values):
             else:
                 res = getattr(cmath, self._name)(a)
         except ValueError:
-            warnings.warn('Value error in evaluation of function %s with argument %s.' % (self._name, a))
+            warnings.warn(
+                "Value error in evaluation of function %s with argument %s." % (self._name, a)
+            )
             raise
         return res
 
@@ -344,9 +355,11 @@ def evaluate(self, x, mapping, component, index_values):
         try:
             res = math.atan2(a, b)
         except TypeError:
-            raise ValueError('Atan2 does not support complex numbers.')
+            raise ValueError("Atan2 does not support complex numbers.")
         except ValueError:
-            warnings.warn('Value error in evaluation of function atan2 with arguments %s, %s.' % (a, b))
+            warnings.warn(
+                "Value error in evaluation of function atan2 with arguments %s, %s." % (a, b)
+            )
             raise
         return res
 
@@ -383,7 +396,7 @@ def evaluate(self, x, mapping, component, index_values):
 class BesselFunction(Operator):
     """Base class for all bessel functions."""
 
-    __slots__ = ("_name")
+    __slots__ = "_name"
 
     def __init__(self, name, nu, argument):
         """Initialise."""
@@ -410,22 +423,22 @@ def evaluate(self, x, mapping, component, index_values):
         try:
             import scipy.special
         except ImportError:
-            raise ValueError("You must have scipy installed to evaluate bessel functions in python.")
+            raise ValueError(
+                "You must have scipy installed to evaluate bessel functions in python."
+            )
         name = self._name[-1]
         if isinstance(self.ufl_operands[0], IntValue):
             nu = int(self.ufl_operands[0])
-            functype = 'n' if name != 'i' else 'v'
+            functype = "n" if name != "i" else "v"
         else:
-            nu = self.ufl_operands[0].evaluate(x, mapping, component,
-                                               index_values)
-            functype = 'v'
+            nu = self.ufl_operands[0].evaluate(x, mapping, component, index_values)
+            functype = "v"
         func = getattr(scipy.special, name + functype)
         return func(nu, a)
 
     def __str__(self):
         """Format as a string."""
-        return "%s(%s, %s)" % (self._name, self.ufl_operands[0],
-                               self.ufl_operands[1])
+        return "%s(%s, %s)" % (self._name, self.ufl_operands[0], self.ufl_operands[1])
 
 
 @ufl_type()
diff --git a/ufl/matrix.py b/ufl/matrix.py
index 7fb1f5c07..039d70e23 100644
--- a/ufl/matrix.py
+++ b/ufl/matrix.py
@@ -30,12 +30,12 @@ class Matrix(BaseForm, Counted):
         "_ufl_shape",
         "_arguments",
         "_coefficients",
-        "_domains")
+        "_domains",
+    )
 
     def __getnewargs__(self):
         """Get new args."""
-        return (self._ufl_function_spaces[0], self._ufl_function_spaces[1],
-                self._count)
+        return (self._ufl_function_spaces[0], self._ufl_function_spaces[1], self._count)
 
     def __init__(self, row_space, column_space, count=None):
         """Initialise."""
@@ -53,7 +53,10 @@ def __init__(self, row_space, column_space, count=None):
         self.ufl_operands = ()
         self._domains = None
         self._hash = None
-        self._repr = f"Matrix({self._ufl_function_spaces[0]!r}, {self._ufl_function_spaces[1]!r}, {self._count!r})"
+        self._repr = (
+            f"Matrix({self._ufl_function_spaces[0]!r} "
+            f"{self._ufl_function_spaces[1]!r}, {self._count!r})"
+        )
 
     def ufl_function_spaces(self):
         """Get the tuple of function spaces of this coefficient."""
@@ -61,8 +64,10 @@ def ufl_function_spaces(self):
 
     def _analyze_form_arguments(self):
         """Define arguments of a matrix when considered as a form."""
-        self._arguments = (Argument(self._ufl_function_spaces[0], 0),
-                           Argument(self._ufl_function_spaces[1], 1))
+        self._arguments = (
+            Argument(self._ufl_function_spaces[0], 0),
+            Argument(self._ufl_function_spaces[1], 1),
+        )
         self._coefficients = ()
 
     def _analyze_domains(self):
@@ -96,4 +101,6 @@ def equals(self, other):
             return False
         if self is other:
             return True
-        return self._count == other._count and self._ufl_function_spaces == other._ufl_function_spaces
+        return (
+            self._count == other._count and self._ufl_function_spaces == other._ufl_function_spaces
+        )
diff --git a/ufl/measure.py b/ufl/measure.py
index 97d719501..08f1fa803 100644
--- a/ufl/measure.py
+++ b/ufl/measure.py
@@ -29,20 +29,22 @@
 _integral_types = [
     # === Integration over full topological dimension:
     ("cell", "dx"),  # Over cells of a mesh
-
     # === Integration over topological dimension - 1:
     ("exterior_facet", "ds"),  # Over one-sided exterior facets of a mesh
     ("interior_facet", "dS"),  # Over two-sided facets between pairs of adjacent cells of a mesh
-
     # === Integration over topological dimension 0
     ("vertex", "dP"),  # Over vertices of a mesh
-
     # === Integration over custom domains
     ("custom", "dc"),  # Over custom user-defined domains (run-time quadrature points)
     ("cutcell", "dC"),  # Over a cell with some part cut away (run-time quadrature points)
-    ("interface", "dI"),  # Over a facet fragment overlapping with two or more cells (run-time quadrature points)
-    ("overlap", "dO"),  # Over a cell fragment overlapping with two or more cells (run-time quadrature points)
-
+    (
+        "interface",
+        "dI",
+    ),  # Over a facet fragment overlapping with two or more cells (run-time quadrature points)
+    (
+        "overlap",
+        "dO",
+    ),  # Over a cell fragment overlapping with two or more cells (run-time quadrature points)
     # === Firedrake specifics:
     ("exterior_facet_bottom", "ds_b"),  # Over bottom facets on extruded mesh
     ("exterior_facet_top", "ds_t"),  # Over top facets on extruded mesh
@@ -73,8 +75,7 @@ def register_integral_type(integral_type, measure_name):
 def as_integral_type(integral_type):
     """Map short name to long name and require a valid one."""
     integral_type = integral_type.replace(" ", "_")
-    integral_type = measure_name_to_integral_type.get(integral_type,
-                                                      integral_type)
+    integral_type = measure_name_to_integral_type.get(integral_type, integral_type)
     if integral_type not in integral_type_to_measure_name:
         raise ValueError("Invalid integral_type.")
     return integral_type
@@ -100,12 +101,14 @@ class Measure(object):
 
     __slots__ = ("_integral_type", "_domain", "_subdomain_id", "_metadata", "_subdomain_data")
 
-    def __init__(self,
-                 integral_type,  # "dx" etc
-                 domain=None,
-                 subdomain_id="everywhere",
-                 metadata=None,
-                 subdomain_data=None):
+    def __init__(
+        self,
+        integral_type,  # "dx" etc
+        domain=None,
+        subdomain_id="everywhere",
+        metadata=None,
+        subdomain_data=None,
+    ):
         """Initialise.
 
         Args:
@@ -177,12 +180,9 @@ def metadata(self):
         """
         return self._metadata
 
-    def reconstruct(self,
-                    integral_type=None,
-                    subdomain_id=None,
-                    domain=None,
-                    metadata=None,
-                    subdomain_data=None):
+    def reconstruct(
+        self, integral_type=None, subdomain_id=None, domain=None, metadata=None, subdomain_data=None
+    ):
         """Construct a new Measure object with some properties replaced with new values.
 
         Example:
@@ -202,9 +202,13 @@ def reconstruct(self,
             metadata = self.metadata()
         if subdomain_data is None:
             subdomain_data = self.subdomain_data()
-        return Measure(self.integral_type(),
-                       domain=domain, subdomain_id=subdomain_id,
-                       metadata=metadata, subdomain_data=subdomain_data)
+        return Measure(
+            self.integral_type(),
+            domain=domain,
+            subdomain_id=subdomain_id,
+            metadata=metadata,
+            subdomain_data=subdomain_data,
+        )
 
     def subdomain_data(self):
         """Return the integral subdomain_data.
@@ -218,12 +222,18 @@ def subdomain_data(self):
     # Note: Must keep the order of the first two arguments here
     # (subdomain_id, metadata) for backwards compatibility, because
     # some tutorials write e.g. dx(0, {...}) to set metadata.
-    def __call__(self, subdomain_id=None, metadata=None, domain=None,
-                 subdomain_data=None, degree=None, scheme=None):
+    def __call__(
+        self,
+        subdomain_id=None,
+        metadata=None,
+        domain=None,
+        subdomain_data=None,
+        degree=None,
+        scheme=None,
+    ):
         """Reconfigure measure with new domain specification or metadata."""
         # Let syntax dx() mean integral over everywhere
-        all_args = (subdomain_id, metadata, domain, subdomain_data,
-                    degree, scheme)
+        all_args = (subdomain_id, metadata, domain, subdomain_data, degree, scheme)
         if all(arg is None for arg in all_args):
             return self.reconstruct(subdomain_id="everywhere")
 
@@ -234,7 +244,9 @@ def __call__(self, subdomain_id=None, metadata=None, domain=None,
             isinstance(subdomain_id, AbstractDomain) or hasattr(subdomain_id, "ufl_domain")
         ):
             if domain is not None:
-                raise ValueError("Ambiguous: setting domain both as keyword argument and first argument.")
+                raise ValueError(
+                    "Ambiguous: setting domain both as keyword argument and first argument."
+                )
             subdomain_id, domain = "everywhere", subdomain_id
 
         # If degree or scheme is set, inject into metadata. This is a
@@ -250,9 +262,12 @@ def __call__(self, subdomain_id=None, metadata=None, domain=None,
         # If we get any keywords, use them to reconstruct Measure.
         # Note that if only one argument is given, it is the
         # subdomain_id, e.g. dx(3) == dx(subdomain_id=3)
-        return self.reconstruct(subdomain_id=subdomain_id, domain=domain,
-                                metadata=metadata,
-                                subdomain_data=subdomain_data)
+        return self.reconstruct(
+            subdomain_id=subdomain_id,
+            domain=domain,
+            metadata=metadata,
+            subdomain_data=subdomain_data,
+        )
 
     def __str__(self):
         """Format as a string."""
@@ -268,7 +283,7 @@ def __str__(self):
         if self._subdomain_data is not None:
             args.append("subdomain_data=%s" % (self._subdomain_data,))
 
-        return "%s(%s)" % (name, ', '.join(args))
+        return "%s(%s)" % (name, ", ".join(args))
 
     def __repr__(self):
         """Return a repr string for this Measure."""
@@ -284,17 +299,19 @@ def __repr__(self):
         if self._subdomain_data is not None:
             args.append("subdomain_data=%s" % repr(self._subdomain_data))
 
-        r = "%s(%s)" % (type(self).__name__, ', '.join(args))
+        r = "%s(%s)" % (type(self).__name__, ", ".join(args))
         return r
 
     def __hash__(self):
         """Return a hash value for this Measure."""
         metadata_hashdata = tuple(sorted((k, id(v)) for k, v in list(self._metadata.items())))
-        hashdata = (self._integral_type,
-                    self._subdomain_id,
-                    hash(self._domain),
-                    metadata_hashdata,
-                    id_or_none(self._subdomain_data))
+        hashdata = (
+            self._integral_type,
+            self._subdomain_id,
+            hash(self._domain),
+            metadata_hashdata,
+            id_or_none(self._subdomain_data),
+        )
         return hash(hashdata)
 
     def __eq__(self, other):
@@ -302,10 +319,14 @@ def __eq__(self, other):
         sorted_metadata = sorted((k, id(v)) for k, v in list(self._metadata.items()))
         sorted_other_metadata = sorted((k, id(v)) for k, v in list(other._metadata.items()))
 
-        return (isinstance(other, Measure) and self._integral_type == other._integral_type and  # noqa: W504
-                self._subdomain_id == other._subdomain_id and self._domain == other._domain and  # noqa: W504
-                id_or_none(self._subdomain_data) == id_or_none(other._subdomain_data) and  # noqa: W504
-                sorted_metadata == sorted_other_metadata)
+        return (
+            isinstance(other, Measure)
+            and self._integral_type == other._integral_type
+            and self._subdomain_id == other._subdomain_id
+            and self._domain == other._domain
+            and id_or_none(self._subdomain_data) == id_or_none(other._subdomain_data)
+            and sorted_metadata == sorted_other_metadata
+        )
 
     def __add__(self, other):
         """Add two measures (self+other).
@@ -361,18 +382,33 @@ def __rmul__(self, integrand):
             raise ValueError(
                 "Can only integrate scalar expressions. The integrand is a "
                 f"tensor expression with value shape {integrand.ufl_shape} and "
-                f"free indices with labels {integrand.ufl_free_indices}.")
+                f"free indices with labels {integrand.ufl_free_indices}."
+            )
 
         # If we have a tuple of domain ids build the integrals one by
         # one and construct as a Form in one go.
         subdomain_id = self.subdomain_id()
         if isinstance(subdomain_id, tuple):
-            return Form(list(chain(*((integrand * self.reconstruct(subdomain_id=d)).integrals()
-                                     for d in subdomain_id))))
+            return Form(
+                list(
+                    chain(
+                        *(
+                            (integrand * self.reconstruct(subdomain_id=d)).integrals()
+                            for d in subdomain_id
+                        )
+                    )
+                )
+            )
 
         # Check that we have an integer subdomain or a string
         # ("everywhere" or "otherwise", any more?)
-        if not isinstance(subdomain_id, (str, numbers.Integral,)):
+        if not isinstance(
+            subdomain_id,
+            (
+                str,
+                numbers.Integral,
+            ),
+        ):
             raise ValueError("Expecting integer or string domain id.")
 
         # If we don't have an integration domain, try to find one in
@@ -381,19 +417,23 @@ def __rmul__(self, integrand):
         if domain is None:
             domains = extract_domains(integrand)
             if len(domains) == 1:
-                domain, = domains
+                (domain,) = domains
             elif len(domains) == 0:
                 raise ValueError("This integral is missing an integration domain.")
             else:
-                raise ValueError("Multiple domains found, making the choice of integration domain ambiguous.")
+                raise ValueError(
+                    "Multiple domains found, making the choice of integration domain ambiguous."
+                )
 
         # Otherwise create and return a one-integral form
-        integral = Integral(integrand=integrand,
-                            integral_type=self.integral_type(),
-                            domain=domain,
-                            subdomain_id=subdomain_id,
-                            metadata=self.metadata(),
-                            subdomain_data=self.subdomain_data())
+        integral = Integral(
+            integrand=integrand,
+            integral_type=self.integral_type(),
+            domain=domain,
+            subdomain_id=subdomain_id,
+            metadata=self.metadata(),
+            subdomain_data=self.subdomain_data(),
+        )
         return Form([integral])
 
 
diff --git a/ufl/operators.py b/ufl/operators.py
index 0394e65eb..2ca1158f5 100644
--- a/ufl/operators.py
+++ b/ufl/operators.py
@@ -22,17 +22,57 @@
 from ufl.averaging import CellAvg, FacetAvg
 from ufl.checks import is_cellwise_constant
 from ufl.coefficient import Coefficient
-from ufl.conditional import EQ, NE, AndCondition, Conditional, MaxValue, MinValue, NotCondition, OrCondition
+from ufl.conditional import (
+    EQ,
+    NE,
+    AndCondition,
+    Conditional,
+    MaxValue,
+    MinValue,
+    NotCondition,
+    OrCondition,
+)
 from ufl.constantvalue import ComplexValue, RealValue, Zero, as_ufl
 from ufl.differentiation import Curl, Div, Grad, NablaDiv, NablaGrad, VariableDerivative
 from ufl.domain import extract_domains
 from ufl.form import Form
 from ufl.geometry import FacetNormal, SpatialCoordinate
 from ufl.indexed import Indexed
-from ufl.mathfunctions import (Acos, Asin, Atan, Atan2, BesselI, BesselJ, BesselK, BesselY, Cos, Cosh, Erf, Exp, Ln,
-                               Sin, Sinh, Sqrt, Tan, Tanh)
-from ufl.tensoralgebra import (Cofactor, Cross, Determinant, Deviatoric, Dot, Inner, Inverse, Outer, Perp, Skew, Sym,
-                               Trace, Transposed)
+from ufl.mathfunctions import (
+    Acos,
+    Asin,
+    Atan,
+    Atan2,
+    BesselI,
+    BesselJ,
+    BesselK,
+    BesselY,
+    Cos,
+    Cosh,
+    Erf,
+    Exp,
+    Ln,
+    Sin,
+    Sinh,
+    Sqrt,
+    Tan,
+    Tanh,
+)
+from ufl.tensoralgebra import (
+    Cofactor,
+    Cross,
+    Determinant,
+    Deviatoric,
+    Dot,
+    Inner,
+    Inverse,
+    Outer,
+    Perp,
+    Skew,
+    Sym,
+    Trace,
+    Transposed,
+)
 from ufl.tensors import ListTensor, as_matrix, as_tensor, as_vector
 from ufl.variable import Variable
 
@@ -53,13 +93,15 @@ def shape(f):
 
 # --- Complex operators ---
 
+
 def conj(f):
     """The complex conjugate of f."""
     f = as_ufl(f)
     return Conj(f)
 
 
-# Alias because both conj and conjugate are in numpy and we wish to be consistent.
+# Alias because both conj and conjugate are in numpy and we wish to be
+# consistent.
 conjugate = conj
 
 
@@ -77,6 +119,7 @@ def imag(f):
 
 # --- Elementwise tensor operators ---
 
+
 def elem_op_items(op_ind, indices, *args):
     """Elem op items."""
     sh = args[0].ufl_shape
@@ -93,17 +136,22 @@ def extind(ii):
 
 
 def elem_op(op, *args):
-    """Take the elementwise application of operator op on scalar values from one or more tensor arguments."""
+    """Apply element-wise operations.
+
+    Take the element-wise application of operator op on scalar values
+    from one or more tensor arguments.
+    """
     args = [as_ufl(arg) for arg in args]
     sh = args[0].ufl_shape
     if not all(sh == x.ufl_shape for x in args):
-        raise ValueError("Cannot take elementwise operation with different shapes.")
+        raise ValueError("Cannot take element-wise operation with different shapes.")
 
     if sh == ():
         return op(*args)
 
     def op_ind(ind, *args):
         return op(*[x[ind] for x in args])
+
     return as_tensor(elem_op_items(op_ind, (), *args))
 
 
@@ -124,6 +172,7 @@ def elem_pow(A, B):
 
 # --- Tensor operators ---
 
+
 def transpose(A):
     """Take the transposed of tensor A."""
     A = as_ufl(A)
@@ -223,7 +272,10 @@ def tr(A):
 
 
 def diag(A):
-    """Take the diagonal part of rank 2 tensor A or make a diagonal rank 2 tensor from a rank 1 tensor.
+    """Diagonal ranl-2 tensor.
+
+    Take the diagonal part of rank 2 tensor A or make a diagonal rank 2
+    tensor from a rank 1 tensor.
 
     Always returns a rank 2 tensor. See also diag_vector.
     """
@@ -232,7 +284,7 @@ def diag(A):
     # Get and check dimensions
     r = len(A.ufl_shape)
     if r == 1:
-        n, = A.ufl_shape
+        (n,) = A.ufl_shape
     elif r == 2:
         m, n = A.ufl_shape
         if m != n:
@@ -287,6 +339,7 @@ def sym(A):
 
 # --- Differential operators
 
+
 def Dx(f, *i):
     """Take the partial derivative of f with respect to spatial variable number i.
 
@@ -315,6 +368,7 @@ def diff(f, v):
     # Apply to integrands
     if isinstance(f, Form):
         from ufl.algorithms.map_integrands import map_integrands
+
         return map_integrands(lambda e: diff(e, v), f)
 
     # Apply to expression
@@ -400,21 +454,24 @@ def curl(f):
 
 # --- DG operators ---
 
+
 def jump(v, n=None):
     """Take the jump of v across a facet."""
     v = as_ufl(v)
     is_constant = len(extract_domains(v)) > 0
     if is_constant:
         if n is None:
-            return v('+') - v('-')
+            return v("+") - v("-")
         r = len(v.ufl_shape)
         if r == 0:
-            return v('+') * n('+') + v('-') * n('-')
+            return v("+") * n("+") + v("-") * n("-")
         else:
-            return dot(v('+'), n('+')) + dot(v('-'), n('-'))
+            return dot(v("+"), n("+")) + dot(v("-"), n("-"))
     else:
-        warnings.warn("Returning zero from jump of expression without a domain. "
-                      "This may be erroneous if a dolfin.Expression is involved.")
+        warnings.warn(
+            "Returning zero from jump of expression without a domain. "
+            "This may be erroneous if a dolfin.Expression is involved."
+        )
         # FIXME: Is this right? If v has no domain, it doesn't depend
         # on anything spatially variable or any form arguments, and
         # thus the jump is zero. In other words, I'm assuming that "v
@@ -427,7 +484,7 @@ def jump(v, n=None):
 def avg(v):
     """Take the average of v across a facet."""
     v = as_ufl(v)
-    return 0.5 * (v('+') + v('-'))
+    return 0.5 * (v("+") + v("-"))
 
 
 def cell_avg(f):
@@ -442,6 +499,7 @@ def facet_avg(f):
 
 # --- Other operators ---
 
+
 def variable(e):
     """Define a variable representing the given expression.
 
@@ -453,6 +511,7 @@ def variable(e):
 
 # --- Conditional expressions ---
 
+
 def conditional(condition, true_value, false_value):
     """A conditional expression.
 
@@ -532,6 +591,7 @@ def min_value(x, y):
 
 # --- Math functions ---
 
+
 def _mathfunction(f, cls):
     """A mat function."""
     f = as_ufl(f)
@@ -608,7 +668,7 @@ def atan2(f1, f2):
     f1 = as_ufl(f1)
     f2 = as_ufl(f2)
     if isinstance(f1, (ComplexValue, complex)) or isinstance(f2, (ComplexValue, complex)):
-        raise TypeError('atan2 is incompatible with complex numbers.')
+        raise TypeError("atan2 is incompatible with complex numbers.")
     r = Atan2(f1, f2)
     if isinstance(r, (RealValue, Zero, int, float)):
         return float(r)
@@ -652,6 +712,7 @@ def bessel_K(nu, f):
 
 # --- Special function for exterior_derivative
 
+
 def exterior_derivative(f):
     """Take the exterior derivative of f.
 
diff --git a/ufl/precedence.py b/ufl/precedence.py
index 0aea48b20..3b404dbda 100644
--- a/ufl/precedence.py
+++ b/ufl/precedence.py
@@ -16,7 +16,7 @@ def parstr(child, parent, pre="(", post=")", format=str):
     # Execute when needed instead of on import, which leads to all
     # kinds of circular trouble.  Fixing this could be an optimization
     # of str(expr) though.
-    if not hasattr(parent, '_precedence'):
+    if not hasattr(parent, "_precedence"):
         assign_precedences(build_precedence_list())
 
     # We want child to be evaluated fully first, and if the parent has
@@ -41,8 +41,19 @@ def parstr(child, parent, pre="(", post=")", format=str):
 
 def build_precedence_list():
     """Build precedence list."""
-    from ufl.classes import (Abs, BesselFunction, Division, Indexed, IndexSum, MathFunction, Operator, Power, Product,
-                             Sum, Terminal)
+    from ufl.classes import (
+        Abs,
+        BesselFunction,
+        Division,
+        Indexed,
+        IndexSum,
+        MathFunction,
+        Operator,
+        Power,
+        Product,
+        Sum,
+        Terminal,
+    )
 
     # TODO: Fill in other types...
     # Power <= Transposed
@@ -57,7 +68,12 @@ def build_precedence_list():
     # stronger than +, but weaker than product
     precedence_list.append((IndexSum,))
 
-    precedence_list.append((Product, Division,))
+    precedence_list.append(
+        (
+            Product,
+            Division,
+        )
+    )
 
     # NB! Depends on language!
     precedence_list.append((Power, MathFunction, BesselFunction, Abs))
@@ -75,6 +91,7 @@ def build_precedence_mapping(precedence_list):
     Utility function used by some external code.
     """
     from ufl.classes import Expr, abstract_classes, all_ufl_classes
+
     pm = {}
     missing = set()
     # Assign integer values for each precedence level
@@ -103,4 +120,7 @@ def assign_precedences(precedence_list):
     for c, p in sorted(pm.items(), key=lambda x: x[0].__name__):
         c._precedence = p
     if missing:
-        warnings.warn("Missing precedence levels for classes:\n" + "\n".join(f"  {c}" for c in sorted(missing)))
+        warnings.warn(
+            "Missing precedence levels for classes:\n"
+            + "\n".join(f"  {c}" for c in sorted(missing))
+        )
diff --git a/ufl/protocols.py b/ufl/protocols.py
index df8041473..ad7dbb7f7 100644
--- a/ufl/protocols.py
+++ b/ufl/protocols.py
@@ -15,7 +15,7 @@ def id_or_none(obj):
     """
     if obj is None:
         return None
-    elif hasattr(obj, 'ufl_id'):
+    elif hasattr(obj, "ufl_id"):
         return obj.ufl_id()
     else:
         return id(obj)
diff --git a/ufl/pullback.py b/ufl/pullback.py
index cbc6b53db..d32fc3861 100644
--- a/ufl/pullback.py
+++ b/ufl/pullback.py
@@ -22,14 +22,26 @@
 if TYPE_CHECKING:
     from ufl.finiteelement import AbstractFiniteElement as _AbstractFiniteElement
 
-__all_classes__ = ["NonStandardPullbackException", "AbstractPullback", "IdentityPullback",
-                   "ContravariantPiola", "CovariantPiola", "L2Piola", "DoubleContravariantPiola",
-                   "DoubleCovariantPiola", "MixedPullback", "SymmetricPullback",
-                   "PhysicalPullback", "CustomPullback", "UndefinedPullback"]
+__all_classes__ = [
+    "NonStandardPullbackException",
+    "AbstractPullback",
+    "IdentityPullback",
+    "ContravariantPiola",
+    "CovariantPiola",
+    "L2Piola",
+    "DoubleContravariantPiola",
+    "DoubleCovariantPiola",
+    "MixedPullback",
+    "SymmetricPullback",
+    "PhysicalPullback",
+    "CustomPullback",
+    "UndefinedPullback",
+]
 
 
 class NonStandardPullbackException(BaseException):
     """Exception to raise if a map is non-standard."""
+
     pass
 
 
@@ -144,7 +156,7 @@ def physical_value_shape(self, element, domain) -> typing.Tuple[int, ...]:
             The value shape when the pull back is applied to the given element
         """
         gdim = domain.geometric_dimension()
-        return (gdim, ) + element.reference_value_shape[1:]
+        return (gdim,) + element.reference_value_shape[1:]
 
 
 class CovariantPiola(AbstractPullback):
@@ -187,7 +199,7 @@ def physical_value_shape(self, element, domain) -> typing.Tuple[int, ...]:
             The value shape when the pull back is applied to the given element
         """
         gdim = domain.geometric_dimension()
-        return (gdim, ) + element.reference_value_shape[1:]
+        return (gdim,) + element.reference_value_shape[1:]
 
 
 class L2Piola(AbstractPullback):
@@ -257,7 +269,7 @@ def apply(self, expr):
         # Apply transform "row-wise" to TensorElement(PiolaMapped, ...)
         *k, i, j, m, n = indices(len(expr.ufl_shape) + 2)
         kmn = (*k, m, n)
-        return as_tensor((1.0 / detJ)**2 * J[i, m] * expr[kmn] * J[j, n], (*k, i, j))
+        return as_tensor((1.0 / detJ) ** 2 * J[i, m] * expr[kmn] * J[j, n], (*k, i, j))
 
     def physical_value_shape(self, element, domain) -> typing.Tuple[int, ...]:
         """Get the physical value shape when this pull back is applied to an element on a domain.
@@ -351,9 +363,11 @@ def apply(self, expr):
         offset = 0
         # For each unique piece in reference space, apply the appropriate pullback
         for subelem in self._element.sub_elements:
-            rsub = as_tensor(np.asarray(
-                rflat[offset: offset + subelem.reference_value_size]
-            ).reshape(subelem.reference_value_shape))
+            rsub = as_tensor(
+                np.asarray(rflat[offset : offset + subelem.reference_value_size]).reshape(
+                    subelem.reference_value_shape
+                )
+            )
             rmapped = subelem.pullback.apply(rsub)
             # Flatten into the pulled back expression for the whole thing
             g_components.extend([rmapped[idx] for idx in np.ndindex(rmapped.ufl_shape)])
@@ -361,8 +375,10 @@ def apply(self, expr):
         # And reshape appropriately
         f = as_tensor(np.asarray(g_components).reshape(space.value_shape))
         if f.ufl_shape != space.value_shape:
-            raise ValueError("Expecting pulled back expression with shape "
-                             f"'{space.value_shape}', got '{f.ufl_shape}'")
+            raise ValueError(
+                "Expecting pulled back expression with shape "
+                f"'{space.value_shape}', got '{f.ufl_shape}'"
+            )
         return f
 
     def physical_value_shape(self, element, domain) -> typing.Tuple[int, ...]:
@@ -377,18 +393,21 @@ def physical_value_shape(self, element, domain) -> typing.Tuple[int, ...]:
         """
         assert element == self._element
         dim = sum(FunctionSpace(domain, e).value_size for e in self._element.sub_elements)
-        return (dim, )
+        return (dim,)
 
 
 class SymmetricPullback(AbstractPullback):
     """Pull back for an element with symmetry."""
 
-    def __init__(self, element: _AbstractFiniteElement, symmetry: typing.Dict[typing.tuple[int, ...], int]):
+    def __init__(
+        self, element: _AbstractFiniteElement, symmetry: typing.Dict[typing.tuple[int, ...], int]
+    ):
         """Initalise.
 
         Args:
             element: The element
-            symmetry: A dictionary mapping from the component in physical space to the local component
+            symmetry: A dictionary mapping from the component in
+                physical space to the local component
         """
         self._element = element
         self._symmetry = symmetry
@@ -427,17 +446,21 @@ def apply(self, expr):
         for component in np.ndindex(self._block_shape):
             i = self._symmetry[component]
             subelem = self._element.sub_elements[i]
-            rsub = as_tensor(np.asarray(
-                rflat[offsets[i]:offsets[i+1]]
-            ).reshape(subelem.reference_value_shape))
+            rsub = as_tensor(
+                np.asarray(rflat[offsets[i] : offsets[i + 1]]).reshape(
+                    subelem.reference_value_shape
+                )
+            )
             rmapped = subelem.pullback.apply(rsub)
             # Flatten into the pulled back expression for the whole thing
             g_components.extend([rmapped[idx] for idx in np.ndindex(rmapped.ufl_shape)])
         # And reshape appropriately
         f = as_tensor(np.asarray(g_components).reshape(space.value_shape))
         if f.ufl_shape != space.value_shape:
-            raise ValueError(f"Expecting pulled back expression with shape "
-                             f"'{space.value_shape}', got '{f.ufl_shape}'")
+            raise ValueError(
+                f"Expecting pulled back expression with shape "
+                f"'{space.value_shape}', got '{f.ufl_shape}'"
+            )
         return f
 
     def physical_value_shape(self, element, domain) -> typing.Tuple[int, ...]:
diff --git a/ufl/referencevalue.py b/ufl/referencevalue.py
index 5a4c5bb11..5dd82f4c3 100644
--- a/ufl/referencevalue.py
+++ b/ufl/referencevalue.py
@@ -10,10 +10,7 @@
 from ufl.core.ufl_type import ufl_type
 
 
-@ufl_type(num_ops=1,
-          is_index_free=True,
-          is_terminal_modifier=True,
-          is_in_reference_frame=True)
+@ufl_type(num_ops=1, is_index_free=True, is_terminal_modifier=True, is_in_reference_frame=True)
 class ReferenceValue(Operator):
     """Representation of the reference cell value of a form argument."""
 
diff --git a/ufl/restriction.py b/ufl/restriction.py
index 2871cd53f..430fefa41 100644
--- a/ufl/restriction.py
+++ b/ufl/restriction.py
@@ -12,11 +12,13 @@
 # --- Restriction operators ---
 
 
-@ufl_type(is_abstract=True,
-          num_ops=1,
-          inherit_shape_from_operand=0,
-          inherit_indices_from_operand=0,
-          is_restriction=True)
+@ufl_type(
+    is_abstract=True,
+    num_ops=1,
+    inherit_shape_from_operand=0,
+    inherit_indices_from_operand=0,
+    is_restriction=True,
+)
 class Restricted(Operator):
     """Restriction."""
 
@@ -34,8 +36,7 @@ def side(self):
 
     def evaluate(self, x, mapping, component, index_values):
         """Evaluate."""
-        return self.ufl_operands[0].evaluate(x, mapping, component,
-                                             index_values)
+        return self.ufl_operands[0].evaluate(x, mapping, component, index_values)
 
     def __str__(self):
         """Format as a string."""
diff --git a/ufl/sobolevspace.py b/ufl/sobolevspace.py
index 9500ae422..ebff0f24d 100644
--- a/ufl/sobolevspace.py
+++ b/ufl/sobolevspace.py
@@ -25,8 +25,9 @@
 class SobolevSpace(object):
     """Symbolic representation of a Sobolev space.
 
-    This implements a subset of the methods of a Python set so that finite elements and
-    other Sobolev spaces can be tested for inclusion.
+    This implements a subset of the methods of a Python set so that
+    finite elements and other Sobolev spaces can be tested for
+    inclusion.
     """
 
     def __init__(self, name, parents=None):
@@ -52,7 +53,7 @@ def __init__(self, name, parents=None):
             "HCurl": 0,
             "HEin": 0,
             "HDivDiv": 0,
-            "DirectionalH": 0
+            "DirectionalH": 0,
         }[self.name]
 
     def __str__(self):
@@ -65,6 +66,7 @@ def __repr__(self):
 
     def __eq__(self, other):
         """Check equality."""
+        print("XXXXX")
         return isinstance(other, SobolevSpace) and self.name == other.name
 
     def __ne__(self, other):
@@ -82,11 +84,11 @@ def __getitem__(self, spatial_index):
     def __contains__(self, other):
         """Implement `fe in s` where `fe` is a FiniteElement and `s` is a SobolevSpace."""
         if isinstance(other, SobolevSpace):
-            raise TypeError("Unable to test for inclusion of a "
-                            "SobolevSpace in another SobolevSpace. "
-                            "Did you mean to use <= instead?")
-        return (other.sobolev_space == self or
-                self in other.sobolev_space.parents)
+            raise TypeError(
+                "Unable to test for inclusion of a SobolevSpace in another SobolevSpace. "
+                "Did you mean to use <= instead?"
+            )
+        return other.sobolev_space == self or self in other.sobolev_space.parents
 
     def __lt__(self, other):
         """In common with intrinsic Python sets, < indicates "is a proper subset of"."""
@@ -98,7 +100,7 @@ class DirectionalSobolevSpace(SobolevSpace):
     """Directional Sobolev space.
 
     Symbolic representation of a Sobolev space with varying smoothness
-    in differerent spatial directions.
+    in different spatial directions.
     """
 
     def __init__(self, orders):
@@ -110,8 +112,8 @@ def __init__(self, orders):
                 smoothness requirement is enforced.
         """
         assert all(
-            isinstance(x, int) or isinf(x)
-            for x in orders), "Order must be an integer or infinity."
+            isinstance(x, int) or isinf(x) for x in orders
+        ), "Order must be an integer or infinity."
         name = "DirectionalH"
         parents = [L2]
         super(DirectionalSobolevSpace, self).__init__(name, parents)
@@ -126,17 +128,23 @@ def __getitem__(self, spatial_index):
         return spaces[self._orders[spatial_index]]
 
     def __contains__(self, other):
-        """Implement `fe in s` where `fe` is a FiniteElement and `s` is a DirectionalSobolevSpace."""
+        """Check if one space is contained in another.
+
+        Implement `fe in s` where `fe` is a FiniteElement and `s` is a
+        DirectionalSobolevSpace.
+        """
         if isinstance(other, SobolevSpace):
-            raise TypeError("Unable to test for inclusion of a "
-                            "SobolevSpace in another SobolevSpace. "
-                            "Did you mean to use <= instead?")
-        return (other.sobolev_space == self or
-                all(self[i] in other.sobolev_space.parents
-                    for i in self._spatial_indices))
+            raise TypeError(
+                "Unable to test for inclusion of a SobolevSpace in another SobolevSpace. "
+                "Did you mean to use <= instead?"
+            )
+        return other.sobolev_space == self or all(
+            self[i] in other.sobolev_space.parents for i in self._spatial_indices
+        )
 
     def __eq__(self, other):
         """Check equality."""
+        print("FFFFFF")
         if isinstance(other, DirectionalSobolevSpace):
             return self._orders == other._orders
         return all(self[i] == other for i in self._spatial_indices)
@@ -146,8 +154,7 @@ def __lt__(self, other):
         if isinstance(other, DirectionalSobolevSpace):
             if self._spatial_indices != other._spatial_indices:
                 return False
-            return any(self._orders[i] > other._orders[i]
-                       for i in self._spatial_indices)
+            return any(self._orders[i] > other._orders[i] for i in self._spatial_indices)
 
         if other in [HDiv, HCurl]:
             return all(self._orders[i] >= 1 for i in self._spatial_indices)
@@ -155,8 +162,7 @@ def __lt__(self, other):
             # Don't know how these spaces compare
             return NotImplementedError(f"Don't know how to compare with {other.name}")
         else:
-            return any(
-                self._orders[i] > other._order for i in self._spatial_indices)
+            return any(self._orders[i] > other._order for i in self._spatial_indices)
 
     def __str__(self):
         """Format as a string."""
diff --git a/ufl/sorting.py b/ufl/sorting.py
index 5efe2a44a..6b9324514 100644
--- a/ufl/sorting.py
+++ b/ufl/sorting.py
@@ -141,7 +141,7 @@ def cmp_expr(a, b):
             bops = b.ufl_operands
 
             # Sort by children in natural order
-            for (r, s) in zip(aops, bops):
+            for r, s in zip(aops, bops):
                 # Skip subtree if objects are the same
                 if r is s:
                     continue
diff --git a/ufl/split_functions.py b/ufl/split_functions.py
index 0931b74ae..a5c18da38 100644
--- a/ufl/split_functions.py
+++ b/ufl/split_functions.py
@@ -8,7 +8,6 @@
 # Modified by Anders Logg, 2008
 
 from ufl.functionspace import FunctionSpace
-
 from ufl.indexed import Indexed
 from ufl.permutation import compute_indices
 from ufl.tensors import ListTensor, as_matrix, as_vector
@@ -19,8 +18,8 @@
 def split(v):
     """Split a coefficient or argument.
 
-    If v is a Coefficient or Argument in a mixed space, returns
-    a tuple with the function components corresponding to the subelements.
+    If v is a Coefficient or Argument in a mixed space, returns a tuple
+    with the function components corresponding to the subelements.
     """
     domain = v.ufl_domain()
 
@@ -42,8 +41,8 @@ def split(v):
                 # Get innermost terminal here and its element
                 v = args[0]
                 # Get relevant range of v components
-                begin, = ops[0].ufl_operands[1]
-                end, = ops[-1].ufl_operands[1]
+                (begin,) = ops[0].ufl_operands[1]
+                (end,) = ops[-1].ufl_operands[1]
                 begin = int(begin)
                 end = int(end) + 1
             else:
@@ -58,7 +57,9 @@ def split(v):
         return (v,)
 
     if len(v.ufl_shape) != 1:
-        raise ValueError("Don't know how to split tensor valued mixed functions without flattened index space.")
+        raise ValueError(
+            "Don't know how to split tensor valued mixed functions without flattened index space."
+        )
 
     # Compute value size and set default range end
     value_size = v.ufl_function_space().value_size
@@ -88,26 +89,29 @@ def split(v):
         strides = shape_to_strides(shape)
         rank = len(shape)
         sub_size = product(shape)
-        subindices = [flatten_multiindex(c, strides)
-                      for c in compute_indices(shape)]
+        subindices = [flatten_multiindex(c, strides) for c in compute_indices(shape)]
         components = [v[k + offset] for k in subindices]
 
         # Shape components into same shape as subelement
         if rank == 0:
-            subv, = components
+            (subv,) = components
         elif rank <= 1:
             subv = as_vector(components)
         elif rank == 2:
-            subv = as_matrix([components[i * shape[1]: (i + 1) * shape[1]]
-                              for i in range(shape[0])])
+            subv = as_matrix(
+                [components[i * shape[1] : (i + 1) * shape[1]] for i in range(shape[0])]
+            )
         else:
-            raise ValueError(f"Don't know how to split functions with sub functions of rank {rank}.")
+            raise ValueError(
+                f"Don't know how to split functions with sub functions of rank {rank}."
+            )
 
         offset += sub_size
         sub_functions.append(subv)
 
     if end != offset:
         raise ValueError(
-            "Function splitting failed to extract components for whole intended range. Something is wrong.")
+            "Function splitting failed to extract components for whole intended range."
+        )
 
     return tuple(sub_functions)
diff --git a/ufl/tensoralgebra.py b/ufl/tensoralgebra.py
index 733b24388..4ec364191 100644
--- a/ufl/tensoralgebra.py
+++ b/ufl/tensoralgebra.py
@@ -41,6 +41,7 @@
 
 # --- Classes representing compound tensor algebra operations ---
 
+
 @ufl_type(is_abstract=True)
 class CompoundTensorOperator(Operator):
     """Compount tensor operator."""
@@ -51,6 +52,7 @@ def __init__(self, operands):
         """Initialise."""
         Operator.__init__(self, operands)
 
+
 # TODO: Use this and make Sum handle scalars only?
 #       This would simplify some algorithms. The only
 #       problem is we can't use + in many algorithms because
@@ -144,8 +146,10 @@ def ufl_shape(self):
 
     def __str__(self):
         """Format as a string."""
-        return "%s (X) %s" % (parstr(self.ufl_operands[0], self),
-                              parstr(self.ufl_operands[1], self))
+        return "%s (X) %s" % (
+            parstr(self.ufl_operands[0], self),
+            parstr(self.ufl_operands[1], self),
+        )
 
 
 @ufl_type(num_ops=2)
@@ -187,8 +191,7 @@ def __init__(self, a, b):
 
     def __str__(self):
         """Format as a string."""
-        return "%s : %s" % (parstr(self.ufl_operands[0], self),
-                            parstr(self.ufl_operands[1], self))
+        return "%s : %s" % (parstr(self.ufl_operands[0], self), parstr(self.ufl_operands[1], self))
 
 
 @ufl_type(num_ops=2)
@@ -202,13 +205,14 @@ def __new__(cls, a, b):
         ash = a.ufl_shape
         bsh = b.ufl_shape
         ar, br = len(ash), len(bsh)
-        scalar = (ar == 0 and br == 0)
+        scalar = ar == 0 and br == 0
 
         # Checks
         if not ((ar >= 1 and br >= 1) or scalar):
             raise ValueError(
                 "Dot product requires non-scalar arguments, "
-                f"got arguments with ranks {ar} and {br}.")
+                f"got arguments with ranks {ar} and {br}."
+            )
         if not (scalar or ash[-1] == bsh[0]):
             raise ValueError("Dimension mismatch in dot product.")
 
@@ -236,8 +240,7 @@ def ufl_shape(self):
 
     def __str__(self):
         """Format as a string."""
-        return "%s . %s" % (parstr(self.ufl_operands[0], self),
-                            parstr(self.ufl_operands[1], self))
+        return "%s . %s" % (parstr(self.ufl_operands[0], self), parstr(self.ufl_operands[1], self))
 
 
 @ufl_type(is_index_free=True, num_ops=1)
@@ -288,7 +291,8 @@ def __new__(cls, a, b):
         if not (len(ash) == 1 and ash == bsh):
             raise ValueError(
                 f"Cross product requires arguments of rank 1, got {ufl_err_str(a)} "
-                f"and {ufl_err_str(b)}.")
+                f"and {ufl_err_str(b)}."
+            )
 
         # Simplification
         if isinstance(a, Zero) or isinstance(b, Zero):
@@ -308,8 +312,7 @@ def __init__(self, a, b):
 
     def __str__(self):
         """Format as a string."""
-        return "%s x %s" % (parstr(self.ufl_operands[0], self),
-                            parstr(self.ufl_operands[1], self))
+        return "%s x %s" % (parstr(self.ufl_operands[0], self), parstr(self.ufl_operands[1], self))
 
 
 @ufl_type(num_ops=1, inherit_indices_from_operand=0)
@@ -468,7 +471,9 @@ def __new__(cls, A):
         if len(sh) != 2:
             raise ValueError("Deviatoric part of tensor with rank != 2 is undefined.")
         if sh[0] != sh[1]:
-            raise ValueError(f"Cannot take deviatoric part of rectangular matrix with dimensions {sh}.")
+            raise ValueError(
+                f"Cannot take deviatoric part of rectangular matrix with dimensions {sh}."
+            )
         if A.ufl_free_indices:
             raise ValueError("Not expecting free indices in Deviatoric.")
 
@@ -536,7 +541,9 @@ def __new__(cls, A):
         if len(sh) != 2:
             raise ValueError("Symmetric part of tensor with rank != 2 is undefined.")
         if sh[0] != sh[1]:
-            raise ValueError(f"Cannot take symmetric part of rectangular matrix with dimensions {sh}.")
+            raise ValueError(
+                f"Cannot take symmetric part of rectangular matrix with dimensions {sh}."
+            )
         if Afi:
             raise ValueError("Not expecting free indices in Sym.")
 
diff --git a/ufl/tensors.py b/ufl/tensors.py
index 2fe829990..3edb0759c 100644
--- a/ufl/tensors.py
+++ b/ufl/tensors.py
@@ -39,11 +39,17 @@ def __new__(cls, *expressions):
 
         # Obviously, each subexpression must have the same shape
         if any(sh != e.ufl_shape for e in expressions[1:]):
-            raise ValueError("Cannot create a tensor by joining subexpressions with different shapes.")
+            raise ValueError(
+                "Cannot create a tensor by joining subexpressions with different shapes."
+            )
         if any(fi != e.ufl_free_indices for e in expressions[1:]):
-            raise ValueError("Cannot create a tensor where the components have different free indices.")
+            raise ValueError(
+                "Cannot create a tensor where the components have different free indices."
+            )
         if any(fid != e.ufl_index_dimensions for e in expressions[1:]):
-            raise ValueError("Cannot create a tensor where the components have different free index dimensions.")
+            raise ValueError(
+                "Cannot create a tensor where the components have different free index dimensions."
+            )
 
         # Simplify to Zero if possible
         if all(isinstance(e, Zero) for e in expressions):
@@ -59,7 +65,9 @@ def __init__(self, *expressions):
         # Checks
         indexset = set(self.ufl_operands[0].ufl_free_indices)
         if not all(not (indexset ^ set(e.ufl_free_indices)) for e in self.ufl_operands):
-            raise ValueError("Can't combine subtensor expressions with different sets of free indices.")
+            raise ValueError(
+                "Can't combine subtensor expressions with different sets of free indices."
+            )
 
     @property
     def ufl_shape(self):
@@ -71,7 +79,8 @@ def evaluate(self, x, mapping, component, index_values, derivatives=()):
         if len(component) != len(self.ufl_shape):
             raise ValueError(
                 "Can only evaluate scalars, expecting a component "
-                "tuple of length {len(self.ufl_shape)}, not {component}.")
+                "tuple of length {len(self.ufl_shape)}, not {component}."
+            )
         a = self.ufl_operands[component[0]]
         component = component[1:]
         if derivatives:
@@ -96,6 +105,7 @@ def __getitem__(self, key):
 
     def __str__(self):
         """Format as a string."""
+
         def substring(expressions, indent):
             ind = " " * indent
             if any(isinstance(e, ListTensor) for e in expressions):
@@ -110,6 +120,7 @@ def substring(expressions, indent):
             else:
                 s = ", ".join(str(e) for e in expressions)
                 return "%s[%s]" % (ind, s)
+
         return substring(self.ufl_operands, 0)
 
 
@@ -123,9 +134,11 @@ def __new__(cls, expression, indices):
         """Create a new ComponentTensor."""
         # Simplify
         if isinstance(expression, Zero):
-            fi, fid, sh = remove_indices(expression.ufl_free_indices,
-                                         expression.ufl_index_dimensions,
-                                         [ind.count() for ind in indices])
+            fi, fid, sh = remove_indices(
+                expression.ufl_free_indices,
+                expression.ufl_index_dimensions,
+                [ind.count() for ind in indices],
+            )
             return Zero(sh, fi, fid)
 
         # Construct
@@ -144,9 +157,11 @@ def __init__(self, expression, indices):
 
         Operator.__init__(self, (expression, indices))
 
-        fi, fid, sh = remove_indices(expression.ufl_free_indices,
-                                     expression.ufl_index_dimensions,
-                                     [ind.count() for ind in indices])
+        fi, fid, sh = remove_indices(
+            expression.ufl_free_indices,
+            expression.ufl_index_dimensions,
+            [ind.count() for ind in indices],
+        )
         self.ufl_free_indices = fi
         self.ufl_index_dimensions = fid
         self.ufl_shape = sh
@@ -190,9 +205,11 @@ def __str__(self):
 
 # --- User-level functions to wrap expressions in the correct way ---
 
+
 def numpy2nestedlists(arr):
     """Convert Numpy array to a nested list."""
     from numpy import ndarray
+
     if not isinstance(arr, ndarray):
         return arr
     return [numpy2nestedlists(arr[k]) for k in range(arr.shape[0])]
@@ -210,8 +227,9 @@ def _as_list_tensor(expressions):
 def from_numpy_to_lists(expressions):
     """Convert Numpy array to lists."""
     try:
-        import numpy
-        if isinstance(expressions, numpy.ndarray):
+        import numpy as np
+
+        if isinstance(expressions, np.ndarray):
             if expressions.shape == ():
                 # Unwrap scalar ndarray
                 return expressions.item()
@@ -389,6 +407,7 @@ def unit_indexed_tensor(shape, component):
     """Unit indexed tensor."""
     from ufl.constantvalue import Identity
     from ufl.operators import outer  # a bit of circular dependency issue here
+
     r = len(shape)
     if r == 0:
         return 0, ()
diff --git a/ufl/utils/formatting.py b/ufl/utils/formatting.py
index 4df63cd98..7c2d4336a 100644
--- a/ufl/utils/formatting.py
+++ b/ufl/utils/formatting.py
@@ -16,7 +16,7 @@ def camel2underscore(name):
             # Don't insert _ between multiple upper case letters
             if lastlower:
                 letters.append("_")
-            i = i.lower()  # noqa: E741
+            i = i.lower()
         lastlower = thislower
         letters.append(i)
     return "".join(letters)
@@ -45,7 +45,7 @@ def tstr(t, colsize=80):
 
     # Pretty-print table
     s = ""
-    for (key, value) in t:
+    for key, value in t:
         key = str(key)
         if isinstance(value, str):
             value = "'%s'" % value
@@ -85,7 +85,10 @@ def _tree_format_expression(expression, indentation, parentheses):
     if expression._ufl_is_terminal_:
         s = "%s%s" % (ind, repr(expression))
     else:
-        sops = [_tree_format_expression(o, indentation + 1, parentheses) for o in expression.ufl_operands]
+        sops = [
+            _tree_format_expression(o, indentation + 1, parentheses)
+            for o in expression.ufl_operands
+        ]
         s = "%s%s\n" % (ind, expression._ufl_class_.__name__)
         if parentheses and len(sops) > 1:
             s += "%s(\n" % (ind,)
diff --git a/ufl/utils/indexflattening.py b/ufl/utils/indexflattening.py
index 0e5aea412..f9935e51a 100644
--- a/ufl/utils/indexflattening.py
+++ b/ufl/utils/indexflattening.py
@@ -1,4 +1,4 @@
-"""This module contains a collection of utilities for mapping between multiindices and a flattened index space."""
+"""Collection of utilities for mapping between multiindices and a flattened index space."""
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
diff --git a/ufl/utils/sequences.py b/ufl/utils/sequences.py
index 9904287c4..71c845349 100644
--- a/ufl/utils/sequences.py
+++ b/ufl/utils/sequences.py
@@ -8,7 +8,7 @@
 
 from functools import reduce
 
-import numpy
+import numpy as np
 
 
 def product(sequence):
@@ -21,11 +21,11 @@ def product(sequence):
 
 def max_degree(degrees):
     """Maximum degree for mixture of scalar and tuple degrees."""
-    # numpy.maximum broadcasts scalar degrees to tuple degrees if
-    # necessary.  reduce applies numpy.maximum pairwise.
-    degree = reduce(numpy.maximum, map(numpy.asarray, degrees))
+    # np.maximum broadcasts scalar degrees to tuple degrees if
+    # necessary.  reduce applies np.maximum pairwise.
+    degree = reduce(np.maximum, map(np.asarray, degrees))
     if degree.ndim:
         degree = tuple(map(int, degree))  # tuple degree
     else:
-        degree = int(degree)              # scalar degree
+        degree = int(degree)  # scalar degree
     return degree
diff --git a/ufl/utils/sorting.py b/ufl/utils/sorting.py
index bf02cfdf6..254a60d59 100644
--- a/ufl/utils/sorting.py
+++ b/ufl/utils/sorting.py
@@ -48,10 +48,12 @@ def sorted_by_count(seq):
 
 def sorted_by_key(mapping):
     """Sort dict items by key, allowing different key types."""
+
     # Python3 doesn't allow comparing builtins of different type,
     # therefore the typename trick here
     def _key(x):
         return (type(x[0]).__name__, x[0])
+
     return sorted(mapping.items(), key=_key)
 
 
@@ -81,8 +83,10 @@ def canonicalize_metadata(metadata):
         elif isinstance(value, (int, float, str)) or value is None:
             value = str(value)
         else:
-            warnings.warn(f"Applying str() to a metadata value of type {type(value).__name__}, "
-                          "don't know if this is safe.")
+            warnings.warn(
+                f"Applying str() to a metadata value of type {type(value).__name__}, "
+                "don't know if this is safe."
+            )
             value = str(value)
         newvalues.append(value)
 
diff --git a/ufl/utils/stacks.py b/ufl/utils/stacks.py
index a19a713de..da4c39614 100644
--- a/ufl/utils/stacks.py
+++ b/ufl/utils/stacks.py
@@ -24,7 +24,11 @@ def peek(self):
 
 
 class StackDict(dict):
-    """A dict that can be changed incrementally with 'd.push(k,v)' and have changes rolled back with 'k,v = d.pop()'."""
+    """A dictionary type.
+
+    A dict that can be changed incrementally with 'd.push(k,v)' and have
+    changes rolled back with 'k,v = d.pop()'.
+    """
 
     def __init__(self, *args, **kwargs):
         """Initialise."""
diff --git a/ufl/variable.py b/ufl/variable.py
index 84a795434..ad671e10c 100644
--- a/ufl/variable.py
+++ b/ufl/variable.py
@@ -118,10 +118,12 @@ def label(self):
 
     def __eq__(self, other):
         """Check equality."""
-        return (isinstance(other, Variable) and self.ufl_operands[1] == other.ufl_operands[1] and  # noqa: W504
-                self.ufl_operands[0] == other.ufl_operands[0])
+        return (
+            isinstance(other, Variable)
+            and self.ufl_operands[1] == other.ufl_operands[1]
+            and self.ufl_operands[0] == other.ufl_operands[0]
+        )
 
     def __str__(self):
         """Format as a string."""
-        return "var%d(%s)" % (self.ufl_operands[1].count(),
-                              self.ufl_operands[0])
+        return "var%d(%s)" % (self.ufl_operands[1].count(), self.ufl_operands[0])


Test patch:
diff --git a/test/conftest.py b/test/conftest.py
index e2c610a6e..5c8030c74 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -8,7 +8,6 @@
 
 
 class Tester:
-
     def assertTrue(self, a):
         assert a
 
diff --git a/test/mockobjects.py b/test/mockobjects.py
index 4c68e0e21..caf8a88a8 100644
--- a/test/mockobjects.py
+++ b/test/mockobjects.py
@@ -2,7 +2,6 @@
 
 
 class MockMesh:
-
     def __init__(self, ufl_id):
         self._ufl_id = ufl_id
 
@@ -12,9 +11,16 @@ def ufl_id(self):
     def ufl_domain(self):
         return Mesh(triangle, ufl_id=self.ufl_id(), cargo=self)
 
-    def ufl_measure(self, integral_type="dx", subdomain_id="everywhere", metadata=None, subdomain_data=None):
-        return Measure(integral_type, subdomain_id=subdomain_id, metadata=metadata, domain=self,
-                       subdomain_data=subdomain_data)
+    def ufl_measure(
+        self, integral_type="dx", subdomain_id="everywhere", metadata=None, subdomain_data=None
+    ):
+        return Measure(
+            integral_type,
+            subdomain_id=subdomain_id,
+            metadata=metadata,
+            domain=self,
+            subdomain_data=subdomain_data,
+        )
 
 
 class MockMeshFunction:
@@ -32,5 +38,9 @@ def mesh(self):
 
     def ufl_measure(self, integral_type=None, subdomain_id="everywhere", metadata=None):
         return Measure(
-            integral_type, subdomain_id=subdomain_id, metadata=metadata,
-            domain=self.mesh(), subdomain_data=self)
+            integral_type,
+            subdomain_id=subdomain_id,
+            metadata=metadata,
+            domain=self.mesh(),
+            subdomain_data=self,
+        )
diff --git a/test/test_algorithms.py b/test/test_algorithms.py
index 4b87c2851..f8543249a 100755
--- a/test/test_algorithms.py
+++ b/test/test_algorithms.py
@@ -6,11 +6,37 @@
 
 import pytest
 
-from ufl import (Argument, Coefficient, FacetNormal, FunctionSpace, Mesh, TestFunction, TrialFunction, adjoint, div,
-                 dot, ds, dx, grad, inner, triangle)
-from ufl.algorithms import (expand_derivatives, expand_indices, extract_arguments, extract_coefficients,
-                            extract_elements, extract_unique_elements)
-from ufl.corealg.traversal import post_traversal, pre_traversal, unique_post_traversal, unique_pre_traversal
+from ufl import (
+    Argument,
+    Coefficient,
+    FacetNormal,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    adjoint,
+    div,
+    dot,
+    ds,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
+from ufl.algorithms import (
+    expand_derivatives,
+    expand_indices,
+    extract_arguments,
+    extract_coefficients,
+    extract_elements,
+    extract_unique_elements,
+)
+from ufl.corealg.traversal import (
+    post_traversal,
+    pre_traversal,
+    unique_post_traversal,
+    unique_pre_traversal,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
@@ -18,29 +44,29 @@
 # TODO: add more tests, covering all utility algorithms
 
 
-@pytest.fixture(scope='module')
+@pytest.fixture(scope="module")
 def element():
     return FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
 
 
-@pytest.fixture(scope='module')
+@pytest.fixture(scope="module")
 def domain():
-    return Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    return Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
 
-@pytest.fixture(scope='module')
+@pytest.fixture(scope="module")
 def space(element, domain):
     return FunctionSpace(domain, element)
 
 
-@pytest.fixture(scope='module')
+@pytest.fixture(scope="module")
 def arguments(space):
     v = TestFunction(space)
     u = TrialFunction(space)
     return (v, u)
 
 
-@pytest.fixture(scope='module')
+@pytest.fixture(scope="module")
 def coefficients(space):
     c = Coefficient(space)
     f = Coefficient(space)
@@ -110,7 +136,9 @@ def test_expand_indices(domain):
     u = TrialFunction(space)
 
     def evaluate(form):
-        return form.cell_integral()[0].integrand()((), {v: 3, u: 5})  # TODO: How to define values of derivatives?
+        return form.cell_integral()[0].integrand()(
+            (), {v: 3, u: 5}
+        )  # TODO: How to define values of derivatives?
 
     a = div(grad(v)) * u * dx
     # a1 = evaluate(a)
diff --git a/test/test_analyse_demos.py b/test/test_analyse_demos.py
index e9f41451d..a22980136 100755
--- a/test/test_analyse_demos.py
+++ b/test/test_analyse_demos.py
@@ -13,9 +13,8 @@
 
 def get_demo_filenames():
     filenames = sorted(
-        set(glob(os.path.join(demodir, "*.py")))
-        - set(glob(os.path.join(demodir, "_*.py")))
-        )
+        set(glob(os.path.join(demodir, "*.py"))) - set(glob(os.path.join(demodir, "_*.py")))
+    )
     return filenames
 
 
diff --git a/test/test_apply_algebra_lowering.py b/test/test_apply_algebra_lowering.py
index e1f496eb9..c0bdceb46 100755
--- a/test/test_apply_algebra_lowering.py
+++ b/test/test_apply_algebra_lowering.py
@@ -10,51 +10,72 @@
 
 @pytest.fixture
 def A0(request):
-    return Coefficient(FunctionSpace(
-        Mesh(FiniteElement("Lagrange", interval, 1,  (1, ), identity_pullback, H1)),
-        FiniteElement("Lagrange", interval, 1, (), identity_pullback, H1)))
+    return Coefficient(
+        FunctionSpace(
+            Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1)),
+            FiniteElement("Lagrange", interval, 1, (), identity_pullback, H1),
+        )
+    )
 
 
 @pytest.fixture
 def A1(request):
-    return Coefficient(FunctionSpace(
-        Mesh(FiniteElement("Lagrange", interval, 1, (1, ), identity_pullback, H1)),
-        FiniteElement("Lagrange", interval, 1, (1, 1), identity_pullback, H1)))
+    return Coefficient(
+        FunctionSpace(
+            Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1)),
+            FiniteElement("Lagrange", interval, 1, (1, 1), identity_pullback, H1),
+        )
+    )
 
 
 @pytest.fixture
 def A2(request):
-    return Coefficient(FunctionSpace(
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)),
-        FiniteElement("Lagrange", triangle, 1, (2, 2), identity_pullback, H1)))
+    return Coefficient(
+        FunctionSpace(
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+            FiniteElement("Lagrange", triangle, 1, (2, 2), identity_pullback, H1),
+        )
+    )
 
 
 @pytest.fixture
 def A3(request):
-    return Coefficient(FunctionSpace(
-        Mesh(FiniteElement("Lagrange", triangle, 1, (3, ), identity_pullback, H1)),
-        FiniteElement("Lagrange", triangle, 1, (3, 3), identity_pullback, H1)))
+    return Coefficient(
+        FunctionSpace(
+            Mesh(FiniteElement("Lagrange", triangle, 1, (3,), identity_pullback, H1)),
+            FiniteElement("Lagrange", triangle, 1, (3, 3), identity_pullback, H1),
+        )
+    )
 
 
 @pytest.fixture
 def A21(request):
-    return Coefficient(FunctionSpace(
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)),
-        FiniteElement("Lagrange", triangle, 1, (2, 1), identity_pullback, H1)))
+    return Coefficient(
+        FunctionSpace(
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+            FiniteElement("Lagrange", triangle, 1, (2, 1), identity_pullback, H1),
+        )
+    )
 
 
 @pytest.fixture
 def A31(request):
-    return Coefficient(FunctionSpace(
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)),
-        FiniteElement("Lagrange", triangle, 1, (3, 1), identity_pullback, H1)))
+    return Coefficient(
+        FunctionSpace(
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+            FiniteElement("Lagrange", triangle, 1, (3, 1), identity_pullback, H1),
+        )
+    )
 
 
 @pytest.fixture
 def A32(request):
-    return Coefficient(FunctionSpace(
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)),
-        FiniteElement("Lagrange", triangle, 1, (3, 2), identity_pullback, H1)))
+    return Coefficient(
+        FunctionSpace(
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+            FiniteElement("Lagrange", triangle, 1, (3, 2), identity_pullback, H1),
+        )
+    )
 
 
 def test_determinant0(A0):
@@ -66,38 +87,42 @@ def test_determinant1(A1):
 
 
 def test_determinant2(A2):
-    assert determinant_expr(A2) == A2[0, 0]*A2[1, 1] - A2[0, 1]*A2[1, 0]
+    assert determinant_expr(A2) == A2[0, 0] * A2[1, 1] - A2[0, 1] * A2[1, 0]
 
 
 def test_determinant3(A3):
-    assert determinant_expr(A3) == (A3[0, 0]*(A3[1, 1]*A3[2, 2] - A3[1, 2]*A3[2, 1])
-                                    + (A3[1, 0]*A3[2, 2] - A3[1, 2]*A3[2, 0])*(-A3[0, 1])
-                                    + A3[0, 2]*(A3[1, 0]*A3[2, 1] - A3[1, 1]*A3[2, 0]))
+    assert determinant_expr(A3) == (
+        A3[0, 0] * (A3[1, 1] * A3[2, 2] - A3[1, 2] * A3[2, 1])
+        + (A3[1, 0] * A3[2, 2] - A3[1, 2] * A3[2, 0]) * (-A3[0, 1])
+        + A3[0, 2] * (A3[1, 0] * A3[2, 1] - A3[1, 1] * A3[2, 0])
+    )
 
 
 def test_pseudo_determinant21(A21):
     i = Index()
-    assert renumber_indices(determinant_expr(A21)) == renumber_indices(sqrt(A21[i, 0]*A21[i, 0]))
+    assert renumber_indices(determinant_expr(A21)) == renumber_indices(sqrt(A21[i, 0] * A21[i, 0]))
 
 
 def test_pseudo_determinant31(A31):
     i = Index()
-    assert renumber_indices(determinant_expr(A31)) == renumber_indices(sqrt((A31[i, 0]*A31[i, 0])))
+    assert renumber_indices(determinant_expr(A31)) == renumber_indices(
+        sqrt((A31[i, 0] * A31[i, 0]))
+    )
 
 
 def test_pseudo_determinant32(A32):
     i = Index()
     c = cross_expr(A32[:, 0], A32[:, 1])
-    assert renumber_indices(determinant_expr(A32)) == renumber_indices(sqrt(c[i]*c[i]))
+    assert renumber_indices(determinant_expr(A32)) == renumber_indices(sqrt(c[i] * c[i]))
 
 
 def test_inverse0(A0):
-    expected = 1.0/A0  # stays scalar
+    expected = 1.0 / A0  # stays scalar
     assert inverse_expr(A0) == renumber_indices(expected)
 
 
 def test_inverse1(A1):
-    expected = as_tensor(((1.0/A1[0, 0],),))  # reshaped into 1x1 tensor
+    expected = as_tensor(((1.0 / A1[0, 0],),))  # reshaped into 1x1 tensor
     assert inverse_expr(A1) == renumber_indices(expected)
 
 
diff --git a/test/test_apply_function_pullbacks.py b/test/test_apply_function_pullbacks.py
index 872cfdd88..a3c009a77 100755
--- a/test/test_apply_function_pullbacks.py
+++ b/test/test_apply_function_pullbacks.py
@@ -1,11 +1,17 @@
-import numpy
+import numpy as np
 
 from ufl import Cell, Coefficient, FunctionSpace, Mesh, as_tensor, as_vector, dx, indices, triangle
 from ufl.algorithms.renumbering import renumber_indices
 from ufl.classes import Jacobian, JacobianDeterminant, JacobianInverse, ReferenceValue
 from ufl.finiteelement import FiniteElement, MixedElement, SymmetricElement
-from ufl.pullback import (contravariant_piola, covariant_piola, double_contravariant_piola, double_covariant_piola,
-                          identity_pullback, l2_piola)
+from ufl.pullback import (
+    contravariant_piola,
+    covariant_piola,
+    double_contravariant_piola,
+    double_covariant_piola,
+    identity_pullback,
+    l2_piola,
+)
 from ufl.sobolevspace import H1, L2, HCurl, HDiv, HDivDiv, HEin
 
 
@@ -13,7 +19,7 @@ def check_single_function_pullback(g, mappings):
     expected = mappings[g]
     actual = g.ufl_element().pullback.apply(ReferenceValue(g))
     assert expected.ufl_shape == actual.ufl_shape
-    for idx in numpy.ndindex(actual.ufl_shape):
+    for idx in np.ndindex(actual.ufl_shape):
         rexp = renumber_indices(expected[idx])
         ract = renumber_indices(actual[idx])
         if not rexp == ract:
@@ -26,26 +32,37 @@ def check_single_function_pullback(g, mappings):
             print("actual:")
             print(str(ract))
             print("signatures:")
-            print((expected**2*dx).signature())
-            print((actual**2*dx).signature())
+            print((expected**2 * dx).signature())
+            print((actual**2 * dx).signature())
             print()
         assert ract == rexp
 
 
 def test_apply_single_function_pullbacks_triangle3d():
     cell = Cell("triangle")
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
 
     UL2 = FiniteElement("Discontinuous Lagrange", cell, 1, (), l2_piola, L2)
     U0 = FiniteElement("Discontinuous Lagrange", cell, 0, (), identity_pullback, L2)
     U = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    V = FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1)
-    Vd = FiniteElement("Raviart-Thomas", cell, 1, (2, ), contravariant_piola, HDiv)
-    Vc = FiniteElement("N1curl", cell, 1, (2, ), covariant_piola, HCurl)
+    V = FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1)
+    Vd = FiniteElement("Raviart-Thomas", cell, 1, (2,), contravariant_piola, HDiv)
+    Vc = FiniteElement("N1curl", cell, 1, (2,), covariant_piola, HCurl)
     T = FiniteElement("Lagrange", cell, 1, (3, 3), identity_pullback, H1)
     S = SymmetricElement(
-        {(0, 0): 0, (1, 0): 1, (2, 0): 2, (0, 1): 1, (1, 1): 3, (2, 1): 4, (0, 2): 2, (1, 2): 4, (2, 2): 5},
-        [FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1) for _ in range(6)])
+        {
+            (0, 0): 0,
+            (1, 0): 1,
+            (2, 0): 2,
+            (0, 1): 1,
+            (1, 1): 3,
+            (2, 1): 4,
+            (0, 2): 2,
+            (1, 2): 4,
+            (2, 2): 5,
+        },
+        [FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1) for _ in range(6)],
+    )
     # (0, 2)-symmetric tensors
     COV2T = FiniteElement("Regge", cell, 0, (2, 2), double_covariant_piola, HEin)
     # (2, 0)-symmetric tensors
@@ -122,7 +139,7 @@ def test_apply_single_function_pullbacks_triangle3d():
     i, j, k, l = indices(4)  # noqa: E741
 
     # Contravariant H(div) Piola mapping:
-    M_hdiv = ((1.0/detJ) * J)  # Not applying cell orientation here
+    M_hdiv = (1.0 / detJ) * J  # Not applying cell orientation here
     # Covariant H(curl) Piola mapping: Jinv.T
 
     mappings = {
@@ -130,82 +147,136 @@ def test_apply_single_function_pullbacks_triangle3d():
         ul2: rul2 / detJ,
         u: ru,
         v: rv,
-        vd: as_vector(M_hdiv[i, j]*rvd[j], i),
-        vc: as_vector(Jinv[j, i]*rvc[j], i),
+        vd: as_vector(M_hdiv[i, j] * rvd[j], i),
+        vc: as_vector(Jinv[j, i] * rvc[j], i),
         t: rt,
-        s: as_tensor([[rs[0], rs[1], rs[2]],
-                      [rs[1], rs[3], rs[4]],
-                      [rs[2], rs[4], rs[5]]]),
+        s: as_tensor([[rs[0], rs[1], rs[2]], [rs[1], rs[3], rs[4]], [rs[2], rs[4], rs[5]]]),
         cov2t: as_tensor(Jinv[k, i] * rcov2t[k, l] * Jinv[l, j], (i, j)),
-        contra2t: as_tensor((1.0 / detJ)**2
-                            * J[i, k] * rcontra2t[k, l] * J[j, l], (i, j)),
+        contra2t: as_tensor((1.0 / detJ) ** 2 * J[i, k] * rcontra2t[k, l] * J[j, l], (i, j)),
         # Mixed elements become a bit more complicated
         uml2: as_vector([ruml2[0] / detJ, ruml2[1] / detJ]),
         um: rum,
         vm: rvm,
-        vdm: as_vector([
-            # V
-            rvdm[0],
-            rvdm[1],
-            rvdm[2],
-            # Vd
-            *(as_tensor(M_hdiv[i, j]*as_vector([rvdm[3], rvdm[4]])[j], (i,))[n]
-              for n in range(3))
-        ]), vcm: as_vector([
-            # Vd
-            *(as_tensor(M_hdiv[i, j]*as_vector([rvcm[0], rvcm[1]])[j], (i,))[n]
-              for n in range(3)),
-            # Vc
-            *(as_tensor(Jinv[i, j]*as_vector([rvcm[2], rvcm[3]])[i], (j,))[n]
-              for n in range(3))
-        ]), tm: as_vector([
-            # Vc
-            *(as_tensor(Jinv[i, j]*as_vector([rtm[0], rtm[1]])[i], (j,))[n]
-              for n in range(3)),
-            # T
-            rtm[2], rtm[3], rtm[4],
-            rtm[5], rtm[6], rtm[7],
-            rtm[8], rtm[9], rtm[10],
-        ]), sm: as_vector([
-            # T
-            rsm[0], rsm[1], rsm[2],
-            rsm[3], rsm[4], rsm[5],
-            rsm[6], rsm[7], rsm[8],
-            # S
-            rsm[9], rsm[10], rsm[11],
-            rsm[10], rsm[12], rsm[13],
-            rsm[11], rsm[13], rsm[14],
-        ]),
+        vdm: as_vector(
+            [
+                # V
+                rvdm[0],
+                rvdm[1],
+                rvdm[2],
+                # Vd
+                *(
+                    as_tensor(M_hdiv[i, j] * as_vector([rvdm[3], rvdm[4]])[j], (i,))[n]
+                    for n in range(3)
+                ),
+            ]
+        ),
+        vcm: as_vector(
+            [
+                # Vd
+                *(
+                    as_tensor(M_hdiv[i, j] * as_vector([rvcm[0], rvcm[1]])[j], (i,))[n]
+                    for n in range(3)
+                ),
+                # Vc
+                *(
+                    as_tensor(Jinv[i, j] * as_vector([rvcm[2], rvcm[3]])[i], (j,))[n]
+                    for n in range(3)
+                ),
+            ]
+        ),
+        tm: as_vector(
+            [
+                # Vc
+                *(
+                    as_tensor(Jinv[i, j] * as_vector([rtm[0], rtm[1]])[i], (j,))[n]
+                    for n in range(3)
+                ),
+                # T
+                rtm[2],
+                rtm[3],
+                rtm[4],
+                rtm[5],
+                rtm[6],
+                rtm[7],
+                rtm[8],
+                rtm[9],
+                rtm[10],
+            ]
+        ),
+        sm: as_vector(
+            [
+                # T
+                rsm[0],
+                rsm[1],
+                rsm[2],
+                rsm[3],
+                rsm[4],
+                rsm[5],
+                rsm[6],
+                rsm[7],
+                rsm[8],
+                # S
+                rsm[9],
+                rsm[10],
+                rsm[11],
+                rsm[10],
+                rsm[12],
+                rsm[13],
+                rsm[11],
+                rsm[13],
+                rsm[14],
+            ]
+        ),
         # Case from failing ffc demo:
-        vd0m: as_vector([
-            M_hdiv[0, j]*as_vector([rvd0m[0], rvd0m[1]])[j],
-            M_hdiv[1, j]*as_vector([rvd0m[0], rvd0m[1]])[j],
-            M_hdiv[2, j]*as_vector([rvd0m[0], rvd0m[1]])[j],
-            rvd0m[2]
-        ]),
+        vd0m: as_vector(
+            [
+                M_hdiv[0, j] * as_vector([rvd0m[0], rvd0m[1]])[j],
+                M_hdiv[1, j] * as_vector([rvd0m[0], rvd0m[1]])[j],
+                M_hdiv[2, j] * as_vector([rvd0m[0], rvd0m[1]])[j],
+                rvd0m[2],
+            ]
+        ),
         # This combines it all:
-        w: as_vector([
-            # S
-            rw[0], rw[1], rw[2],
-            rw[1], rw[3], rw[4],
-            rw[2], rw[4], rw[5],
-            # T
-            rw[6], rw[7], rw[8],
-            rw[9], rw[10], rw[11],
-            rw[12], rw[13], rw[14],
-            # Vc
-            *(as_tensor(Jinv[i, j]*as_vector([rw[15], rw[16]])[i], (j,))[n]
-              for n in range(3)),
-            # Vd
-            *(as_tensor(M_hdiv[i, j]*as_vector([rw[17], rw[18]])[j], (i,))[n]
-              for n in range(3)),
-            # V
-            rw[19],
-            rw[20],
-            rw[21],
-            # U
-            rw[22],
-        ]),
+        w: as_vector(
+            [
+                # S
+                rw[0],
+                rw[1],
+                rw[2],
+                rw[1],
+                rw[3],
+                rw[4],
+                rw[2],
+                rw[4],
+                rw[5],
+                # T
+                rw[6],
+                rw[7],
+                rw[8],
+                rw[9],
+                rw[10],
+                rw[11],
+                rw[12],
+                rw[13],
+                rw[14],
+                # Vc
+                *(
+                    as_tensor(Jinv[i, j] * as_vector([rw[15], rw[16]])[i], (j,))[n]
+                    for n in range(3)
+                ),
+                # Vd
+                *(
+                    as_tensor(M_hdiv[i, j] * as_vector([rw[17], rw[18]])[j], (i,))[n]
+                    for n in range(3)
+                ),
+                # V
+                rw[19],
+                rw[20],
+                rw[21],
+                # U
+                rw[22],
+            ]
+        ),
     }
 
     # Check functions of various elements outside a mixed context
@@ -234,16 +305,18 @@ def test_apply_single_function_pullbacks_triangle3d():
 
 def test_apply_single_function_pullbacks_triangle():
     cell = triangle
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 
     Ul2 = FiniteElement("Discontinuous Lagrange", cell, 1, (), l2_piola, L2)
     U = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    V = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
-    Vd = FiniteElement("Raviart-Thomas", cell, 1, (2, ), contravariant_piola, HDiv)
-    Vc = FiniteElement("N1curl", cell, 1, (2, ), covariant_piola, HCurl)
+    V = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
+    Vd = FiniteElement("Raviart-Thomas", cell, 1, (2,), contravariant_piola, HDiv)
+    Vc = FiniteElement("N1curl", cell, 1, (2,), covariant_piola, HCurl)
     T = FiniteElement("Lagrange", cell, 1, (2, 2), identity_pullback, H1)
-    S = SymmetricElement({(0, 0): 0, (0, 1): 1, (1, 0): 1, (1, 1): 2}, [
-        FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1) for i in range(3)])
+    S = SymmetricElement(
+        {(0, 0): 0, (0, 1): 1, (1, 0): 1, (1, 1): 2},
+        [FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1) for i in range(3)],
+    )
 
     Uml2 = MixedElement([Ul2, Ul2])
     Um = MixedElement([U, U])
@@ -303,7 +376,7 @@ def test_apply_single_function_pullbacks_triangle():
     i, j, k, l = indices(4)  # noqa: E741
 
     # Contravariant H(div) Piola mapping:
-    M_hdiv = (1.0/detJ) * J
+    M_hdiv = (1.0 / detJ) * J
     # Covariant H(curl) Piola mapping: Jinv.T
 
     mappings = {
@@ -311,66 +384,95 @@ def test_apply_single_function_pullbacks_triangle():
         ul2: rul2 / detJ,
         u: ru,
         v: rv,
-        vd: as_vector(M_hdiv[i, j]*rvd[j], i),
-        vc: as_vector(Jinv[j, i]*rvc[j], i),
+        vd: as_vector(M_hdiv[i, j] * rvd[j], i),
+        vc: as_vector(Jinv[j, i] * rvc[j], i),
         t: rt,
         s: as_tensor([[rs[0], rs[1]], [rs[1], rs[2]]]),
         # Mixed elements become a bit more complicated
         uml2: as_vector([ruml2[0] / detJ, ruml2[1] / detJ]),
         um: rum,
         vm: rvm,
-        vdm: as_vector([
-            # V
-            rvdm[0],
-            rvdm[1],
-            # Vd
-            *(as_tensor(M_hdiv[i, j]*as_vector([rvdm[2], rvdm[3]])[j], (i,))[n]
-              for n in range(2)),
-        ]),
-        vcm: as_vector([
-            # Vd
-            *(as_tensor(M_hdiv[i, j]*as_vector([rvcm[0], rvcm[1]])[j], (i,))[n]
-              for n in range(2)),
-            # Vc
-            *(as_tensor(Jinv[i, j]*as_vector([rvcm[2], rvcm[3]])[i], (j,))[n]
-              for n in range(2)),
-        ]),
-        tm: as_vector([
-            # Vc
-            *(as_tensor(Jinv[i, j]*as_vector([rtm[0], rtm[1]])[i], (j,))[n]
-              for n in range(2)),
-            # T
-            rtm[2], rtm[3],
-            rtm[4], rtm[5],
-        ]),
-        sm: as_vector([
-            # T
-            rsm[0], rsm[1],
-            rsm[2], rsm[3],
-            # S
-            rsm[4], rsm[5],
-            rsm[5], rsm[6],
-        ]),
+        vdm: as_vector(
+            [
+                # V
+                rvdm[0],
+                rvdm[1],
+                # Vd
+                *(
+                    as_tensor(M_hdiv[i, j] * as_vector([rvdm[2], rvdm[3]])[j], (i,))[n]
+                    for n in range(2)
+                ),
+            ]
+        ),
+        vcm: as_vector(
+            [
+                # Vd
+                *(
+                    as_tensor(M_hdiv[i, j] * as_vector([rvcm[0], rvcm[1]])[j], (i,))[n]
+                    for n in range(2)
+                ),
+                # Vc
+                *(
+                    as_tensor(Jinv[i, j] * as_vector([rvcm[2], rvcm[3]])[i], (j,))[n]
+                    for n in range(2)
+                ),
+            ]
+        ),
+        tm: as_vector(
+            [
+                # Vc
+                *(
+                    as_tensor(Jinv[i, j] * as_vector([rtm[0], rtm[1]])[i], (j,))[n]
+                    for n in range(2)
+                ),
+                # T
+                rtm[2],
+                rtm[3],
+                rtm[4],
+                rtm[5],
+            ]
+        ),
+        sm: as_vector(
+            [
+                # T
+                rsm[0],
+                rsm[1],
+                rsm[2],
+                rsm[3],
+                # S
+                rsm[4],
+                rsm[5],
+                rsm[5],
+                rsm[6],
+            ]
+        ),
         # This combines it all:
-        w: as_vector([
-            # S
-            rw[0], rw[1],
-            rw[1], rw[2],
-            # T
-            rw[3], rw[4],
-            rw[5], rw[6],
-            # Vc
-            *(as_tensor(Jinv[i, j]*as_vector([rw[7], rw[8]])[i], (j,))[n]
-              for n in range(2)),
-            # Vd
-            *(as_tensor(M_hdiv[i, j]*as_vector([rw[9], rw[10]])[j], (i,))[n]
-              for n in range(2)),
-            # V
-            rw[11],
-            rw[12],
-            # U
-            rw[13],
-        ]),
+        w: as_vector(
+            [
+                # S
+                rw[0],
+                rw[1],
+                rw[1],
+                rw[2],
+                # T
+                rw[3],
+                rw[4],
+                rw[5],
+                rw[6],
+                # Vc
+                *(as_tensor(Jinv[i, j] * as_vector([rw[7], rw[8]])[i], (j,))[n] for n in range(2)),
+                # Vd
+                *(
+                    as_tensor(M_hdiv[i, j] * as_vector([rw[9], rw[10]])[j], (i,))[n]
+                    for n in range(2)
+                ),
+                # V
+                rw[11],
+                rw[12],
+                # U
+                rw[13],
+            ]
+        ),
     }
 
     # Check functions of various elements outside a mixed context
diff --git a/test/test_apply_restrictions.py b/test/test_apply_restrictions.py
index efb9ad514..61b370e00 100755
--- a/test/test_apply_restrictions.py
+++ b/test/test_apply_restrictions.py
@@ -1,6 +1,16 @@
 from pytest import raises
 
-from ufl import Coefficient, FacetNormal, FunctionSpace, Mesh, SpatialCoordinate, as_tensor, grad, i, triangle
+from ufl import (
+    Coefficient,
+    FacetNormal,
+    FunctionSpace,
+    Mesh,
+    SpatialCoordinate,
+    as_tensor,
+    grad,
+    i,
+    triangle,
+)
 from ufl.algorithms.apply_restrictions import apply_default_restrictions, apply_restrictions
 from ufl.algorithms.renumbering import renumber_indices
 from ufl.finiteelement import FiniteElement
@@ -14,7 +24,7 @@ def test_apply_restrictions():
     V1 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
     V2 = FiniteElement("Lagrange", cell, 2, (), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     v0_space = FunctionSpace(domain, V0)
     v1_space = FunctionSpace(domain, V1)
     v2_space = FunctionSpace(domain, V2)
@@ -31,23 +41,26 @@ def test_apply_restrictions():
 
     # Continuous function gets default restriction if none
     # provided otherwise the user choice is respected
-    assert apply_restrictions(f) == f('+')
-    assert apply_restrictions(f('-')) == f('-')
-    assert apply_restrictions(f('+')) == f('+')
+    assert apply_restrictions(f) == f("+")
+    assert apply_restrictions(f("-")) == f("-")
+    assert apply_restrictions(f("+")) == f("+")
 
     # Propagation to terminals
-    assert apply_restrictions((f + f0)('+')) == f('+') + f0('+')
+    assert apply_restrictions((f + f0)("+")) == f("+") + f0("+")
 
     # Propagation stops at grad
-    assert apply_restrictions(grad(f)('-')) == grad(f)('-')
-    assert apply_restrictions((grad(f)**2)('+')) == grad(f)('+')**2
-    assert apply_restrictions((grad(f) + grad(g))('-')) == (grad(f)('-') + grad(g)('-'))
+    assert apply_restrictions(grad(f)("-")) == grad(f)("-")
+    assert apply_restrictions((grad(f) ** 2)("+")) == grad(f)("+") ** 2
+    assert apply_restrictions((grad(f) + grad(g))("-")) == (grad(f)("-") + grad(g)("-"))
 
     # x is the same from both sides but computed from one of them
-    assert apply_default_restrictions(x) == x('+')
+    assert apply_default_restrictions(x) == x("+")
 
     # n on a linear mesh is opposite pointing from the other side
-    assert apply_restrictions(n('+')) == n('+')
-    assert renumber_indices(apply_restrictions(n('-'))) == renumber_indices(as_tensor(-1*n('+')[i], i))
-    # This would be nicer, but -f is translated to -1*f which is translated to as_tensor(-1*f[i], i).
-    # assert apply_restrictions(n('-')) == -n('+')
+    assert apply_restrictions(n("+")) == n("+")
+    assert renumber_indices(apply_restrictions(n("-"))) == renumber_indices(
+        as_tensor(-1 * n("+")[i], i)
+    )
+    # This would be nicer, but -f is translated to -1*f which is
+    # translated to as_tensor(-1*f[i], i). assert
+    # apply_restrictions(n('-')) == -n('+')
diff --git a/test/test_arithmetic.py b/test/test_arithmetic.py
index 858f9ddd6..554eca967 100755
--- a/test/test_arithmetic.py
+++ b/test/test_arithmetic.py
@@ -1,5 +1,17 @@
-from ufl import (Identity, Mesh, SpatialCoordinate, as_matrix, as_ufl, as_vector, elem_div, elem_mult, elem_op, sin,
-                 tetrahedron, triangle)
+from ufl import (
+    Identity,
+    Mesh,
+    SpatialCoordinate,
+    as_matrix,
+    as_ufl,
+    as_vector,
+    elem_div,
+    elem_mult,
+    elem_op,
+    sin,
+    tetrahedron,
+    triangle,
+)
 from ufl.classes import ComplexValue, Division, FloatValue, IntValue
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
@@ -19,13 +31,13 @@ def test_scalar_casting(self):
 
 
 def test_ufl_float_division(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     d = SpatialCoordinate(domain)[0] / 10.0  # TODO: Use mock instead of x
     self.assertIsInstance(d, Division)
 
 
 def test_float_ufl_division(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     d = 3.14 / SpatialCoordinate(domain)[0]  # TODO: Use mock instead of x
     self.assertIsInstance(d, Division)
 
@@ -68,7 +80,7 @@ def test_elem_mult(self):
 
 
 def test_elem_mult_on_matrices(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
     A = as_matrix(((1, 2), (3, 4)))
     B = as_matrix(((4, 5), (6, 7)))
@@ -77,7 +89,7 @@ def test_elem_mult_on_matrices(self):
     x, y = SpatialCoordinate(domain)
     A = as_matrix(((x, y), (3, 4)))
     B = as_matrix(((4, 5), (y, x)))
-    self.assertEqual(elem_mult(A, B), as_matrix(((4*x, 5*y), (3*y, 4*x))))
+    self.assertEqual(elem_mult(A, B), as_matrix(((4 * x, 5 * y), (3 * y, 4 * x))))
 
     x, y = SpatialCoordinate(domain)
     A = as_matrix(((x, y), (3, 4)))
@@ -86,17 +98,18 @@ def test_elem_mult_on_matrices(self):
 
 
 def test_elem_div(self):
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     x, y, z = SpatialCoordinate(domain)
     A = as_matrix(((x, y, z), (3, 4, 5)))
     B = as_matrix(((7, 8, 9), (z, x, y)))
-    self.assertEqual(elem_div(A, B), as_matrix(((x/7, y/8, z/9), (3/z, 4/x, 5/y))))
+    self.assertEqual(elem_div(A, B), as_matrix(((x / 7, y / 8, z / 9), (3 / z, 4 / x, 5 / y))))
 
 
 def test_elem_op(self):
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     x, y, z = SpatialCoordinate(domain)
     A = as_matrix(((x, y, z), (3, 4, 5)))
-    self.assertEqual(elem_op(sin, A), as_matrix(((sin(x), sin(y), sin(z)),
-                                                 (sin(3), sin(4), sin(5)))))
+    self.assertEqual(
+        elem_op(sin, A), as_matrix(((sin(x), sin(y), sin(z)), (sin(3), sin(4), sin(5))))
+    )
     self.assertEqual(elem_op(sin, A).dx(0).ufl_shape, (2, 3))
diff --git a/test/test_automatic_differentiation.py b/test/test_automatic_differentiation.py
index a1d080c76..45549ae6b 100755
--- a/test/test_automatic_differentiation.py
+++ b/test/test_automatic_differentiation.py
@@ -7,13 +7,76 @@
 
 import pytest
 
-from ufl import (And, Argument, CellDiameter, CellVolume, Circumradius, Coefficient, Constant, FacetArea, FacetNormal,
-                 FunctionSpace, Identity, Jacobian, JacobianDeterminant, JacobianInverse, MaxCellEdgeLength,
-                 MaxFacetEdgeLength, Mesh, MinCellEdgeLength, MinFacetEdgeLength, Not, Or, PermutationSymbol,
-                 SpatialCoordinate, acos, as_matrix, as_tensor, as_ufl, as_vector, asin, atan, bessel_I, bessel_J,
-                 bessel_K, bessel_Y, cofac, conditional, cos, cross, derivative, det, dev, diff, dot, eq, erf, exp, ge,
-                 grad, gt, indices, inner, interval, inv, le, ln, lt, ne, outer, replace, sin, skew, sqrt, sym, tan,
-                 tetrahedron, tr, triangle, variable)
+from ufl import (
+    And,
+    Argument,
+    CellDiameter,
+    CellVolume,
+    Circumradius,
+    Coefficient,
+    Constant,
+    FacetArea,
+    FacetNormal,
+    FunctionSpace,
+    Identity,
+    Jacobian,
+    JacobianDeterminant,
+    JacobianInverse,
+    MaxCellEdgeLength,
+    MaxFacetEdgeLength,
+    Mesh,
+    MinCellEdgeLength,
+    MinFacetEdgeLength,
+    Not,
+    Or,
+    PermutationSymbol,
+    SpatialCoordinate,
+    acos,
+    as_matrix,
+    as_tensor,
+    as_ufl,
+    as_vector,
+    asin,
+    atan,
+    bessel_I,
+    bessel_J,
+    bessel_K,
+    bessel_Y,
+    cofac,
+    conditional,
+    cos,
+    cross,
+    derivative,
+    det,
+    dev,
+    diff,
+    dot,
+    eq,
+    erf,
+    exp,
+    ge,
+    grad,
+    gt,
+    indices,
+    inner,
+    interval,
+    inv,
+    le,
+    ln,
+    lt,
+    ne,
+    outer,
+    replace,
+    sin,
+    skew,
+    sqrt,
+    sym,
+    tan,
+    tetrahedron,
+    tr,
+    triangle,
+    variable,
+)
 from ufl.algorithms import expand_derivatives
 from ufl.conditional import Conditional
 from ufl.corealg.traversal import unique_post_traversal
@@ -23,11 +86,10 @@
 
 
 class ExpressionCollection(object):
-
     def __init__(self, cell):
         self.cell = cell
         d = cell.topological_dimension()
-        domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1))
+        domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1))
 
         x = SpatialCoordinate(domain)
         n = FacetNormal(domain)
@@ -49,7 +111,7 @@ def __init__(self, cell):
         eps = PermutationSymbol(d)
 
         U = FiniteElement("Undefined", cell, None, (), identity_pullback, L2)
-        V = FiniteElement("Undefined", cell, None, (d, ), identity_pullback, L2)
+        V = FiniteElement("Undefined", cell, None, (d,), identity_pullback, L2)
         W = FiniteElement("Undefined", cell, None, (d, d), identity_pullback, L2)
 
         u_space = FunctionSpace(domain, U)
@@ -65,6 +127,7 @@ def __init__(self, cell):
 
         class ObjectCollection(object):
             pass
+
         self.shared_objects = ObjectCollection()
         for key, value in list(locals().items()):
             setattr(self.shared_objects, key, value)
@@ -78,51 +141,84 @@ class ObjectCollection(object):
         self.terminals += self.geometry
         self.terminals += self.functions
 
-        self.algebra = ([
-            u*2, v*2, w*2,
-            u+2*u, v+2*v, w+2*w,
-            2/u, u/2, v/2, w/2,
-            u**3, 3**u,
-        ])
-        self.mathfunctions = ([
-            abs(u), sqrt(u), exp(u), ln(u),
-            cos(u), sin(u), tan(u), acos(u), asin(u), atan(u),
-            erf(u), bessel_I(1, u), bessel_J(1, u), bessel_K(1, u), bessel_Y(1, u),
-        ])
-        self.variables = ([
-            variable(u), variable(v), variable(w),
-            variable(w*u), 3*variable(w*u),
-        ])
+        self.algebra = [
+            u * 2,
+            v * 2,
+            w * 2,
+            u + 2 * u,
+            v + 2 * v,
+            w + 2 * w,
+            2 / u,
+            u / 2,
+            v / 2,
+            w / 2,
+            u**3,
+            3**u,
+        ]
+        self.mathfunctions = [
+            abs(u),
+            sqrt(u),
+            exp(u),
+            ln(u),
+            cos(u),
+            sin(u),
+            tan(u),
+            acos(u),
+            asin(u),
+            atan(u),
+            erf(u),
+            bessel_I(1, u),
+            bessel_J(1, u),
+            bessel_K(1, u),
+            bessel_Y(1, u),
+        ]
+        self.variables = [
+            variable(u),
+            variable(v),
+            variable(w),
+            variable(w * u),
+            3 * variable(w * u),
+        ]
 
         if d == 1:
             w2 = as_matrix(((u**2,),))
         if d == 2:
-            w2 = as_matrix(((u**2, u**3),
-                            (u**4, u**5)))
+            w2 = as_matrix(((u**2, u**3), (u**4, u**5)))
         if d == 3:
-            w2 = as_matrix(((u**2, u**3, u**4),
-                            (u**4, u**5, u**6),
-                            (u**6, u**7, u**8)))
+            w2 = as_matrix(((u**2, u**3, u**4), (u**4, u**5, u**6), (u**6, u**7, u**8)))
 
         # Indexed,  ListTensor, ComponentTensor, IndexSum
         i, j, k, l = indices(4)  # noqa: E741
-        self.indexing = ([
-                v[0], w[d-1, 0], v[i], w[i, j],
-                v[:], w[0, :], w[:, 0],
-                v[...], w[0, ...], w[..., 0],
-                v[i]*v[j], w[i, 0]*v[j], w[d-1, j]*v[i],
-                v[i]*v[i], w[i, 0]*w[0, i], v[i]*w[0, i],
-                v[j]*w[d-1, j], w[i, i], w[i, j]*w[j, i],
-                as_tensor(v[i]*w[k, 0], (k, i)),
-                as_tensor(v[i]*w[k, 0], (k, i))[:, l],
-                as_tensor(w[i, j]*w[k, l], (k, j, l, i)),
-                as_tensor(w[i, j]*w[k, l], (k, j, l, i))[0, 0, 0, 0],
-                as_vector((u, 2, 3)),
-                as_matrix(((u**2, u**3), (u**4, u**5))),
-                as_vector((u, 2, 3))[i],
-                w2[i, j]*w[i, j],
-        ])
-        self.conditionals = ([
+        self.indexing = [
+            v[0],
+            w[d - 1, 0],
+            v[i],
+            w[i, j],
+            v[:],
+            w[0, :],
+            w[:, 0],
+            v[...],
+            w[0, ...],
+            w[..., 0],
+            v[i] * v[j],
+            w[i, 0] * v[j],
+            w[d - 1, j] * v[i],
+            v[i] * v[i],
+            w[i, 0] * w[0, i],
+            v[i] * w[0, i],
+            v[j] * w[d - 1, j],
+            w[i, i],
+            w[i, j] * w[j, i],
+            as_tensor(v[i] * w[k, 0], (k, i)),
+            as_tensor(v[i] * w[k, 0], (k, i))[:, l],
+            as_tensor(w[i, j] * w[k, l], (k, j, l, i)),
+            as_tensor(w[i, j] * w[k, l], (k, j, l, i))[0, 0, 0, 0],
+            as_vector((u, 2, 3)),
+            as_matrix(((u**2, u**3), (u**4, u**5))),
+            as_vector((u, 2, 3))[i],
+            w2[i, j] * w[i, j],
+        ]
+        self.conditionals = [
             conditional(le(u, 1.0), 1, 0),
             conditional(eq(3.0, u), 1, 0),
             conditional(ne(sin(u), cos(u)), 1, 0),
@@ -136,16 +232,16 @@ class ObjectCollection(object):
             conditional(Not(ge(u, 0.0)), 1, 2),
             conditional(And(Not(ge(u, 0.0)), lt(u, 1.0)), 1, 2),
             conditional(le(u, 0.0), u**3, ln(u)),
-        ])
-        self.restrictions = [u('+'), u('-'), v('+'), v('-'), w('+'), w('-')]
+        ]
+        self.restrictions = [u("+"), u("-"), v("+"), v("-"), w("+"), w("-")]
         if d > 1:
             i, j = indices(2)
-            self.restrictions += ([
-                v('+')[i]*v('+')[i],
-                v[i]('+')*v[i]('+'),
-                (v[i]*v[i])('+'),
-                (v[i]*v[j])('+')*w[i, j]('+'),
-            ])
+            self.restrictions += [
+                v("+")[i] * v("+")[i],
+                v[i]("+") * v[i]("+"),
+                (v[i] * v[i])("+"),
+                (v[i] * v[j])("+") * w[i, j]("+"),
+            ]
 
         self.noncompounds = []
         self.noncompounds += self.algebra
@@ -158,7 +254,7 @@ class ObjectCollection(object):
         if d == 1:
             self.tensorproducts = []
         else:
-            self.tensorproducts = ([
+            self.tensorproducts = [
                 dot(v, v),
                 dot(v, w),
                 dot(w, w),
@@ -168,26 +264,32 @@ class ObjectCollection(object):
                 outer(w, v),
                 outer(v, w),
                 outer(w, w),
-            ])
+            ]
 
         if d == 1:
             self.tensoralgebra = []
         else:
-            self.tensoralgebra = ([
-                w.T, sym(w), skew(w), dev(w),
-                det(w), tr(w), cofac(w), inv(w),
-            ])
+            self.tensoralgebra = [
+                w.T,
+                sym(w),
+                skew(w),
+                dev(w),
+                det(w),
+                tr(w),
+                cofac(w),
+                inv(w),
+            ]
 
         if d != 3:
             self.crossproducts = []
         else:
-            self.crossproducts = ([
+            self.crossproducts = [
                 cross(v, v),
-                cross(v, 2*v),
+                cross(v, 2 * v),
                 cross(v, w[0, :]),
                 cross(v, w[:, 1]),
                 cross(w[:, 0], v),
-            ])
+            ]
 
         self.compounds = []
         self.compounds += self.tensorproducts
@@ -220,31 +322,36 @@ def ad_algorithm(expr):
             expr,
             apply_expand_compounds_before=True,
             apply_expand_compounds_after=False,
-            use_alternative_wrapper_algorithm=True)
+            use_alternative_wrapper_algorithm=True,
+        )
     elif alt == 2:
         return expand_derivatives(
             expr,
             apply_expand_compounds_before=False,
             apply_expand_compounds_after=True,
-            use_alternative_wrapper_algorithm=False)
+            use_alternative_wrapper_algorithm=False,
+        )
     elif alt == 3:
         return expand_derivatives(
             expr,
             apply_expand_compounds_before=False,
             apply_expand_compounds_after=False,
-            use_alternative_wrapper_algorithm=False)
+            use_alternative_wrapper_algorithm=False,
+        )
     elif alt == 4:
         return expand_derivatives(
             expr,
             apply_expand_compounds_before=False,
             apply_expand_compounds_after=False,
-            use_alternative_wrapper_algorithm=True)
+            use_alternative_wrapper_algorithm=True,
+        )
     elif alt == 5:
         return expand_derivatives(
             expr,
             apply_expand_compounds_before=False,
             apply_expand_compounds_after=False,
-            use_alternative_wrapper_algorithm=False)
+            use_alternative_wrapper_algorithm=False,
+        )
 
 
 def _test_no_derivatives_no_change(self, collection):
@@ -277,7 +384,9 @@ def test_no_derivatives_no_change(self, d_expr):
     _test_no_derivatives_no_change(self, ex.noncompounds)
 
 
-def xtest_compounds_no_derivatives_no_change(self, d_expr):  # This test fails with expand_compounds enabled
+def xtest_compounds_no_derivatives_no_change(
+    self, d_expr
+):  # This test fails with expand_compounds enabled
     d, ex = d_expr
     _test_no_derivatives_no_change(self, ex.compounds)
 
@@ -298,13 +407,13 @@ def _test_zero_derivatives_of_terminals_produce_the_right_types_and_shapes(self,
         for var in (u, v, w):
             before = derivative(t, var)  # This will often get preliminary simplified to zero
             after = ad_algorithm(before)
-            expected = 0*t
+            expected = 0 * t
             # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
-            before = derivative(c*t, var)  # This will usually not get simplified to zero
+            before = derivative(c * t, var)  # This will usually not get simplified to zero
             after = ad_algorithm(before)
-            expected = 0*t
+            expected = 0 * t
             # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
@@ -328,13 +437,13 @@ def _test_zero_diffs_of_terminals_produce_the_right_types_and_shapes(self, colle
         for var in (vu, vv, vw):
             before = diff(t, var)  # This will often get preliminary simplified to zero
             after = ad_algorithm(before)
-            expected = 0*outer(t, var)
+            expected = 0 * outer(t, var)
             # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
-            before = diff(c*t, var)  # This will usually not get simplified to zero
+            before = diff(c * t, var)  # This will usually not get simplified to zero
             after = ad_algorithm(before)
-            expected = 0*outer(t, var)
+            expected = 0 * outer(t, var)
             # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
@@ -356,22 +465,22 @@ def _test_zero_derivatives_of_noncompounds_produce_the_right_types_and_shapes(se
     for t in collection.noncompounds:
         for var in (u, v, w):
             if debug:
-                print('\n', 'shapes:   ', t.ufl_shape, var.ufl_shape, '\n')
+                print("\n", "shapes:   ", t.ufl_shape, var.ufl_shape, "\n")
             if debug:
-                print('\n', 't:        ', str(t), '\n')
+                print("\n", "t:        ", str(t), "\n")
             if debug:
-                print('\n', 't ind:    ', str(t.ufl_free_indices), '\n')
+                print("\n", "t ind:    ", str(t.ufl_free_indices), "\n")
             if debug:
-                print('\n', 'var:      ', str(var), '\n')
+                print("\n", "var:      ", str(var), "\n")
             before = derivative(t, var)
             if debug:
-                print('\n', 'before:   ', str(before), '\n')
+                print("\n", "before:   ", str(before), "\n")
             after = ad_algorithm(before)
             if debug:
-                print('\n', 'after:    ', str(after), '\n')
-            expected = 0*t
+                print("\n", "after:    ", str(after), "\n")
+            expected = 0 * t
             if debug:
-                print('\n', 'expected: ', str(expected), '\n')
+                print("\n", "expected: ", str(expected), "\n")
             assert after == expected
 
 
@@ -396,13 +505,13 @@ def _test_zero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self, co
         for var in (vu, vv, vw):
             before = diff(t, var)
             if debug:
-                print('\n', 'before:   ', str(before), '\n')
+                print("\n", "before:   ", str(before), "\n")
             after = ad_algorithm(before)
             if debug:
-                print('\n', 'after:    ', str(after), '\n')
-            expected = 0*outer(t, var)
+                print("\n", "after:    ", str(after), "\n")
+            expected = 0 * outer(t, var)
             if debug:
-                print('\n', 'expected: ', str(expected), '\n')
+                print("\n", "expected: ", str(expected), "\n")
             # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
@@ -429,16 +538,16 @@ def _test_nonzero_derivatives_of_noncompounds_produce_the_right_types_and_shapes
                 continue
 
             if debug:
-                print(('\n', '...:   ', t.ufl_shape, var.ufl_shape, '\n'))
+                print(("\n", "...:   ", t.ufl_shape, var.ufl_shape, "\n"))
             before = derivative(t, var)
             if debug:
-                print(('\n', 'before:   ', str(before), '\n'))
+                print(("\n", "before:   ", str(before), "\n"))
             after = ad_algorithm(before)
             if debug:
-                print(('\n', 'after:    ', str(after), '\n'))
-            expected_shape = 0*t
+                print(("\n", "after:    ", str(after), "\n"))
+            expected_shape = 0 * t
             if debug:
-                print(('\n', 'expected_shape: ', str(expected_shape), '\n'))
+                print(("\n", "expected_shape: ", str(expected_shape), "\n"))
             # print '\n', str(expected_shape), '\n', str(after), '\n', str(before), '\n'
 
             if var in unique_post_traversal(t):
@@ -475,13 +584,13 @@ def _test_nonzero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self,
 
             before = diff(t, var)
             if debug:
-                print(('\n', 'before:   ', str(before), '\n'))
+                print(("\n", "before:   ", str(before), "\n"))
             after = ad_algorithm(before)
             if debug:
-                print(('\n', 'after:    ', str(after), '\n'))
-            expected_shape = 0*outer(t, var)  # expected shape, not necessarily value
+                print(("\n", "after:    ", str(after), "\n"))
+            expected_shape = 0 * outer(t, var)  # expected shape, not necessarily value
             if debug:
-                print(('\n', 'expected_shape: ', str(expected_shape), '\n'))
+                print(("\n", "expected_shape: ", str(expected_shape), "\n"))
             # print '\n', str(expected_shape), '\n', str(after), '\n', str(before), '\n'
 
             if var in unique_post_traversal(t):
@@ -502,8 +611,8 @@ def test_grad_coeff(self, d_expr):
         after = ad_algorithm(before)
 
         if before.ufl_shape != after.ufl_shape:
-            print(('\n', 'shapes:', before.ufl_shape, after.ufl_shape))
-            print(('\n', str(before), '\n', str(after), '\n'))
+            print(("\n", "shapes:", before.ufl_shape, after.ufl_shape))
+            print(("\n", str(before), "\n", str(after), "\n"))
 
         self.assertEqualTotalShape(before, after)
         if f is u:  # Differing by being wrapped in indexing types
@@ -543,8 +652,8 @@ def test_derivative_grad_coeff(self, d_expr):
         # assert after == expected
         if 0:
             print()
-            print(('B', f, "::", before))
-            print(('A', f, "::", after))
+            print(("B", f, "::", before))
+            print(("A", f, "::", after))
 
 
 def xtest_derivative_grad_coeff_with_variation_components(self, d_expr):
@@ -556,7 +665,7 @@ def xtest_derivative_grad_coeff_with_variation_components(self, d_expr):
     dw = collection.shared_objects.dw
     for g, dg in ((v, dv), (w, dw)):
         # Pick a single component
-        ii = (0,)*(len(g.ufl_shape))
+        ii = (0,) * (len(g.ufl_shape))
         f = g[ii]
         df = dg[ii]
 
@@ -576,5 +685,5 @@ def xtest_derivative_grad_coeff_with_variation_components(self, d_expr):
         # assert after == expected
         if 0:
             print()
-            print(('B', f, "::", before))
-            print(('A', f, "::", after))
+            print(("B", f, "::", before))
+            print(("A", f, "::", after))
diff --git a/test/test_change_to_local.py b/test/test_change_to_local.py
index f0789fbba..973195bc7 100755
--- a/test/test_change_to_local.py
+++ b/test/test_change_to_local.py
@@ -11,15 +11,15 @@
 
 def test_change_to_reference_grad():
     cell = triangle
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     U = FunctionSpace(domain, FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1))
-    V = FunctionSpace(domain, FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    V = FunctionSpace(domain, FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     u = Coefficient(U)
     v = Coefficient(V)
     Jinv = JacobianInverse(domain)
     i, j, k = indices(3)
     q, r, s = indices(3)
-    t, = indices(1)
+    (t,) = indices(1)
 
     # Single grad change on a scalar function
     expr = grad(u)
@@ -36,27 +36,33 @@ def test_change_to_reference_grad():
     # Multiple grads should work fine for affine domains:
     expr = grad(grad(u))
     actual = change_to_reference_grad(expr)
-    expected = as_tensor(
-        Jinv[s, j] * (Jinv[r, i] * ReferenceGrad(ReferenceGrad(u))[r, s]), (i, j))
+    expected = as_tensor(Jinv[s, j] * (Jinv[r, i] * ReferenceGrad(ReferenceGrad(u))[r, s]), (i, j))
     assert renumber_indices(actual) == renumber_indices(expected)
 
     expr = grad(grad(grad(u)))
     actual = change_to_reference_grad(expr)
     expected = as_tensor(
-        Jinv[s, k] * (Jinv[r, j] * (Jinv[q, i] * ReferenceGrad(ReferenceGrad(ReferenceGrad(u)))[q, r, s])), (i, j, k))
+        Jinv[s, k]
+        * (Jinv[r, j] * (Jinv[q, i] * ReferenceGrad(ReferenceGrad(ReferenceGrad(u)))[q, r, s])),
+        (i, j, k),
+    )
     assert renumber_indices(actual) == renumber_indices(expected)
 
     # Multiple grads on a vector valued function
     expr = grad(grad(v))
     actual = change_to_reference_grad(expr)
     expected = as_tensor(
-        Jinv[s, j] * (Jinv[r, i] * ReferenceGrad(ReferenceGrad(v))[t, r, s]), (t, i, j))
+        Jinv[s, j] * (Jinv[r, i] * ReferenceGrad(ReferenceGrad(v))[t, r, s]), (t, i, j)
+    )
     assert renumber_indices(actual) == renumber_indices(expected)
 
     expr = grad(grad(grad(v)))
     actual = change_to_reference_grad(expr)
-    expected = as_tensor(Jinv[s, k] * (Jinv[r, j] * (
-        Jinv[q, i] * ReferenceGrad(ReferenceGrad(ReferenceGrad(v)))[t, q, r, s])), (t, i, j, k))
+    expected = as_tensor(
+        Jinv[s, k]
+        * (Jinv[r, j] * (Jinv[q, i] * ReferenceGrad(ReferenceGrad(ReferenceGrad(v)))[t, q, r, s])),
+        (t, i, j, k),
+    )
     assert renumber_indices(actual) == renumber_indices(expected)
 
     # print tree_format(expected)
diff --git a/test/test_change_to_reference_frame.py b/test/test_change_to_reference_frame.py
index 9b46b510c..63b0751b3 100755
--- a/test/test_change_to_reference_frame.py
+++ b/test/test_change_to_reference_frame.py
@@ -14,10 +14,10 @@ def change_to_reference_frame(expr):
 
 def test_change_unmapped_form_arguments_to_reference_frame():
     U = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    V = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
+    V = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
     T = FiniteElement("Lagrange", triangle, 1, (2, 2), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     u_space = FunctionSpace(domain, U)
     v_space = FunctionSpace(domain, V)
     t_space = FunctionSpace(domain, T)
@@ -31,9 +31,9 @@ def test_change_unmapped_form_arguments_to_reference_frame():
 
 
 def test_change_hdiv_form_arguments_to_reference_frame():
-    V = FiniteElement("Raviart-Thomas", triangle, 1, (2, ), contravariant_piola, HDiv)
+    V = FiniteElement("Raviart-Thomas", triangle, 1, (2,), contravariant_piola, HDiv)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
 
     expr = Coefficient(v_space)
@@ -41,15 +41,15 @@ def test_change_hdiv_form_arguments_to_reference_frame():
 
 
 def test_change_hcurl_form_arguments_to_reference_frame():
-    V = FiniteElement("Raviart-Thomas", triangle, 1, (2, ), contravariant_piola, HDiv)
+    V = FiniteElement("Raviart-Thomas", triangle, 1, (2,), contravariant_piola, HDiv)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
 
     expr = Coefficient(v_space)
     assert change_to_reference_frame(expr) == ReferenceValue(expr)
 
-    '''
+    """
     # user input
     grad(f + g)('+')
     # change to reference frame
@@ -121,10 +121,10 @@ def test_change_hcurl_form_arguments_to_reference_frame():
     e = v | cell_avg(v) | facet_avg(v) | at_cell_midpoint(v) | at_facet_midpoint(v)
                                          # evaluated at point or averaged over cell entity
     m = e | indexed(e)                   # scalar component of
-    '''
+    """
 
 
-'''
+"""
 New form preprocessing pipeline:
 
 Preferably introduce these changes:
@@ -139,7 +139,8 @@ def test_change_hcurl_form_arguments_to_reference_frame():
     b) lower_compound_operators # expand_compounds
     c) change_to_reference_frame # change f->rv(f), m->M*rv(m),
                                           grad(f)->K*rgrad(rv(f)),
-                                          grad(grad(f))->K*rgrad(K*rgrad(rv(f))), grad(expr)->K*rgrad(expr)
+                                          grad(grad(f))->K*rgrad(K*rgrad(rv(f))),
+                                                grad(expr)->K*rgrad(expr)
                                  # if grad(expr)->K*rgrad(expr) should be valid,
                                    then rgrad must be applicable to quite generic expressions
     d) apply_derivatives         # one possibility is to add an apply_mapped_derivatives AD
@@ -147,4 +148,4 @@ def test_change_hcurl_form_arguments_to_reference_frame():
     e) apply_geometry_lowering
     f) apply_restrictions # requiring grad(f)('+') instead of grad(f('+')) would simplify a lot...
 iii) extract final metadata about elements and coefficient ordering
-'''
+"""
diff --git a/test/test_check_arities.py b/test/test_check_arities.py
index 37ce7a26d..e4ede949f 100755
--- a/test/test_check_arities.py
+++ b/test/test_check_arities.py
@@ -1,7 +1,23 @@
 import pytest
 
-from ufl import (Coefficient, FacetNormal, FunctionSpace, Mesh, SpatialCoordinate, TestFunction, TrialFunction, adjoint,
-                 cofac, conj, derivative, ds, dx, grad, inner, tetrahedron)
+from ufl import (
+    Coefficient,
+    FacetNormal,
+    FunctionSpace,
+    Mesh,
+    SpatialCoordinate,
+    TestFunction,
+    TrialFunction,
+    adjoint,
+    cofac,
+    conj,
+    derivative,
+    ds,
+    dx,
+    grad,
+    inner,
+    tetrahedron,
+)
 from ufl.algorithms.check_arities import ArityMismatch
 from ufl.algorithms.compute_form_data import compute_form_data
 from ufl.finiteelement import FiniteElement
@@ -12,8 +28,8 @@
 def test_check_arities():
     # Code from bitbucket issue #49
     cell = tetrahedron
-    D = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
-    V = FunctionSpace(D, FiniteElement("Lagrange", cell, 2, (3, ), identity_pullback, H1))
+    D = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
+    V = FunctionSpace(D, FiniteElement("Lagrange", cell, 2, (3,), identity_pullback, H1))
     dv = TestFunction(V)
     du = TrialFunction(V)
 
@@ -36,8 +52,8 @@ def test_check_arities():
 
 def test_complex_arities():
     cell = tetrahedron
-    D = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
-    V = FunctionSpace(D, FiniteElement("Lagrange", cell, 2, (3, ), identity_pullback, H1))
+    D = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
+    V = FunctionSpace(D, FiniteElement("Lagrange", cell, 2, (3,), identity_pullback, H1))
     v = TestFunction(V)
     u = TrialFunction(V)
 
diff --git a/test/test_classcoverage.py b/test/test_classcoverage.py
index caeff1b91..522e2f999 100755
--- a/test/test_classcoverage.py
+++ b/test/test_classcoverage.py
@@ -2,19 +2,113 @@
 __date__ = "2008-09-06 -- 2009-02-10"
 
 import ufl
-from ufl import *  # noqa: F403, F401
-from ufl import (And, Argument, CellDiameter, CellVolume, Circumradius, Coefficient, Constant, FacetArea, FacetNormal,
-                 FunctionSpace, Identity, Jacobian, JacobianDeterminant, JacobianInverse, MaxFacetEdgeLength, Mesh,
-                 MinFacetEdgeLength, Not, Or, PermutationSymbol, SpatialCoordinate, TensorConstant, VectorConstant,
-                 acos, action, as_matrix, as_tensor, as_ufl, as_vector, asin, atan, cell_avg, cofac, conditional, cos,
-                 cosh, cross, curl, derivative, det, dev, diff, div, dot, ds, dS, dx, eq, exp, facet_avg, ge, grad, gt,
-                 i, inner, inv, j, k, l, le, ln, lt, nabla_div, nabla_grad, ne, outer, rot, sin, sinh, skew, sqrt, sym,
-                 tan, tanh, tetrahedron, tr, transpose, triangle, variable)
-from ufl.algorithms import *  # noqa: F403, F401
-from ufl.classes import *  # noqa: F403, F401
-from ufl.classes import (Acos, Asin, Atan, CellCoordinate, Cos, Cosh, Exp, Expr, FacetJacobian,
-                         FacetJacobianDeterminant, FacetJacobianInverse, FloatValue, IntValue, Ln, Outer, Sin, Sinh,
-                         Sqrt, Tan, Tanh, all_ufl_classes)
+from ufl import *  # noqa: F403
+from ufl import (
+    And,
+    Argument,
+    CellDiameter,
+    CellVolume,
+    Circumradius,
+    Coefficient,
+    Constant,
+    FacetArea,
+    FacetNormal,
+    FunctionSpace,
+    Identity,
+    Jacobian,
+    JacobianDeterminant,
+    JacobianInverse,
+    MaxFacetEdgeLength,
+    Mesh,
+    MinFacetEdgeLength,
+    Not,
+    Or,
+    PermutationSymbol,
+    SpatialCoordinate,
+    TensorConstant,
+    VectorConstant,
+    acos,
+    action,
+    as_matrix,
+    as_tensor,
+    as_ufl,
+    as_vector,
+    asin,
+    atan,
+    cell_avg,
+    cofac,
+    conditional,
+    cos,
+    cosh,
+    cross,
+    curl,
+    derivative,
+    det,
+    dev,
+    diff,
+    div,
+    dot,
+    dS,
+    ds,
+    dx,
+    eq,
+    exp,
+    facet_avg,
+    ge,
+    grad,
+    gt,
+    i,
+    inner,
+    inv,
+    j,
+    k,
+    l,
+    le,
+    ln,
+    lt,
+    nabla_div,
+    nabla_grad,
+    ne,
+    outer,
+    rot,
+    sin,
+    sinh,
+    skew,
+    sqrt,
+    sym,
+    tan,
+    tanh,
+    tetrahedron,
+    tr,
+    transpose,
+    triangle,
+    variable,
+)
+from ufl.algorithms import *  # noqa: F403
+from ufl.classes import *  # noqa: F403
+from ufl.classes import (
+    Acos,
+    Asin,
+    Atan,
+    CellCoordinate,
+    Cos,
+    Cosh,
+    Exp,
+    Expr,
+    FacetJacobian,
+    FacetJacobianDeterminant,
+    FacetJacobianInverse,
+    FloatValue,
+    IntValue,
+    Ln,
+    Outer,
+    Sin,
+    Sinh,
+    Sqrt,
+    Tan,
+    Tanh,
+    all_ufl_classes,
+)
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
@@ -25,9 +119,9 @@
 
 def _test_object(a, shape, free_indices):
     # Check if instances of this type has certain memory consuming members
-    if hasattr(a, '_repr'):
+    if hasattr(a, "_repr"):
         has_repr.add(a.__class__.__name__)
-    if hasattr(a, '__dict__'):
+    if hasattr(a, "__dict__"):
         has_dict.add(a.__class__.__name__)
 
     # Test reproduction via repr string
@@ -60,9 +154,9 @@ def _test_object(a, shape, free_indices):
 
 def _test_object2(a):
     # Check if instances of this type has certain memory consuming members
-    if hasattr(a, '_repr'):
+    if hasattr(a, "_repr"):
         has_repr.add(a.__class__.__name__)
-    if hasattr(a, '__dict__'):
+    if hasattr(a, "__dict__"):
         has_dict.add(a.__class__.__name__)
 
     # Test reproduction via repr string
@@ -92,8 +186,9 @@ def testExports(self):
             for c in list(vars(m).values()):
                 if isinstance(c, type) and issubclass(c, Expr):
                     all_expr_classes.append(c)
-    missing_classes = set(c.__name__ for c in all_expr_classes)\
-        - set(c.__name__ for c in all_ufl_classes)
+    missing_classes = set(c.__name__ for c in all_expr_classes) - set(
+        c.__name__ for c in all_ufl_classes
+    )
     if missing_classes:
         print("The following subclasses of Expr were not exported from ufl.classes:")
         print(("\n".join(sorted(missing_classes))))
@@ -101,7 +196,6 @@ def testExports(self):
 
 
 def testAll(self):
-
     Expr.ufl_enable_profiling()
 
     # --- Elements:
@@ -109,14 +203,14 @@ def testAll(self):
     dim = 2
 
     e0 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    e1 = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
+    e1 = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
     e2 = FiniteElement("Lagrange", cell, 1, (2, 2), identity_pullback, H1)
     e3 = MixedElement([e0, e1, e2])
 
-    e13D = FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1)
+    e13D = FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (dim, ), identity_pullback, H1))
-    domain3D = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (dim,), identity_pullback, H1))
+    domain3D = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     e0_space = FunctionSpace(domain, e0)
     e1_space = FunctionSpace(domain, e1)
     e2_space = FunctionSpace(domain, e2)
@@ -136,7 +230,7 @@ def testAll(self):
     _test_object(v0, (), ())
     _test_object(v1, (dim,), ())
     _test_object(v2, (dim, dim), ())
-    _test_object(v3, (1 + dim + dim ** 2, ), ())
+    _test_object(v3, (1 + dim + dim**2,), ())
 
     f0 = Coefficient(e0_space)
     f1 = Coefficient(e1_space)
@@ -146,7 +240,7 @@ def testAll(self):
     _test_object(f0, (), ())
     _test_object(f1, (dim,), ())
     _test_object(f2, (dim, dim), ())
-    _test_object(f3, (1 + dim + dim ** 2, ), ())
+    _test_object(f3, (1 + dim + dim**2,), ())
 
     c = Constant(domain)
     _test_object(c, (), ())
@@ -193,11 +287,11 @@ def testAll(self):
     _test_object(g, (dim, dim), ())
 
     g = FacetJacobian(domain)
-    _test_object(g, (dim, dim-1), ())
+    _test_object(g, (dim, dim - 1), ())
     g = FacetJacobianDeterminant(domain)
     _test_object(g, (), ())
     g = FacetJacobianInverse(domain)
-    _test_object(g, (dim-1, dim), ())
+    _test_object(g, (dim - 1, dim), ())
 
     g = FacetNormal(domain)
     _test_object(g, (dim,), ())
@@ -229,7 +323,7 @@ def testAll(self):
     a = variable(v2)
     _test_object(a, (dim, dim), ())
     a = variable(v3)
-    _test_object(a, (1 + dim + dim ** 2, ), ())
+    _test_object(a, (1 + dim + dim**2,), ())
     a = variable(f0)
     _test_object(a, (), ())
     a = variable(f1)
@@ -237,7 +331,7 @@ def testAll(self):
     a = variable(f2)
     _test_object(a, (dim, dim), ())
     a = variable(f3)
-    _test_object(a, (1 + dim + dim ** 2, ), ())
+    _test_object(a, (1 + dim + dim**2,), ())
 
     # a = MultiIndex()
 
@@ -290,7 +384,7 @@ def testAll(self):
     a = v2 + f2 + v2
     _test_object(a, (dim, dim), ())
     # a = Product()
-    a = 3*v0*(2.0*v0)*f0*(v0*3.0)
+    a = 3 * v0 * (2.0 * v0) * f0 * (v0 * 3.0)
     _test_object(a, (), ())
     # a = Division()
     a = v0 / 2.0
@@ -302,78 +396,76 @@ def testAll(self):
     # a = Power()
     a = f0**3
     _test_object(a, (), ())
-    a = (f0*2)**1.23
+    a = (f0 * 2) ** 1.23
     _test_object(a, (), ())
 
     # a = ListTensor()
-    a = as_vector([1.0, 2.0*f0, f0**2])
+    a = as_vector([1.0, 2.0 * f0, f0**2])
     _test_object(a, (3,), ())
-    a = as_matrix([[1.0, 2.0*f0, f0**2],
-                   [1.0, 2.0*f0, f0**2]])
+    a = as_matrix([[1.0, 2.0 * f0, f0**2], [1.0, 2.0 * f0, f0**2]])
     _test_object(a, (2, 3), ())
-    a = as_tensor([[[0.00, 0.01, 0.02],
-                    [0.10, 0.11, 0.12]],
-                   [[1.00, 1.01, 1.02],
-                    [1.10, 1.11, 1.12]]])
+    a = as_tensor(
+        [[[0.00, 0.01, 0.02], [0.10, 0.11, 0.12]], [[1.00, 1.01, 1.02], [1.10, 1.11, 1.12]]]
+    )
     _test_object(a, (2, 2, 3), ())
 
     # a = ComponentTensor()
-    a = as_vector(v1[i]*f1[j], i)
+    a = as_vector(v1[i] * f1[j], i)
     _test_object(a, (dim,), (j,))
-    a = as_matrix(v1[i]*f1[j], (j, i))
+    a = as_matrix(v1[i] * f1[j], (j, i))
     _test_object(a, (dim, dim), ())
-    a = as_tensor(v1[i]*f1[j], (i, j))
+    a = as_tensor(v1[i] * f1[j], (i, j))
     _test_object(a, (dim, dim), ())
-    a = as_tensor(v2[i, j]*f2[j, k], (i, k))
+    a = as_tensor(v2[i, j] * f2[j, k], (i, k))
     _test_object(a, (dim, dim), ())
 
     a = dev(v2)
     _test_object(a, (dim, dim), ())
     a = dev(f2)
     _test_object(a, (dim, dim), ())
-    a = dev(f2*f0+v2*3)
+    a = dev(f2 * f0 + v2 * 3)
     _test_object(a, (dim, dim), ())
 
     a = sym(v2)
     _test_object(a, (dim, dim), ())
     a = sym(f2)
     _test_object(a, (dim, dim), ())
-    a = sym(f2*f0+v2*3)
+    a = sym(f2 * f0 + v2 * 3)
     _test_object(a, (dim, dim), ())
 
     a = skew(v2)
     _test_object(a, (dim, dim), ())
     a = skew(f2)
     _test_object(a, (dim, dim), ())
-    a = skew(f2*f0+v2*3)
+    a = skew(f2 * f0 + v2 * 3)
     _test_object(a, (dim, dim), ())
 
     a = v2.T
     _test_object(a, (dim, dim), ())
     a = f2.T
     _test_object(a, (dim, dim), ())
-    a = transpose(f2*f0+v2*3)
+    a = transpose(f2 * f0 + v2 * 3)
     _test_object(a, (dim, dim), ())
 
     a = det(v2)
     _test_object(a, (), ())
     a = det(f2)
     _test_object(a, (), ())
-    a = det(f2*f0+v2*3)
+    a = det(f2 * f0 + v2 * 3)
     _test_object(a, (), ())
 
     a = tr(v2)
     _test_object(a, (), ())
     a = tr(f2)
     _test_object(a, (), ())
-    a = tr(f2*f0+v2*3)
+    a = tr(f2 * f0 + v2 * 3)
     _test_object(a, (), ())
 
     a = cofac(v2)
     _test_object(a, (dim, dim), ())
     a = cofac(f2)
     _test_object(a, (dim, dim), ())
-    a = cofac(f2*f0+v2*3)
+    a = cofac(f2 * f0 + v2 * 3)
     _test_object(a, (dim, dim), ())
 
     cond1 = le(f0, 1.0)
@@ -468,7 +560,7 @@ def testAll(self):
     s0 = variable(f0)
     s1 = variable(f1)
     s2 = variable(f2)
-    f = dot(s0*s1, s2)
+    f = dot(s0 * s1, s2)
     _test_object(s0, (), ())
     _test_object(s1, (dim,), ())
     _test_object(s2, (dim, dim), ())
@@ -477,7 +569,14 @@ def testAll(self):
     a = diff(f, s0)
     _test_object(a, (dim,), ())
     a = diff(f, s1)
-    _test_object(a, (dim, dim,), ())
+    _test_object(
+        a,
+        (
+            dim,
+            dim,
+        ),
+        (),
+    )
     a = diff(f, s2)
     _test_object(a, (dim, dim, dim), ())
 
@@ -500,9 +599,9 @@ def testAll(self):
     _test_object(a, (dim, dim), ())
     a = grad(f1)
     _test_object(a, (dim, dim), ())
-    a = grad(f0*v0)
+    a = grad(f0 * v0)
     _test_object(a, (dim,), ())
-    a = grad(f0*v1)
+    a = grad(f0 * v1)
     _test_object(a, (dim, dim), ())
 
     a = nabla_div(v1)
@@ -524,9 +623,9 @@ def testAll(self):
     _test_object(a, (dim, dim), ())
     a = nabla_grad(f1)
     _test_object(a, (dim, dim), ())
-    a = nabla_grad(f0*v0)
+    a = nabla_grad(f0 * v0)
     _test_object(a, (dim,), ())
-    a = nabla_grad(f0*v1)
+    a = nabla_grad(f0 * v1)
     _test_object(a, (dim, dim), ())
 
     a = curl(v13D)
@@ -540,16 +639,16 @@ def testAll(self):
 
     # a = PositiveRestricted(v0)
     # _test_object(a, (), ())
-    a = v0('+')
+    a = v0("+")
     _test_object(a, (), ())
-    a = v0('+')*f0
+    a = v0("+") * f0
     _test_object(a, (), ())
 
     # a = NegativeRestricted(v0)
     # _test_object(a, (), ())
-    a = v0('-')
+    a = v0("-")
     _test_object(a, (), ())
-    a = v0('-') + f0
+    a = v0("-") + f0
     _test_object(a, (), ())
 
     a = cell_avg(v0)
@@ -567,47 +666,47 @@ def testAll(self):
 
     # --- Integrals:
 
-    a = v0*dx
+    a = v0 * dx
     _test_form(a)
-    a = v0*dx(0)
+    a = v0 * dx(0)
     _test_form(a)
-    a = v0*dx(1)
+    a = v0 * dx(1)
     _test_form(a)
-    a = v0*ds
+    a = v0 * ds
     _test_form(a)
-    a = v0*ds(0)
+    a = v0 * ds(0)
     _test_form(a)
-    a = v0*ds(1)
+    a = v0 * ds(1)
     _test_form(a)
-    a = v0*dS
+    a = v0 * dS
     _test_form(a)
-    a = v0*dS(0)
+    a = v0 * dS(0)
     _test_form(a)
-    a = v0*dS(1)
+    a = v0 * dS(1)
     _test_form(a)
 
-    a = v0*dot(v1, f1)*dx
+    a = v0 * dot(v1, f1) * dx
     _test_form(a)
-    a = v0*dot(v1, f1)*dx(0)
+    a = v0 * dot(v1, f1) * dx(0)
     _test_form(a)
-    a = v0*dot(v1, f1)*dx(1)
+    a = v0 * dot(v1, f1) * dx(1)
     _test_form(a)
-    a = v0*dot(v1, f1)*ds
+    a = v0 * dot(v1, f1) * ds
     _test_form(a)
-    a = v0*dot(v1, f1)*ds(0)
+    a = v0 * dot(v1, f1) * ds(0)
     _test_form(a)
-    a = v0*dot(v1, f1)*ds(1)
+    a = v0 * dot(v1, f1) * ds(1)
     _test_form(a)
-    a = v0*dot(v1, f1)*dS
+    a = v0 * dot(v1, f1) * dS
     _test_form(a)
-    a = v0*dot(v1, f1)*dS(0)
+    a = v0 * dot(v1, f1) * dS(0)
     _test_form(a)
-    a = v0*dot(v1, f1)*dS(1)
+    a = v0 * dot(v1, f1) * dS(1)
     _test_form(a)
 
     # --- Form transformations:
 
-    a = f0*v0*dx + f0*v0*dot(f1, v1)*dx
+    a = f0 * v0 * dx + f0 * v0 * dot(f1, v1) * dx
     # b = lhs(a) # TODO
     # c = rhs(a) # TODO
     d = derivative(a, f1, v1)
diff --git a/test/test_complex.py b/test/test_complex.py
index 6f3eda840..d91d0911c 100755
--- a/test/test_complex.py
+++ b/test/test_complex.py
@@ -2,9 +2,38 @@
 
 import pytest
 
-from ufl import (Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, as_tensor, as_ufl, atan, conditional,
-                 conj, cos, cosh, dot, dx, exp, ge, grad, gt, imag, inner, le, ln, lt, max_value, min_value, outer,
-                 real, sin, sqrt, triangle)
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    as_tensor,
+    as_ufl,
+    atan,
+    conditional,
+    conj,
+    cos,
+    cosh,
+    dot,
+    dx,
+    exp,
+    ge,
+    grad,
+    gt,
+    imag,
+    inner,
+    le,
+    ln,
+    lt,
+    max_value,
+    min_value,
+    outer,
+    real,
+    sin,
+    sqrt,
+    triangle,
+)
 from ufl.algebra import Conj, Imag, Real
 from ufl.algorithms import estimate_total_polynomial_degree
 from ufl.algorithms.apply_algebra_lowering import apply_algebra_lowering
@@ -18,8 +47,8 @@
 
 
 def test_conj(self):
-    z1 = ComplexValue(1+2j)
-    z2 = ComplexValue(1-2j)
+    z1 = ComplexValue(1 + 2j)
+    z2 = ComplexValue(1 - 2j)
 
     assert z1 == Conj(z2)
     assert z2 == Conj(z1)
@@ -29,7 +58,7 @@ def test_real(self):
     z0 = Zero()
     z1 = as_ufl(1.0)
     z2 = ComplexValue(1j)
-    z3 = ComplexValue(1+1j)
+    z3 = ComplexValue(1 + 1j)
     assert Real(z1) == z1
     assert Real(z3) == z1
     assert Real(z2) == z0
@@ -39,7 +68,7 @@ def test_imag(self):
     z0 = Zero()
     z1 = as_ufl(1.0)
     z2 = as_ufl(1j)
-    z3 = ComplexValue(1+1j)
+    z3 = ComplexValue(1 + 1j)
 
     assert Imag(z2) == z1
     assert Imag(z3) == z1
@@ -48,8 +77,8 @@ def test_imag(self):
 
 def test_compute_form_adjoint(self):
     cell = triangle
-    element = FiniteElement('Lagrange', cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     u = TrialFunction(space)
@@ -62,23 +91,28 @@ def test_compute_form_adjoint(self):
 
 def test_complex_algebra(self):
     z1 = ComplexValue(1j)
-    z2 = ComplexValue(1+1j)
-
-    # Remember that ufl.algebra functions return ComplexValues, but ufl.mathfunctions return complex Python scalar
-    # Any operations with a ComplexValue and a complex Python scalar promote to ComplexValue
-    assert z1*z2 == ComplexValue(-1+1j)
-    assert z2/z1 == ComplexValue(1-1j)
-    assert pow(z2, z1) == ComplexValue((1+1j)**1j)
-    assert sqrt(z2) * as_ufl(1) == ComplexValue(cmath.sqrt(1+1j))
+    z2 = ComplexValue(1 + 1j)
+
+    # Remember that ufl.algebra functions return ComplexValues, but
+    # ufl.mathfunctions return complex Python scalar
+    # Any operations with a ComplexValue and a complex Python scalar
+    # promote to ComplexValue
+    assert z1 * z2 == ComplexValue(-1 + 1j)
+    assert z2 / z1 == ComplexValue(1 - 1j)
+    assert pow(z2, z1) == ComplexValue((1 + 1j) ** 1j)
+    assert sqrt(z2) * as_ufl(1) == ComplexValue(cmath.sqrt(1 + 1j))
     assert (sin(z2) + cosh(z2) - atan(z2)) * z1 == ComplexValue(
-        (cmath.sin(1+1j) + cmath.cosh(1+1j) - cmath.atan(1+1j))*1j)
-    assert (abs(z2) - ln(z2))/exp(z1) == ComplexValue((abs(1+1j) - cmath.log(1+1j))/cmath.exp(1j))
+        (cmath.sin(1 + 1j) + cmath.cosh(1 + 1j) - cmath.atan(1 + 1j)) * 1j
+    )
+    assert (abs(z2) - ln(z2)) / exp(z1) == ComplexValue(
+        (abs(1 + 1j) - cmath.log(1 + 1j)) / cmath.exp(1j)
+    )
 
 
 def test_automatic_simplification(self):
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -92,7 +126,7 @@ def test_automatic_simplification(self):
 def test_apply_algebra_lowering_complex(self):
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -115,13 +149,15 @@ def test_apply_algebra_lowering_complex(self):
     assert lowered_a == gu[lowered_a_index] * gv[lowered_a_index]
     assert lowered_b == gv[lowered_b_index] * conj(gu[lowered_b_index])
     assert lowered_c == as_tensor(
-        conj(gu[lowered_c_indices[0]]) * gv[lowered_c_indices[1]], (lowered_c_indices[0],) + (lowered_c_indices[1],))
+        conj(gu[lowered_c_indices[0]]) * gv[lowered_c_indices[1]],
+        (lowered_c_indices[0],) + (lowered_c_indices[1],),
+    )
 
 
 def test_remove_complex_nodes(self):
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     u = TrialFunction(space)
@@ -131,7 +167,7 @@ def test_remove_complex_nodes(self):
     a = conj(v)
     b = real(u)
     c = imag(f)
-    d = conj(real(v))*imag(conj(u))
+    d = conj(real(v)) * imag(conj(u))
 
     assert remove_complex_nodes(a) == v
     assert remove_complex_nodes(b) == u
@@ -144,7 +180,7 @@ def test_remove_complex_nodes(self):
 def test_comparison_checker(self):
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     u = TrialFunction(space)
@@ -172,7 +208,7 @@ def test_comparison_checker(self):
 def test_complex_degree_handling(self):
     cell = triangle
     element = FiniteElement("Lagrange", cell, 3, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
diff --git a/test/test_conditionals.py b/test/test_conditionals.py
index 7b60054d5..8b7980d2d 100755
--- a/test/test_conditionals.py
+++ b/test/test_conditionals.py
@@ -13,7 +13,7 @@
 @pytest.fixture
 def f():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     return Coefficient(space)
 
@@ -21,7 +21,7 @@ def f():
 @pytest.fixture
 def g():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     return Coefficient(space)
 
diff --git a/test/test_degree_estimation.py b/test/test_degree_estimation.py
index dbadffef6..6101db9ee 100755
--- a/test/test_degree_estimation.py
+++ b/test/test_degree_estimation.py
@@ -1,8 +1,26 @@
 __authors__ = "Martin Sandve Alnæs"
 __date__ = "2008-03-12 -- 2009-01-28"
 
-from ufl import (Argument, Coefficient, Coefficients, FacetNormal, FunctionSpace, Mesh, SpatialCoordinate, cos, div,
-                 dot, grad, i, inner, nabla_div, nabla_grad, sin, tan, triangle)
+from ufl import (
+    Argument,
+    Coefficient,
+    Coefficients,
+    FacetNormal,
+    FunctionSpace,
+    Mesh,
+    SpatialCoordinate,
+    cos,
+    div,
+    dot,
+    grad,
+    i,
+    inner,
+    nabla_div,
+    nabla_grad,
+    sin,
+    tan,
+    triangle,
+)
 from ufl.algorithms import estimate_total_polynomial_degree
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import identity_pullback
@@ -12,10 +30,10 @@
 def test_total_degree_estimation():
     V1 = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V2 = FiniteElement("Lagrange", triangle, 2, (), identity_pullback, H1)
-    VV = FiniteElement("Lagrange", triangle, 3, (2, ), identity_pullback, H1)
+    VV = FiniteElement("Lagrange", triangle, 3, (2,), identity_pullback, H1)
     VM = MixedElement([V1, V2])
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
     v1_space = FunctionSpace(domain, V1)
     v2_space = FunctionSpace(domain, V2)
@@ -31,8 +49,8 @@ def test_total_degree_estimation():
     x, y = SpatialCoordinate(domain)
     assert estimate_total_polynomial_degree(x) == 1
     assert estimate_total_polynomial_degree(x * y) == 2
-    assert estimate_total_polynomial_degree(x ** 3) == 3
-    assert estimate_total_polynomial_degree(x ** 3) == 3
+    assert estimate_total_polynomial_degree(x**3) == 3
+    assert estimate_total_polynomial_degree(x**3) == 3
     assert estimate_total_polynomial_degree((x - 1) ** 4) == 4
 
     assert estimate_total_polynomial_degree(vv[0]) == 3
@@ -59,7 +77,7 @@ def test_total_degree_estimation():
 
     assert estimate_total_polynomial_degree(f2 + 3) == 2
     assert estimate_total_polynomial_degree(f2 * 3) == 2
-    assert estimate_total_polynomial_degree(f2 ** 3) == 6
+    assert estimate_total_polynomial_degree(f2**3) == 6
     assert estimate_total_polynomial_degree(f2 / 3) == 2
     assert estimate_total_polynomial_degree(f2 / v2) == 4
     assert estimate_total_polynomial_degree(f2 / (x - 1)) == 3
@@ -70,15 +88,15 @@ def test_total_degree_estimation():
     assert estimate_total_polynomial_degree(f2 * v2.dx(0) * v1.dx(0)) == 2 + 1
 
     assert estimate_total_polynomial_degree(f2) == 2
-    assert estimate_total_polynomial_degree(f2 ** 2) == 4
-    assert estimate_total_polynomial_degree(f2 ** 3) == 6
-    assert estimate_total_polynomial_degree(f2 ** 3 * v1) == 7
-    assert estimate_total_polynomial_degree(f2 ** 3 * v1 + f1 * v1) == 7
+    assert estimate_total_polynomial_degree(f2**2) == 4
+    assert estimate_total_polynomial_degree(f2**3) == 6
+    assert estimate_total_polynomial_degree(f2**3 * v1) == 7
+    assert estimate_total_polynomial_degree(f2**3 * v1 + f1 * v1) == 7
 
     # Math functions of constant values are constant values
     nx, ny = FacetNormal(domain)
-    e = nx ** 2
-    for f in [sin, cos, tan, abs, lambda z:z**7]:
+    e = nx**2
+    for f in [sin, cos, tan, abs, lambda z: z**7]:
         assert estimate_total_polynomial_degree(f(e)) == 0
 
     # Based on the arbitrary chosen math function heuristics...
@@ -89,7 +107,6 @@ def test_total_degree_estimation():
 
 
 def test_some_compound_types():
-
     # NB! Although some compound types are supported here,
     # some derivatives and compounds must be preprocessed
     # prior to degree estimation. In generic code, this algorithm
@@ -98,8 +115,8 @@ def test_some_compound_types():
     etpd = estimate_total_polynomial_degree
 
     P2 = FiniteElement("Lagrange", triangle, 2, (), identity_pullback, H1)
-    V2 = FiniteElement("Lagrange", triangle, 2, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    V2 = FiniteElement("Lagrange", triangle, 2, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
     u = Coefficient(FunctionSpace(domain, P2))
     v = Coefficient(FunctionSpace(domain, V2))
diff --git a/test/test_derivative.py b/test/test_derivative.py
index fc8bfdd76..cce955a12 100755
--- a/test/test_derivative.py
+++ b/test/test_derivative.py
@@ -3,11 +3,58 @@
 
 from itertools import chain
 
-from ufl import (CellDiameter, CellVolume, Circumradius, Coefficient, Constant, FacetArea, FacetNormal, FunctionSpace,
-                 Identity, Index, Jacobian, JacobianInverse, Mesh, SpatialCoordinate, TestFunction, TrialFunction, acos,
-                 as_matrix, as_tensor, as_vector, asin, atan, conditional, cos, derivative, diff, dot, dx, exp, i,
-                 indices, inner, interval, j, k, ln, lt, nabla_grad, outer, quadrilateral, replace, sign, sin, split,
-                 sqrt, tan, tetrahedron, triangle, variable, zero)
+from ufl import (
+    CellDiameter,
+    CellVolume,
+    Circumradius,
+    Coefficient,
+    Constant,
+    FacetArea,
+    FacetNormal,
+    FunctionSpace,
+    Identity,
+    Index,
+    Jacobian,
+    JacobianInverse,
+    Mesh,
+    SpatialCoordinate,
+    TestFunction,
+    TrialFunction,
+    acos,
+    as_matrix,
+    as_tensor,
+    as_vector,
+    asin,
+    atan,
+    conditional,
+    cos,
+    derivative,
+    diff,
+    dot,
+    dx,
+    exp,
+    i,
+    indices,
+    inner,
+    interval,
+    j,
+    k,
+    ln,
+    lt,
+    nabla_grad,
+    outer,
+    quadrilateral,
+    replace,
+    sign,
+    sin,
+    split,
+    sqrt,
+    tan,
+    tetrahedron,
+    triangle,
+    variable,
+    zero,
+)
 from ufl.algorithms import compute_form_data, expand_indices, strip_variables
 from ufl.algorithms.apply_algebra_lowering import apply_algebra_lowering
 from ufl.algorithms.apply_derivatives import apply_derivatives
@@ -21,13 +68,14 @@
 
 
 def assertEqualBySampling(actual, expected):
-    ad = compute_form_data(actual*dx)
+    ad = compute_form_data(actual * dx)
     a = ad.preprocessed_form.integrals_by_type("cell")[0].integrand()
-    bd = compute_form_data(expected*dx)
+    bd = compute_form_data(expected * dx)
     b = bd.preprocessed_form.integrals_by_type("cell")[0].integrand()
 
-    assert ([ad.function_replace_map[ac] for ac in ad.reduced_coefficients]
-            == [bd.function_replace_map[bc] for bc in bd.reduced_coefficients])
+    assert [ad.function_replace_map[ac] for ac in ad.reduced_coefficients] == [
+        bd.function_replace_map[bc] for bc in bd.reduced_coefficients
+    ]
 
     n = ad.num_coefficients
 
@@ -45,8 +93,14 @@ def make_value(c):
         else:
             raise NotImplementedError("Tensor valued expressions not supported here.")
 
-    amapping = dict((c, make_value(c)) for c in chain(ad.original_form.coefficients(), ad.original_form.arguments()))
-    bmapping = dict((c, make_value(c)) for c in chain(bd.original_form.coefficients(), bd.original_form.arguments()))
+    amapping = dict(
+        (c, make_value(c))
+        for c in chain(ad.original_form.coefficients(), ad.original_form.arguments())
+    )
+    bmapping = dict(
+        (c, make_value(c))
+        for c in chain(bd.original_form.coefficients(), bd.original_form.arguments())
+    )
     adomain = extract_unique_domain(actual)
     bdomain = extract_unique_domain(expected)
     acell = adomain.ufl_cell()
@@ -77,7 +131,7 @@ def make_value(c):
 def _test(self, f, df):
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -97,12 +151,13 @@ def _test(self, f, df):
     dfv2 = dfv2(x, mapping)
     assert dfv1 == dfv2
 
-    dfv1 = derivative(f(7*w), w, v)
-    dfv2 = 7*df(7*w, v)
+    dfv1 = derivative(f(7 * w), w, v)
+    dfv2 = 7 * df(7 * w, v)
     dfv1 = dfv1(x, mapping)
     dfv2 = dfv2(x, mapping)
     assert dfv1 == dfv2
 
+
 # --- Literals
 
 
@@ -125,6 +180,7 @@ def df(w, v):
 
     _test(self, f, df)
 
+
 # --- Form arguments
 
 
@@ -140,21 +196,27 @@ def df(w, v):
 
 def testArgument(self):
     def f(w):
-        return TestFunction(FunctionSpace(
-            Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)),
-            FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)))
+        return TestFunction(
+            FunctionSpace(
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+                FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1),
+            )
+        )
 
     def df(w, v):
         return zero()
+
     _test(self, f, df)
 
+
 # --- Geometry
 
 
 def testSpatialCoordinate(self):
     def f(w):
         return SpatialCoordinate(
-            Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)))[0]
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
+        )[0]
 
     def df(w, v):
         return zero()
@@ -165,7 +227,8 @@ def df(w, v):
 def testFacetNormal(self):
     def f(w):
         return FacetNormal(
-            Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)))[0]
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
+        )[0]
 
     def df(w, v):
         return zero()
@@ -175,8 +238,7 @@ def df(w, v):
 
 def testFacetArea(self):
     def f(w):
-        return FacetArea(
-            Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)))
+        return FacetArea(Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)))
 
     def df(w, v):
         return zero()
@@ -187,7 +249,8 @@ def df(w, v):
 def testCellDiameter(self):
     def f(w):
         return CellDiameter(
-            Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)))
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
+        )
 
     def df(w, v):
         return zero()
@@ -197,22 +260,26 @@ def df(w, v):
 
 def testCircumradius(self):
     def f(w):
-        return Circumradius(Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)))
+        return Circumradius(
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
+        )
 
     def df(w, v):
         return zero()
+
     _test(self, f, df)
 
 
 def testCellVolume(self):
     def f(w):
-        return CellVolume(Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)))
+        return CellVolume(Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)))
 
     def df(w, v):
         return zero()
 
     _test(self, f, df)
 
+
 # --- Basic operators
 
 
@@ -228,10 +295,10 @@ def df(w, v):
 
 def testProduct(self):
     def f(w):
-        return 3*w
+        return 3 * w
 
     def df(w, v):
-        return 3*v
+        return 3 * v
 
     _test(self, f, df)
 
@@ -241,7 +308,7 @@ def f(w):
         return w**3
 
     def df(w, v):
-        return 3*w**2*v
+        return 3 * w**2 * v
 
     _test(self, f, df)
 
@@ -271,7 +338,7 @@ def f(w):
         return exp(w)
 
     def df(w, v):
-        return v*exp(w)
+        return v * exp(w)
 
     _test(self, f, df)
 
@@ -291,7 +358,7 @@ def f(w):
         return cos(w)
 
     def df(w, v):
-        return -v*sin(w)
+        return -v * sin(w)
 
     _test(self, f, df)
 
@@ -301,7 +368,7 @@ def f(w):
         return sin(w)
 
     def df(w, v):
-        return v*cos(w)
+        return v * cos(w)
 
     _test(self, f, df)
 
@@ -311,27 +378,27 @@ def f(w):
         return tan(w)
 
     def df(w, v):
-        return v*2.0/(cos(2.0*w) + 1.0)
+        return v * 2.0 / (cos(2.0 * w) + 1.0)
 
     _test(self, f, df)
 
 
 def testAcos(self):
     def f(w):
-        return acos(w/1000)
+        return acos(w / 1000)
 
     def df(w, v):
-        return -(v/1000)/sqrt(1.0 - (w/1000)**2)
+        return -(v / 1000) / sqrt(1.0 - (w / 1000) ** 2)
 
     _test(self, f, df)
 
 
 def testAsin(self):
     def f(w):
-        return asin(w/1000)
+        return asin(w / 1000)
 
     def df(w, v):
-        return (v/1000)/sqrt(1.0 - (w/1000)**2)
+        return (v / 1000) / sqrt(1.0 - (w / 1000) ** 2)
 
     _test(self, f, df)
 
@@ -341,10 +408,11 @@ def f(w):
         return atan(w)
 
     def df(w, v):
-        return v/(1.0 + w**2)
+        return v / (1.0 + w**2)
 
     _test(self, f, df)
 
+
 # FIXME: Add the new erf and bessel_*
 
 # --- Abs and conditionals
@@ -355,7 +423,7 @@ def f(w):
         return abs(w)
 
     def df(w, v):
-        return sign(w)*v
+        return sign(w) * v
 
     _test(self, f, df)
 
@@ -365,14 +433,14 @@ def cond(w):
         return lt(w, 1.0)
 
     def f(w):
-        return conditional(cond(w), 2*w, 3*w)
+        return conditional(cond(w), 2 * w, 3 * w)
 
     def df(w, v):
-        return (conditional(cond(w), 1, 0) * 2*v +
-                conditional(cond(w), 0, 1) * 3*v)
+        return conditional(cond(w), 1, 0) * 2 * v + conditional(cond(w), 0, 1) * 3 * v
 
     _test(self, f, df)
 
+
 # --- Tensor algebra basics
 
 
@@ -381,28 +449,32 @@ def f(w):
         # 3*w + 4*w**2 + 5*w**3
         a = as_vector((w, w**2, w**3))
         b = as_vector((3, 4, 5))
-        i, = indices(1)
-        return a[i]*b[i]
+        (i,) = indices(1)
+        return a[i] * b[i]
 
     def df(w, v):
-        return 3*v + 4*2*w*v + 5*3*w**2*v
+        return 3 * v + 4 * 2 * w * v + 5 * 3 * w**2 * v
 
     _test(self, f, df)
 
 
 def testListTensor(self):
     v = variable(as_ufl(42))
-    f = as_tensor((
-        ((0, 0), (0, 0)),
-        ((v, 2*v), (0, 0)),
-        ((v**2, 1), (2, v/2)),
-    ))
+    f = as_tensor(
+        (
+            ((0, 0), (0, 0)),
+            ((v, 2 * v), (0, 0)),
+            ((v**2, 1), (2, v / 2)),
+        )
+    )
     assert f.ufl_shape == (3, 2, 2)
-    g = as_tensor((
-        ((0, 0), (0, 0)),
-        ((1, 2), (0, 0)),
-        ((84, 0), (0, 0.5)),
-    ))
+    g = as_tensor(
+        (
+            ((0, 0), (0, 0)),
+            ((1, 2), (0, 0)),
+            ((84, 0), (0, 0.5)),
+        )
+    )
     assert g.ufl_shape == (3, 2, 2)
     dfv = diff(f, v)
     x = None
@@ -411,40 +483,41 @@ def testListTensor(self):
             for c in range(2):
                 self.assertEqual(dfv[a, b, c](x), g[a, b, c](x))
 
+
 # --- Coefficient and argument input configurations
 
 
 def test_single_scalar_coefficient_derivative(self):
     cell = triangle
     V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     u = Coefficient(space)
     v = TestFunction(space)
-    a = 3*u**2
+    a = 3 * u**2
     b = derivative(a, u, v)
-    self.assertEqualAfterPreprocessing(b, 3*(u*(2*v)))
+    self.assertEqualAfterPreprocessing(b, 3 * (u * (2 * v)))
 
 
 def test_single_vector_coefficient_derivative(self):
     cell = triangle
-    V = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    V = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     u = Coefficient(space)
     v = TestFunction(space)
-    a = 3*dot(u, u)
+    a = 3 * dot(u, u)
     actual = derivative(a, u, v)
-    expected = 3*(2*(u[i]*v[i]))
+    expected = 3 * (2 * (u[i] * v[i]))
     assertEqualBySampling(actual, expected)
 
 
 def test_multiple_coefficient_derivative(self):
     cell = triangle
     V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    W = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
+    W = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
     M = MixedElement([V, W])
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     w_space = FunctionSpace(domain, W)
     m_space = FunctionSpace(domain, M)
@@ -453,14 +526,14 @@ def test_multiple_coefficient_derivative(self):
     v = TestFunction(m_space)
     vv, vw = split(v)
 
-    a = sin(uv)*dot(uw, uw)
+    a = sin(uv) * dot(uw, uw)
 
     actual = derivative(a, (uv, uw), split(v))
-    expected = cos(uv)*vv * (uw[i]*uw[i]) + (uw[j]*vw[j])*2 * sin(uv)
+    expected = cos(uv) * vv * (uw[i] * uw[i]) + (uw[j] * vw[j]) * 2 * sin(uv)
     assertEqualBySampling(actual, expected)
 
     actual = derivative(a, (uv, uw), v)
-    expected = cos(uv)*vv * (uw[i]*uw[i]) + (uw[j]*vw[j])*2 * sin(uv)
+    expected = cos(uv) * vv * (uw[i] * uw[i]) + (uw[j] * vw[j]) * 2 * sin(uv)
     assertEqualBySampling(actual, expected)
 
 
@@ -468,8 +541,8 @@ def test_indexed_coefficient_derivative(self):
     cell = triangle
     ident = Identity(2)
     V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    W = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    W = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     w_space = FunctionSpace(domain, W)
     u = Coefficient(w_space)
@@ -477,11 +550,11 @@ def test_indexed_coefficient_derivative(self):
 
     w = dot(u, nabla_grad(u))
     # a = dot(w, w)
-    a = (u[i]*u[k].dx(i)) * w[k]
+    a = (u[i] * u[k].dx(i)) * w[k]
 
     actual = derivative(a, u[0], v)
 
-    dw = v*u[k].dx(0) + u[i]*ident[0, k]*v.dx(i)
+    dw = v * u[k].dx(0) + u[i] * ident[0, k] * v.dx(i)
     expected = 2 * w[k] * dw
 
     assertEqualBySampling(actual, expected)
@@ -491,8 +564,8 @@ def test_multiple_indexed_coefficient_derivative(self):
     cell = tetrahedron
     V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
     V2 = MixedElement([V, V])
-    W = FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
+    W = FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
     v2_space = FunctionSpace(domain, V2)
     w_space = FunctionSpace(domain, W)
     u = Coefficient(w_space)
@@ -500,8 +573,8 @@ def test_multiple_indexed_coefficient_derivative(self):
     v = TestFunction(v2_space)
     vu, vw = split(v)
 
-    actual = derivative(cos(u[i]*w[i]), (u[2], w[1]), (vu, vw))
-    expected = -sin(u[i]*w[i])*(vu*w[2] + u[1]*vw)
+    actual = derivative(cos(u[i] * w[i]), (u[2], w[1]), (vu, vw))
+    expected = -sin(u[i] * w[i]) * (vu * w[2] + u[1] * vw)
 
     assertEqualBySampling(actual, expected)
 
@@ -509,9 +582,9 @@ def test_multiple_indexed_coefficient_derivative(self):
 def test_segregated_derivative_of_convection(self):
     cell = tetrahedron
     V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    W = FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1)
+    W = FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     w_space = FunctionSpace(domain, W)
 
@@ -531,7 +604,7 @@ def test_segregated_derivative_of_convection(self):
 
     for a in range(3):
         for b in range(3):
-            form = Lvu[a, b]*dx
+            form = Lvu[a, b] * dx
             fd = compute_form_data(form)
             pf = fd.preprocessed_form
             expand_indices(pf)
@@ -540,16 +613,17 @@ def test_segregated_derivative_of_convection(self):
     for a in range(3):
         for b in range(3):
             actual = Lvu[a, b]
-            expected = du*u[a].dx(b)*dv + u[k]*du.dx(k)*dv
+            expected = du * u[a].dx(b) * dv + u[k] * du.dx(k) * dv
             assertEqualBySampling(actual, expected)
 
+
 # --- User provided derivatives of coefficients
 
 
 def test_coefficient_derivatives(self):
     V = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
 
     dv = TestFunction(space)
@@ -562,21 +636,21 @@ def test_coefficient_derivatives(self):
     cd = {f: df, g: dg}
 
     integrand = inner(f, g)
-    expected = (df*dv)*g + f*(dg*dv)
+    expected = (df * dv) * g + f * (dg * dv)
 
-    F = integrand*dx
+    F = integrand * dx
     J = derivative(F, u, dv, cd)
     fd = compute_form_data(J)
     actual = fd.preprocessed_form.integrals()[0].integrand()
-    assert (actual*dx).signature() == (expected*dx).signature()
+    assert (actual * dx).signature() == (expected * dx).signature()
     self.assertEqual(replace(actual, fd.function_replace_map), expected)
 
 
 def test_vector_coefficient_scalar_derivatives(self):
     V = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    VV = FiniteElement("vector Lagrange", triangle, 1, (2, ), identity_pullback, H1)
+    VV = FiniteElement("vector Lagrange", triangle, 1, (2,), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     vv_space = FunctionSpace(domain, VV)
 
@@ -591,20 +665,20 @@ def test_vector_coefficient_scalar_derivatives(self):
     integrand = inner(f, g)
 
     i0, i1, i2, i3, i4 = [Index(count=c) for c in range(5)]
-    expected = as_tensor(df[i1]*dv, (i1,))[i0]*g[i0]
+    expected = as_tensor(df[i1] * dv, (i1,))[i0] * g[i0]
 
-    F = integrand*dx
+    F = integrand * dx
     J = derivative(F, u, dv, cd)
     fd = compute_form_data(J)
     actual = fd.preprocessed_form.integrals()[0].integrand()
-    assert (actual*dx).signature() == (expected*dx).signature()
+    assert (actual * dx).signature() == (expected * dx).signature()
 
 
 def test_vector_coefficient_derivatives(self):
-    V = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
+    V = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
     VV = FiniteElement("Lagrange", triangle, 1, (2, 2), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     vv_space = FunctionSpace(domain, VV)
 
@@ -619,21 +693,21 @@ def test_vector_coefficient_derivatives(self):
     integrand = inner(f, g)
 
     i0, i1, i2, i3, i4 = [Index(count=c) for c in range(5)]
-    expected = as_tensor(df[i2, i1]*dv[i1], (i2,))[i0]*g[i0]
+    expected = as_tensor(df[i2, i1] * dv[i1], (i2,))[i0] * g[i0]
 
-    F = integrand*dx
+    F = integrand * dx
     J = derivative(F, u, dv, cd)
     fd = compute_form_data(J)
     actual = fd.preprocessed_form.integrals()[0].integrand()
-    assert (actual*dx).signature() == (expected*dx).signature()
+    assert (actual * dx).signature() == (expected * dx).signature()
     # self.assertEqual(replace(actual, fd.function_replace_map), expected)
 
 
 def test_vector_coefficient_derivatives_of_product(self):
-    V = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
+    V = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
     VV = FiniteElement("Lagrange", triangle, 1, (2, 2), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     vv_space = FunctionSpace(domain, VV)
 
@@ -646,13 +720,15 @@ def test_vector_coefficient_derivatives_of_product(self):
     u = Coefficient(v_space, count=4)
     cd = {f: df, g: dg}
 
-    integrand = f[i]*g[i]
+    integrand = f[i] * g[i]
 
     i0, i1, i2, i3, i4 = [Index(count=c) for c in range(5)]
-    expected = as_tensor(df[i2, i1]*dv[i1], (i2,))[i0]*g[i0] +\
-        f[i0]*as_tensor(dg[i4, i3]*dv[i3], (i4,))[i0]
+    expected = (
+        as_tensor(df[i2, i1] * dv[i1], (i2,))[i0] * g[i0]
+        + f[i0] * as_tensor(dg[i4, i3] * dv[i3], (i4,))[i0]
+    )
 
-    F = integrand*dx
+    F = integrand * dx
     J = derivative(F, u, dv, cd)
     fd = compute_form_data(J)
     actual = fd.preprocessed_form.integrals()[0].integrand()
@@ -666,13 +742,14 @@ def test_vector_coefficient_derivatives_of_product(self):
 
     # TODO: Add tests covering more cases, in particular mixed stuff
 
+
 # --- Some actual forms
 
 
 def testHyperElasticity(self):
     cell = interval
     element = FiniteElement("Lagrange", cell, 2, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (1, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (1,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     w = Coefficient(space)
     v = TestFunction(space)
@@ -686,10 +763,10 @@ def testHyperElasticity(self):
 
     E = dw + dw**2 / 2
     E = variable(E)
-    Q = b*E**2
-    psi = K*(exp(Q)-1)
+    Q = b * E**2
+    psi = K * (exp(Q) - 1)
 
-    f = psi*dx
+    f = psi * dx
     F = derivative(f, w, v)
     J = derivative(F, w, u)
 
@@ -707,18 +784,18 @@ def testHyperElasticity(self):
 
     # classes = set(c.__class__ for c in post_traversal(f_expression))
 
-    Kv = .2
-    bv = .3
-    dw = .5
-    dv = .7
-    du = .11
-    E = dw + dw**2 / 2.
-    Q = bv*E**2
+    Kv = 0.2
+    bv = 0.3
+    dw = 0.5
+    dv = 0.7
+    du = 0.11
+    E = dw + dw**2 / 2.0
+    Q = bv * E**2
     expQ = float(exp(Q))
-    psi = Kv*(expQ-1)
+    psi = Kv * (expQ - 1)
     fv = psi
-    Fv = 2*Kv*bv*E*(1+dw)*expQ*dv
-    Jv = 2*Kv*bv*expQ*dv*du*(E + (1+dw)**2*(2*bv*E**2 + 1))
+    Fv = 2 * Kv * bv * E * (1 + dw) * expQ * dv
+    Jv = 2 * Kv * bv * expQ * dv * du * (E + (1 + dw) ** 2 * (2 * bv * E**2 + 1))
 
     def Nv(x, derivatives):
         assert derivatives == (0,)
@@ -736,7 +813,7 @@ def Nw(x, derivatives):
     fv2 = f_expression((0,), mapping)
     self.assertAlmostEqual(fv, fv2)
 
-    v, = form_data_F.original_form.arguments()
+    (v,) = form_data_F.original_form.arguments()
     mapping = {K: Kv, b: bv, v: Nv, w: Nw}
     Fv2 = F_expression((0,), mapping)
     self.assertAlmostEqual(Fv, Fv2)
@@ -751,21 +828,22 @@ def test_mass_derived_from_functional(self):
     cell = triangle
     V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
 
     v = TestFunction(space)
     u = TrialFunction(space)
     w = Coefficient(space)
 
-    f = (w**2/2)*dx
-    L = w*v*dx
-    a = u*v*dx  # noqa: F841
+    f = (w**2 / 2) * dx
+    L = w * v * dx
+    # a = u*v*dx
     F = derivative(f, w, v)
-    J1 = derivative(L, w, u)  # noqa: F841
-    J2 = derivative(F, w, u)  # noqa: F841
+    derivative(L, w, u)
+    derivative(F, w, u)
     # TODO: assert something
 
+
 # --- Interaction with replace
 
 
@@ -773,7 +851,7 @@ def test_derivative_replace_works_together(self):
     cell = triangle
     V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
 
     v = TestFunction(space)
@@ -781,14 +859,14 @@ def test_derivative_replace_works_together(self):
     f = Coefficient(space)
     g = Coefficient(space)
 
-    M = cos(f)*sin(g)
+    M = cos(f) * sin(g)
     F = derivative(M, f, v)
     J = derivative(F, f, u)
     JR = replace(J, {f: g})
 
-    F2 = -sin(f)*v*sin(g)
-    J2 = -cos(f)*u*v*sin(g)
-    JR2 = -cos(g)*u*v*sin(g)
+    F2 = -sin(f) * v * sin(g)
+    J2 = -cos(f) * u * v * sin(g)
+    JR2 = -cos(g) * u * v * sin(g)
 
     assertEqualBySampling(F, F2)
     assertEqualBySampling(J, J2)
@@ -796,30 +874,29 @@ def test_derivative_replace_works_together(self):
 
 
 def test_index_simplification_handles_repeated_indices(self):
-    mesh = Mesh(FiniteElement("Lagrange", quadrilateral, 1, (2, ), identity_pullback, H1))
+    mesh = Mesh(FiniteElement("Lagrange", quadrilateral, 1, (2,), identity_pullback, H1))
     V = FunctionSpace(mesh, FiniteElement("DQ", quadrilateral, 0, (2, 2), identity_pullback, L2))
     K = JacobianInverse(mesh)
     G = outer(Identity(2), Identity(2))
-    i, j, k, l, m, n = indices(6)
-    A = as_tensor(K[m, i] * K[n, j] * G[i, j, k, l], (m, n, k, l))
+    i, j, k, L, m, n = indices(6)
+    A = as_tensor(K[m, i] * K[n, j] * G[i, j, k, L], (m, n, k, L))
     i, j = indices(2)
     # Can't use A[i, i, j, j] because UFL automagically index-sums
     # repeated indices in the __getitem__ call.
     Adiag = Indexed(A, MultiIndex((i, i, j, j)))
     A = as_tensor(Adiag, (i, j))
     v = TestFunction(V)
-    f = inner(A, v)*dx
+    f = inner(A, v) * dx
     fd = compute_form_data(f, do_apply_geometry_lowering=True)
-    integral, = fd.preprocessed_form.integrals()
+    (integral,) = fd.preprocessed_form.integrals()
     assert integral.integrand().ufl_free_indices == ()
 
 
 def test_index_simplification_reference_grad(self):
-    mesh = Mesh(FiniteElement("Lagrange", quadrilateral, 1, (2, ), identity_pullback, H1))
-    i, = indices(1)
+    mesh = Mesh(FiniteElement("Lagrange", quadrilateral, 1, (2,), identity_pullback, H1))
+    (i,) = indices(1)
     A = as_tensor(Indexed(Jacobian(mesh), MultiIndex((i, i))), (i,))
-    expr = apply_derivatives(apply_geometry_lowering(
-        apply_algebra_lowering(A[0])))
+    expr = apply_derivatives(apply_geometry_lowering(apply_algebra_lowering(A[0])))
     assert expr == ReferenceGrad(SpatialCoordinate(mesh))[0, 0]
     assert expr.ufl_free_indices == ()
     assert expr.ufl_shape == ()
@@ -827,27 +904,24 @@ def test_index_simplification_reference_grad(self):
 
 # --- Scratch space
 
+
 def test_foobar(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
-
     du = TrialFunction(space)
-
     U = Coefficient(space)
 
     def planarGrad(u):
-        return as_matrix([[u[0].dx(0), 0, u[0].dx(1)],
-                          [0, 0, 0],
-                          [u[1].dx(0), 0, u[1].dx(1)]])
+        return as_matrix([[u[0].dx(0), 0, u[0].dx(1)], [0, 0, 0], [u[1].dx(0), 0, u[1].dx(1)]])
 
     def epsilon(u):
-        return 0.5*(planarGrad(u)+planarGrad(u).T)
+        return 0.5 * (planarGrad(u) + planarGrad(u).T)
 
     def NS_a(u, v):
         return inner(epsilon(u), epsilon(v))
 
-    L = NS_a(U, v)*dx
-    a = derivative(L, U, du)  # noqa: F841
+    L = NS_a(U, v) * dx
+    _ = derivative(L, U, du)
     # TODO: assert something
diff --git a/test/test_diff.py b/test/test_diff.py
index 5a53e5c8d..5388eab43 100755
--- a/test/test_diff.py
+++ b/test/test_diff.py
@@ -3,8 +3,23 @@
 
 import pytest
 
-from ufl import (Coefficient, FunctionSpace, Mesh, SpatialCoordinate, as_vector, atan, cos, diff, exp, indices, ln, sin,
-                 tan, triangle, variable)
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    SpatialCoordinate,
+    as_vector,
+    atan,
+    cos,
+    diff,
+    exp,
+    indices,
+    ln,
+    sin,
+    tan,
+    triangle,
+    variable,
+)
 from ufl.algorithms import expand_derivatives
 from ufl.constantvalue import as_ufl
 from ufl.finiteelement import FiniteElement
@@ -46,6 +61,7 @@ def f(v):
 
     def df(v):
         return as_ufl(1)
+
     _test(f, df)
 
 
@@ -55,6 +71,7 @@ def f(v):
 
     def df(v):
         return as_ufl(1)
+
     _test(f, df)
 
 
@@ -64,15 +81,17 @@ def f(v):
 
     def df(v):
         return as_ufl(3)
+
     _test(f, df)
 
 
 def testPower(v):
     def f(v):
-        return v ** 3
+        return v**3
 
     def df(v):
-        return 3 * v ** 2
+        return 3 * v**2
+
     _test(f, df)
 
 
@@ -82,6 +101,7 @@ def f(v):
 
     def df(v):
         return as_ufl(1.0 / 3.0)
+
     _test(f, df)
 
 
@@ -90,7 +110,8 @@ def f(v):
         return 3.0 / v
 
     def df(v):
-        return -3.0 / v ** 2
+        return -3.0 / v**2
+
     _test(f, df)
 
 
@@ -100,6 +121,7 @@ def f(v):
 
     def df(v):
         return exp(v)
+
     _test(f, df)
 
 
@@ -109,6 +131,7 @@ def f(v):
 
     def df(v):
         return 1.0 / v
+
     _test(f, df)
 
 
@@ -118,6 +141,7 @@ def f(v):
 
     def df(v):
         return cos(v)
+
     _test(f, df)
 
 
@@ -127,6 +151,7 @@ def f(v):
 
     def df(v):
         return -sin(v)
+
     _test(f, df)
 
 
@@ -136,8 +161,10 @@ def f(v):
 
     def df(v):
         return 2.0 / (cos(2.0 * v) + 1.0)
+
     _test(f, df)
 
+
 # TODO: Check the following tests. They run into strange math domain errors.
 # def testAsin(v):
 #    def f(v):  return asin(v)
@@ -155,37 +182,39 @@ def f(v):
         return atan(v)
 
     def df(v):
-        return 1 / (1.0 + v ** 2)
+        return 1 / (1.0 + v**2)
+
     _test(f, df)
 
 
 def testIndexSum(v):
     def f(v):
         # 3*v + 4*v**2 + 5*v**3
-        a = as_vector((v, v ** 2, v ** 3))
+        a = as_vector((v, v**2, v**3))
         b = as_vector((3, 4, 5))
-        i, = indices(1)
+        (i,) = indices(1)
         return a[i] * b[i]
 
     def df(v):
-        return 3 + 4 * 2 * v + 5 * 3 * v ** 2
+        return 3 + 4 * 2 * v + 5 * 3 * v**2
+
     _test(f, df)
 
 
 def testCoefficient():
-    coord_elem = FiniteElement("Lagrange", triangle, 1, (3, ), identity_pullback, H1)
+    coord_elem = FiniteElement("Lagrange", triangle, 1, (3,), identity_pullback, H1)
     mesh = Mesh(coord_elem)
     V = FunctionSpace(mesh, FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1))
     v = Coefficient(V)
-    assert round(expand_derivatives(diff(v, v))-1.0, 7) == 0
+    assert round(expand_derivatives(diff(v, v)) - 1.0, 7) == 0
 
 
 def testDiffX():
     cell = triangle
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     f = x[0] ** 2 * x[1] ** 2
-    i, = indices(1)
+    (i,) = indices(1)
     df1 = diff(f, x)
     df2 = as_vector(f.dx(i), i)
 
@@ -199,4 +228,5 @@ def testDiffX():
     assert round(df10 - 2 * 2 * 9, 7) == 0
     assert round(df11 - 2 * 4 * 3, 7) == 0
 
+
 # TODO: More tests involving wrapper types and indices
diff --git a/test/test_domains.py b/test/test_domains.py
index 112a1613b..44477cc9c 100755
--- a/test/test_domains.py
+++ b/test/test_domains.py
@@ -1,16 +1,30 @@
-
 """Tests of domain language and attaching domains to forms."""
 
 import pytest
 from mockobjects import MockMesh
 
 import ufl  # noqa: F401
-from ufl import (Cell, Coefficient, Constant, FunctionSpace, Mesh, ds, dS, dx, hexahedron, interval, quadrilateral,
-                 tetrahedron, triangle)
+from ufl import (
+    Cell,
+    Coefficient,
+    Constant,
+    FunctionSpace,
+    Mesh,
+    dS,
+    ds,
+    dx,
+    hexahedron,
+    interval,
+    quadrilateral,
+    tetrahedron,
+    triangle,
+)
 from ufl.algorithms import compute_form_data
 from ufl.finiteelement import FiniteElement
-from ufl.pullback import IdentityPullback  # noqa: F401
-from ufl.pullback import identity_pullback
+from ufl.pullback import (
+    IdentityPullback,  # noqa: F401
+    identity_pullback,
+)
 from ufl.sobolevspace import H1
 
 all_cells = (interval, triangle, tetrahedron, quadrilateral, hexahedron)
@@ -19,13 +33,13 @@
 def test_construct_domains_from_cells():
     for cell in all_cells:
         d = cell.topological_dimension()
-        Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1))
+        Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1))
 
 
 def test_construct_domains_with_names():
     for cell in all_cells:
         d = cell.topological_dimension()
-        e = FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1)
+        e = FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1)
         D2 = Mesh(e, ufl_id=2)
         D3 = Mesh(e, ufl_id=3)
         D3b = Mesh(e, ufl_id=3)
@@ -36,52 +50,60 @@ def test_construct_domains_with_names():
 def test_domains_sort_by_name():
     # This ordering is rather arbitrary, but at least this shows sorting is
     # working
-    domains1 = [Mesh(FiniteElement("Lagrange", cell, 1, (cell.topological_dimension(), ),
-                                   identity_pullback, H1),
-                     ufl_id=hash(cell.cellname()))
-                for cell in all_cells]
-    domains2 = [Mesh(FiniteElement("Lagrange", cell, 1, (cell.topological_dimension(), ),
-                                   identity_pullback, H1),
-                     ufl_id=hash(cell.cellname()))
-                for cell in sorted(all_cells)]
-    sdomains = sorted(domains1, key=lambda D: (D.topological_dimension(),
-                                               D.ufl_cell(),
-                                               D.ufl_id()))
+    domains1 = [
+        Mesh(
+            FiniteElement(
+                "Lagrange", cell, 1, (cell.topological_dimension(),), identity_pullback, H1
+            ),
+            ufl_id=hash(cell.cellname()),
+        )
+        for cell in all_cells
+    ]
+    domains2 = [
+        Mesh(
+            FiniteElement(
+                "Lagrange", cell, 1, (cell.topological_dimension(),), identity_pullback, H1
+            ),
+            ufl_id=hash(cell.cellname()),
+        )
+        for cell in sorted(all_cells)
+    ]
+    sdomains = sorted(domains1, key=lambda D: (D.topological_dimension(), D.ufl_cell(), D.ufl_id()))
     assert sdomains != domains1
     assert sdomains == domains2
 
 
 def test_topdomain_creation():
-    D = Mesh(FiniteElement("Lagrange", interval, 1, (1, ), identity_pullback, H1))
+    D = Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1))
     assert D.geometric_dimension() == 1
-    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     assert D.geometric_dimension() == 2
-    D = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    D = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     assert D.geometric_dimension() == 3
 
 
 def test_cell_legacy_case():
     # Passing cell like old code does
-    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
     V = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     f = Coefficient(FunctionSpace(D, V))
-    assert f.ufl_domains() == (D, )
+    assert f.ufl_domains() == (D,)
 
     M = f * dx
-    assert M.ufl_domains() == (D, )
+    assert M.ufl_domains() == (D,)
 
 
 def test_simple_domain_case():
     # Creating domain from just cell with label like new dolfin will do
-    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=3)
+    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=3)
 
     V = FunctionSpace(D, FiniteElement("Lagrange", D.ufl_cell(), 1, (), identity_pullback, "H1"))
     f = Coefficient(V)
-    assert f.ufl_domains() == (D, )
+    assert f.ufl_domains() == (D,)
 
     M = f * dx
-    assert M.ufl_domains() == (D, )
+    assert M.ufl_domains() == (D,)
 
 
 def test_creating_domains_with_coordinate_fields():  # FIXME: Rewrite for new approach
@@ -89,7 +111,7 @@ def test_creating_domains_with_coordinate_fields():  # FIXME: Rewrite for new ap
 
     # Mesh with P2 representation of coordinates
     cell = triangle
-    P2 = FiniteElement("Lagrange", cell, 2, (2, ), identity_pullback, H1)
+    P2 = FiniteElement("Lagrange", cell, 2, (2,), identity_pullback, H1)
     domain = Mesh(P2)
 
     # Piecewise linear function space over quadratic mesh
@@ -98,8 +120,8 @@ def test_creating_domains_with_coordinate_fields():  # FIXME: Rewrite for new ap
 
     f = Coefficient(V)
     M = f * dx
-    assert f.ufl_domains() == (domain, )
-    assert M.ufl_domains() == (domain, )
+    assert f.ufl_domains() == (domain,)
+    assert M.ufl_domains() == (domain,)
 
     # Test the gymnastics that dolfin will have to go through
     domain2 = Mesh(P2, ufl_id=domain.ufl_id())
@@ -112,86 +134,193 @@ def test_creating_domains_with_coordinate_fields():  # FIXME: Rewrite for new ap
 
 def test_join_domains():
     from ufl.domain import join_domains
+
     mesh7 = MockMesh(7)
     mesh8 = MockMesh(8)
     triangle = Cell("triangle")
-    xa = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    xb = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
+    xa = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    xb = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
 
     # Equal domains are joined
-    assert 1 == len(join_domains([
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7),
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7)]))
-    assert 1 == len(join_domains([
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7, cargo=mesh7),
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7, cargo=mesh7)]))
+    assert 1 == len(
+        join_domains(
+            [
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=7),
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=7),
+            ]
+        )
+    )
+    assert 1 == len(
+        join_domains(
+            [
+                Mesh(
+                    FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1),
+                    ufl_id=7,
+                    cargo=mesh7,
+                ),
+                Mesh(
+                    FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1),
+                    ufl_id=7,
+                    cargo=mesh7,
+                ),
+            ]
+        )
+    )
     assert 1 == len(join_domains([Mesh(xa, ufl_id=3), Mesh(xa, ufl_id=3)]))
 
     # Different domains are not joined
-    assert 2 == len(join_domains([
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)),
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))]))
-    assert 2 == len(join_domains([
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7),
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=8)]))
-    assert 2 == len(join_domains([
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7),
-        Mesh(FiniteElement("Lagrange", quadrilateral, 1, (2, ), identity_pullback, H1), ufl_id=8)]))
+    assert 2 == len(
+        join_domains(
+            [
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+            ]
+        )
+    )
+    assert 2 == len(
+        join_domains(
+            [
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=7),
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=8),
+            ]
+        )
+    )
+    assert 2 == len(
+        join_domains(
+            [
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=7),
+                Mesh(
+                    FiniteElement("Lagrange", quadrilateral, 1, (2,), identity_pullback, H1),
+                    ufl_id=8,
+                ),
+            ]
+        )
+    )
     assert 2 == len(join_domains([Mesh(xa, ufl_id=7), Mesh(xa, ufl_id=8)]))
     assert 2 == len(join_domains([Mesh(xa), Mesh(xb)]))
 
     # Incompatible coordinates require labeling
-    xc = Coefficient(FunctionSpace(
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)),
-        FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)))
-    xd = Coefficient(FunctionSpace(
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)),
-        FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)))
+    xc = Coefficient(
+        FunctionSpace(
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+            FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1),
+        )
+    )
+    xd = Coefficient(
+        FunctionSpace(
+            Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+            FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1),
+        )
+    )
     with pytest.raises(BaseException):
         join_domains([Mesh(xc), Mesh(xd)])
 
     # Incompatible data is checked if and only if the domains are the same
-    assert 2 == len(join_domains([
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7, cargo=mesh7),
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=8, cargo=mesh8)]))
-    assert 2 == len(join_domains([
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7, cargo=mesh7),
-        Mesh(FiniteElement("Lagrange", quadrilateral, 1, (2, ), identity_pullback, H1),
-             ufl_id=8, cargo=mesh8)]))
+    assert 2 == len(
+        join_domains(
+            [
+                Mesh(
+                    FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1),
+                    ufl_id=7,
+                    cargo=mesh7,
+                ),
+                Mesh(
+                    FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1),
+                    ufl_id=8,
+                    cargo=mesh8,
+                ),
+            ]
+        )
+    )
+    assert 2 == len(
+        join_domains(
+            [
+                Mesh(
+                    FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1),
+                    ufl_id=7,
+                    cargo=mesh7,
+                ),
+                Mesh(
+                    FiniteElement("Lagrange", quadrilateral, 1, (2,), identity_pullback, H1),
+                    ufl_id=8,
+                    cargo=mesh8,
+                ),
+            ]
+        )
+    )
     # Geometric dimensions must match
     with pytest.raises(BaseException):
-        join_domains([
-            Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)),
-            Mesh(FiniteElement("Lagrange", triangle, 1, (3, ), identity_pullback, H1))])
+        join_domains(
+            [
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)),
+                Mesh(FiniteElement("Lagrange", triangle, 1, (3,), identity_pullback, H1)),
+            ]
+        )
     with pytest.raises(BaseException):
-        join_domains([
-            Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7, cargo=mesh7),
-            Mesh(FiniteElement("Lagrange", triangle, 1, (3, ), identity_pullback, H1), ufl_id=8, cargo=mesh8)])
+        join_domains(
+            [
+                Mesh(
+                    FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1),
+                    ufl_id=7,
+                    cargo=mesh7,
+                ),
+                Mesh(
+                    FiniteElement("Lagrange", triangle, 1, (3,), identity_pullback, H1),
+                    ufl_id=8,
+                    cargo=mesh8,
+                ),
+            ]
+        )
     # Cargo and mesh ids must match
     with pytest.raises(BaseException):
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7, cargo=mesh8)
+        Mesh(
+            FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1),
+            ufl_id=7,
+            cargo=mesh8,
+        )
 
     # Nones are removed
-    assert 2 == len(join_domains([
-        None, Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=3),
-        None, Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=3),
-        None, Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=4)]))
-    assert 2 == len(join_domains([
-        Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1), ufl_id=7), None,
-        Mesh(FiniteElement("Lagrange", quadrilateral, 1, (2, ), identity_pullback, H1), ufl_id=8)]))
-    assert None not in join_domains([
-        Mesh(FiniteElement("Lagrange", triangle, 1, (3, ), identity_pullback, H1), ufl_id=7), None,
-        Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1), ufl_id=8)])
+    assert 2 == len(
+        join_domains(
+            [
+                None,
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=3),
+                None,
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=3),
+                None,
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=4),
+            ]
+        )
+    )
+    assert 2 == len(
+        join_domains(
+            [
+                Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1), ufl_id=7),
+                None,
+                Mesh(
+                    FiniteElement("Lagrange", quadrilateral, 1, (2,), identity_pullback, H1),
+                    ufl_id=8,
+                ),
+            ]
+        )
+    )
+    assert None not in join_domains(
+        [
+            Mesh(FiniteElement("Lagrange", triangle, 1, (3,), identity_pullback, H1), ufl_id=7),
+            None,
+            Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1), ufl_id=8),
+        ]
+    )
 
 
 def test_everywhere_integrals_with_backwards_compatibility():
-    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
     V = FunctionSpace(D, FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1))
     f = Coefficient(V)
 
     a = f * dx
-    ida, = compute_form_data(a).integral_data
+    (ida,) = compute_form_data(a).integral_data
 
     # Check some integral data
     assert ida.integral_type == "cell"
@@ -207,7 +336,7 @@ def test_everywhere_integrals_with_backwards_compatibility():
 
 
 def test_merge_sort_integral_data():
-    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    D = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
     V = FunctionSpace(D, FiniteElement("CG", triangle, 1, (), identity_pullback, H1))
 
diff --git a/test/test_duals.py b/test/test_duals.py
index 53e230f3f..7786e7400 100644
--- a/test/test_duals.py
+++ b/test/test_duals.py
@@ -3,9 +3,29 @@
 
 import pytest
 
-from ufl import (Action, Adjoint, Argument, Coargument, Coefficient, Cofunction, FormSum, FunctionSpace, Matrix, Mesh,
-                 MixedFunctionSpace, TestFunction, TrialFunction, action, adjoint, derivative, dx, inner, interval,
-                 tetrahedron, triangle)
+from ufl import (
+    Action,
+    Adjoint,
+    Argument,
+    Coargument,
+    Coefficient,
+    Cofunction,
+    FormSum,
+    FunctionSpace,
+    Matrix,
+    Mesh,
+    MixedFunctionSpace,
+    TestFunction,
+    TrialFunction,
+    action,
+    adjoint,
+    derivative,
+    dx,
+    inner,
+    interval,
+    tetrahedron,
+    triangle,
+)
 from ufl.algorithms.ad import expand_derivatives
 from ufl.constantvalue import Zero
 from ufl.duals import is_dual, is_primal
@@ -17,9 +37,9 @@
 
 def test_mixed_functionspace(self):
     # Domains
-    domain_3d = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
-    domain_1d = Mesh(FiniteElement("Lagrange", interval, 1, (1, ), identity_pullback, H1))
+    domain_3d = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
+    domain_1d = Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1))
     # Finite elements
     f_1d = FiniteElement("Lagrange", interval, 1, (), identity_pullback, H1)
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
@@ -50,7 +70,7 @@ def test_mixed_functionspace(self):
 
 
 def test_dual_coefficients():
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V = FunctionSpace(domain_2d, f_2d)
     V_dual = V.dual()
@@ -73,7 +93,7 @@ def test_dual_coefficients():
 
 
 def test_dual_arguments():
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V = FunctionSpace(domain_2d, f_2d)
     V_dual = V.dual()
@@ -96,7 +116,7 @@ def test_dual_arguments():
 
 
 def test_addition():
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V = FunctionSpace(domain_2d, f_2d)
     V_dual = V.dual()
@@ -134,7 +154,7 @@ def test_addition():
 
 
 def test_scalar_mult():
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V = FunctionSpace(domain_2d, f_2d)
     V_dual = V.dual()
@@ -152,7 +172,7 @@ def test_scalar_mult():
 
 
 def test_adjoint():
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V = FunctionSpace(domain_2d, f_2d)
     a = Matrix(V, V)
@@ -171,10 +191,10 @@ def test_adjoint():
 
 
 def test_action():
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V = FunctionSpace(domain_2d, f_2d)
-    domain_1d = Mesh(FiniteElement("Lagrange", interval, 1, (1, ), identity_pullback, H1))
+    domain_1d = Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1))
     f_1d = FiniteElement("Lagrange", interval, 1, (), identity_pullback, H1)
     U = FunctionSpace(domain_1d, f_1d)
 
@@ -222,7 +242,8 @@ def test_action():
     u2 = Coefficient(U)
     u3 = Coefficient(U)
     # Check Action left-distributivity with Sum
-    # Add 3 Coefficients to check composition of Sum works fine since u + u2 + u3 => Sum(u, Sum(u2, u3))
+    # Add 3 Coefficients to check composition of Sum works fine since u
+    # + u2 + u3 => Sum(u, Sum(u2, u3))
     res = action(a, u + u2 + u3)
     assert res == Action(a, u3) + Action(a, u) + Action(a, u2)
     # Check Action right-distributivity with Sum
@@ -231,10 +252,10 @@ def test_action():
 
 
 def test_differentiation():
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V = FunctionSpace(domain_2d, f_2d)
-    domain_1d = Mesh(FiniteElement("Lagrange", interval, 1, (1, ), identity_pullback, H1))
+    domain_1d = Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1))
     f_1d = FiniteElement("Lagrange", interval, 1, (), identity_pullback, H1)
     U = FunctionSpace(domain_1d, f_1d)
 
@@ -246,7 +267,10 @@ def test_differentiation():
     w = Cofunction(U.dual())
     dwdu = expand_derivatives(derivative(w, u))
     assert isinstance(dwdu, ZeroBaseForm)
-    assert dwdu.arguments() == (Argument(w.ufl_function_space().dual(), 0), Argument(u.ufl_function_space(), 1))
+    assert dwdu.arguments() == (
+        Argument(w.ufl_function_space().dual(), 0),
+        Argument(u.ufl_function_space(), 1),
+    )
     # Check compatibility with int/float
     assert dwdu == 0
 
@@ -277,8 +301,10 @@ def test_differentiation():
     # -- Action -- #
     Ac = Action(w, u)
     dAcdu = derivative(Ac, u)
-    assert dAcdu == (action(adjoint(derivative(w, u), derivatives_expanded=True), u, derivatives_expanded=True)
-                     + action(w, derivative(u, u), derivatives_expanded=True))
+    assert dAcdu == (
+        action(adjoint(derivative(w, u), derivatives_expanded=True), u, derivatives_expanded=True)
+        + action(w, derivative(u, u), derivatives_expanded=True)
+    )
 
     dAcdu = expand_derivatives(dAcdu)
     # Since dw/du = 0
@@ -294,7 +320,7 @@ def test_differentiation():
 
 
 def test_zero_base_form_mult():
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V = FunctionSpace(domain_2d, f_2d)
     v = Argument(V, 0)
@@ -308,7 +334,7 @@ def test_zero_base_form_mult():
 
 
 def test_base_form_call():
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     V = FunctionSpace(domain_2d, f_2d)
 
diff --git a/test/test_equals.py b/test/test_equals.py
index ddfa5058c..3956463e8 100755
--- a/test/test_equals.py
+++ b/test/test_equals.py
@@ -11,7 +11,7 @@ def test_comparison_of_coefficients():
     U = FiniteElement("Lagrange", triangle, 2, (), identity_pullback, H1)
     Ub = FiniteElement("Lagrange", triangle, 2, (), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     u_space = FunctionSpace(domain, U)
     ub_space = FunctionSpace(domain, Ub)
@@ -43,7 +43,7 @@ def test_comparison_of_cofunctions():
     U = FiniteElement("Lagrange", triangle, 2, (), identity_pullback, H1)
     Ub = FiniteElement("Lagrange", triangle, 2, (), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     u_space = FunctionSpace(domain, U)
     ub_space = FunctionSpace(domain, Ub)
@@ -72,7 +72,7 @@ def test_comparison_of_cofunctions():
 
 def test_comparison_of_products():
     V = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     v = Coefficient(v_space)
     u = Coefficient(v_space)
@@ -86,7 +86,7 @@ def test_comparison_of_products():
 
 def test_comparison_of_sums():
     V = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     v = Coefficient(v_space)
     u = Coefficient(v_space)
@@ -100,7 +100,7 @@ def test_comparison_of_sums():
 
 def test_comparison_of_deeply_nested_expression():
     V = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     v_space = FunctionSpace(domain, V)
     v = Coefficient(v_space, count=1)
     u = Coefficient(v_space, count=1)
@@ -113,8 +113,9 @@ def build_expr(a):
             elif i % 3 == 1:
                 a = a * i
             elif i % 3 == 2:
-                a = a ** i
+                a = a**i
         return a
+
     a = build_expr(u)
     b = build_expr(v)
     c = build_expr(w)
diff --git a/test/test_evaluate.py b/test/test_evaluate.py
index 55ca15aeb..da01d452b 100755
--- a/test/test_evaluate.py
+++ b/test/test_evaluate.py
@@ -3,9 +3,36 @@
 
 import math
 
-from ufl import (Argument, Coefficient, FunctionSpace, Identity, Mesh, SpatialCoordinate, as_matrix, as_vector, cos,
-                 cross, det, dev, dot, exp, i, indices, inner, j, ln, outer, sin, skew, sqrt, sym, tan, tetrahedron, tr,
-                 triangle)
+from ufl import (
+    Argument,
+    Coefficient,
+    FunctionSpace,
+    Identity,
+    Mesh,
+    SpatialCoordinate,
+    as_matrix,
+    as_vector,
+    cos,
+    cross,
+    det,
+    dev,
+    dot,
+    exp,
+    i,
+    indices,
+    inner,
+    j,
+    ln,
+    outer,
+    sin,
+    skew,
+    sqrt,
+    sym,
+    tan,
+    tetrahedron,
+    tr,
+    triangle,
+)
 from ufl.constantvalue import as_ufl
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
@@ -43,7 +70,7 @@ def testIdentity():
 
 def testCoords():
     cell = triangle
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     s = x[0] + x[1]
     e = s((5, 7))
@@ -54,7 +81,7 @@ def testCoords():
 def testFunction1():
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     f = Coefficient(space)
     s = 3 * f
@@ -66,12 +93,13 @@ def testFunction1():
 def testFunction2():
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     f = Coefficient(space)
 
     def g(x):
         return x[0]
+
     s = 3 * f
     e = s((5, 7), {f: g})
     v = 3 * 5
@@ -81,12 +109,13 @@ def g(x):
 def testArgument2():
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     f = Argument(space, 2)
 
     def g(x):
         return x[0]
+
     s = 3 * f
     e = s((5, 7), {f: g})
     v = 3 * 5
@@ -95,40 +124,40 @@ def g(x):
 
 def testAlgebra():
     cell = triangle
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     s = 3 * (x[0] + x[1]) - 7 + x[0] ** (x[1] / 2)
     e = s((5, 7))
-    v = 3 * (5. + 7.) - 7 + 5. ** (7. / 2)
+    v = 3 * (5.0 + 7.0) - 7 + 5.0 ** (7.0 / 2)
     assert e == v
 
 
 def testIndexSum():
     cell = triangle
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
-    i, = indices(1)
+    (i,) = indices(1)
     s = x[i] * x[i]
     e = s((5, 7))
-    v = 5 ** 2 + 7 ** 2
+    v = 5**2 + 7**2
     assert e == v
 
 
 def testIndexSum2():
     cell = triangle
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     ident = Identity(cell.topological_dimension())
     i, j = indices(2)
     s = (x[i] * x[j]) * ident[i, j]
     e = s((5, 7))
     # v = sum_i sum_j x_i x_j delta_ij = x_0 x_0 + x_1 x_1
-    v = 5 ** 2 + 7 ** 2
+    v = 5**2 + 7**2
     assert e == v
 
 
 def testMathFunctions():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)[0]
 
     s = sin(x)
@@ -163,7 +192,7 @@ def testMathFunctions():
 
 
 def testListTensor():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x, y = SpatialCoordinate(domain)
 
     m = as_matrix([[x, y], [-y, -x]])
@@ -175,12 +204,12 @@ def testListTensor():
 
     s = m[0, 0] * m[1, 0] * m[0, 1] * m[1, 1]
     e = s((5, 7))
-    v = 5 ** 2 * 7 ** 2
+    v = 5**2 * 7**2
     assert e == v
 
 
 def testComponentTensor1():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     m = as_vector(x[i], i)
 
@@ -191,7 +220,7 @@ def testComponentTensor1():
 
 
 def testComponentTensor2():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xx = outer(x, x)
 
@@ -204,7 +233,7 @@ def testComponentTensor2():
 
 
 def testComponentTensor3():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xx = outer(x, x)
 
@@ -218,19 +247,20 @@ def testComponentTensor3():
 
 def testCoefficient():
     V = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     f = Coefficient(space)
-    e = f ** 2
+    e = f**2
 
     def eval_f(x):
         return x[0] * x[1] ** 2
-    assert e((3, 7), {f: eval_f}) == (3 * 7 ** 2) ** 2
+
+    assert e((3, 7), {f: eval_f}) == (3 * 7**2) ** 2
 
 
 def testCoefficientDerivative():
     V = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     f = Coefficient(space)
     e = f.dx(0) ** 2 + f.dx(1) ** 2
@@ -239,19 +269,20 @@ def eval_f(x, derivatives):
         if not derivatives:
             return eval_f.c * x[0] * x[1] ** 2
         # assume only first order derivative
-        d, = derivatives
+        (d,) = derivatives
         if d == 0:
             return eval_f.c * x[1] ** 2
         if d == 1:
             return eval_f.c * x[0] * 2 * x[1]
+
     # shows how to attach data to eval_f
     eval_f.c = 5
 
-    assert e((3, 7), {f: eval_f}) == (5 * 7 ** 2) ** 2 + (5 * 3 * 2 * 7) ** 2
+    assert e((3, 7), {f: eval_f}) == (5 * 7**2) ** 2 + (5 * 3 * 2 * 7) ** 2
 
 
 def test_dot():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     s = dot(x, 2 * x)
     e = s((5, 7))
@@ -260,7 +291,7 @@ def test_dot():
 
 
 def test_inner():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xx = as_matrix(((2 * x[0], 3 * x[0]), (2 * x[1], 3 * x[1])))
     s = inner(xx, 2 * xx)
@@ -270,35 +301,27 @@ def test_inner():
 
 
 def test_outer():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xx = outer(outer(x, x), as_vector((2, 3)))
     s = inner(xx, 2 * xx)
     e = s((5, 7))
-    v = 2 * (5 ** 2 + 7 ** 2) ** 2 * (2 ** 2 + 3 ** 2)
+    v = 2 * (5**2 + 7**2) ** 2 * (2**2 + 3**2)
     assert e == v
 
 
 def test_cross():
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xv = (3, 5, 7)
 
     # Test cross product of triplets of orthogonal
     # vectors, where |a x b| = |a| |b|
     ts = [
-        [as_vector((x[0], 0, 0)),
-            as_vector((0, x[1], 0)),
-            as_vector((0, 0, x[2]))],
-        [as_vector((x[0], x[1], 0)),
-            as_vector((x[1], -x[0], 0)),
-            as_vector((0, 0, x[2]))],
-        [as_vector((0, x[0], x[1])),
-            as_vector((0, x[1], -x[0])),
-            as_vector((x[2], 0, 0))],
-        [as_vector((x[0], 0, x[1])),
-            as_vector((x[1], 0, -x[0])),
-            as_vector((0, x[2], 0))],
+        [as_vector((x[0], 0, 0)), as_vector((0, x[1], 0)), as_vector((0, 0, x[2]))],
+        [as_vector((x[0], x[1], 0)), as_vector((x[1], -x[0], 0)), as_vector((0, 0, x[2]))],
+        [as_vector((0, x[0], x[1])), as_vector((0, x[1], -x[0])), as_vector((x[2], 0, 0))],
+        [as_vector((x[0], 0, x[1])), as_vector((x[1], 0, -x[0])), as_vector((0, x[2], 0))],
     ]
     for t in ts:
         for a in range(3):
@@ -313,7 +336,7 @@ def test_cross():
 
 
 def xtest_dev():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xv = (5, 7)
     xx = outer(x, x)
@@ -325,31 +348,31 @@ def xtest_dev():
 
 
 def test_skew():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xv = (5, 7)
     xx = outer(x, x)
     s1 = skew(2 * xx)
-    s2 = (xx - xx.T)
+    s2 = xx - xx.T
     e = inner(s1, s1)(xv)
     v = inner(s2, s2)(xv)
     assert e == v
 
 
 def test_sym():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xv = (5, 7)
     xx = outer(x, x)
     s1 = sym(2 * xx)
-    s2 = (xx + xx.T)
+    s2 = xx + xx.T
     e = inner(s1, s1)(xv)
     v = inner(s2, s2)(xv)
     assert e == v
 
 
 def test_tr():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xv = (5, 7)
     xx = outer(x, x)
@@ -360,14 +383,14 @@ def test_tr():
 
 
 def test_det2D():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     xv = (5, 7)
     a, b = 6.5, -4
     xx = as_matrix(((x[0], x[1]), (a, b)))
     s = det(2 * xx)
     e = s(xv)
-    v = 2 ** 2 * (5 * b - 7 * a)
+    v = 2**2 * (5 * b - 7 * a)
     assert e == v
 
 
@@ -376,14 +399,10 @@ def xtest_det3D():  # FIXME
     xv = (5, 7, 9)
     a, b, c = 6.5, -4, 3
     d, e, f = 2, 3, 4
-    xx = as_matrix(((x[0], x[1], x[2]),
-                    (a, b, c),
-                    (d, e, f)))
+    xx = as_matrix(((x[0], x[1], x[2]), (a, b, c), (d, e, f)))
     s = det(2 * xx)
     e = s(xv)
-    v = 2 ** 3 * \
-        (xv[0] * (b * f - e * c) - xv[1] *
-         (a * f - c * d) + xv[2] * (a * e - b * d))
+    v = 2**3 * (xv[0] * (b * f - e * c) - xv[1] * (a * f - c * d) + xv[2] * (a * e - b * d))
     assert e == v
 
 
diff --git a/test/test_expand_indices.py b/test/test_expand_indices.py
index f8314df2c..1cd9d8983 100755
--- a/test/test_expand_indices.py
+++ b/test/test_expand_indices.py
@@ -8,8 +8,31 @@
 
 import pytest
 
-from ufl import (Coefficient, FunctionSpace, Identity, Mesh, as_tensor, cos, det, div, dot, dx, exp, grad, i, inner, j,
-                 k, l, ln, nabla_div, nabla_grad, outer, sin, triangle)
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Identity,
+    Mesh,
+    as_tensor,
+    cos,
+    det,
+    div,
+    dot,
+    dx,
+    exp,
+    grad,
+    i,
+    inner,
+    j,
+    k,
+    l,
+    ln,
+    nabla_div,
+    nabla_grad,
+    outer,
+    sin,
+    triangle,
+)
 from ufl.algorithms import compute_form_data, expand_derivatives, expand_indices
 from ufl.algorithms.renumbering import renumber_indices
 from ufl.finiteelement import FiniteElement
@@ -21,13 +44,12 @@
 
 
 class Fixture:
-
     def __init__(self):
         cell = triangle
         element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-        velement = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
+        velement = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
         telement = FiniteElement("Lagrange", cell, 1, (2, 2), identity_pullback, H1)
-        domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+        domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
         space = FunctionSpace(domain, element)
         vspace = FunctionSpace(domain, velement)
         tspace = FunctionSpace(domain, telement)
@@ -113,22 +135,22 @@ def TF(x, derivatives=()):
     def compare(self, f, value):
         debug = 0
         if debug:
-            print(('f', f))
+            print(("f", f))
         g = expand_derivatives(f)
         if debug:
-            print(('g', g))
+            print(("g", g))
         gv = g(self.x, self.mapping)
         assert abs(gv - value) < 1e-7
 
         g = expand_indices(g)
         if debug:
-            print(('g', g))
+            print(("g", g))
         gv = g(self.x, self.mapping)
         assert abs(gv - value) < 1e-7
 
         g = renumber_indices(g)
         if debug:
-            print(('g', g))
+            print(("g", g))
         gv = g(self.x, self.mapping)
         assert abs(gv - value) < 1e-7
 
@@ -149,13 +171,13 @@ def test_basic_expand_indices(self, fixt):
     compare(sf, 3)
     compare(sf + 1, 4)
     compare(sf - 2.5, 0.5)
-    compare(sf/2, 1.5)
-    compare(sf/0.5, 6)
+    compare(sf / 2, 1.5)
+    compare(sf / 0.5, 6)
     compare(sf**2, 9)
     compare(sf**0.5, 3**0.5)
     compare(sf**3, 27)
     compare(0.5**sf, 0.5**3)
-    compare(sf * (sf/6), 1.5)
+    compare(sf * (sf / 6), 1.5)
     compare(sin(sf), math.sin(3))
     compare(cos(sf), math.cos(3))
     compare(exp(sf), math.exp(3))
@@ -165,13 +187,13 @@ def test_basic_expand_indices(self, fixt):
     compare(vf[0], 5)
     compare(vf[0] + 1, 6)
     compare(vf[0] - 2.5, 2.5)
-    compare(vf[0]/2, 2.5)
-    compare(vf[0]/0.5, 10)
-    compare(vf[0]**2, 25)
-    compare(vf[0]**0.5, 5**0.5)
-    compare(vf[0]**3, 125)
-    compare(0.5**vf[0], 0.5**5)
-    compare(vf[0] * (vf[0]/6), 5*(5./6))
+    compare(vf[0] / 2, 2.5)
+    compare(vf[0] / 0.5, 10)
+    compare(vf[0] ** 2, 25)
+    compare(vf[0] ** 0.5, 5**0.5)
+    compare(vf[0] ** 3, 125)
+    compare(0.5 ** vf[0], 0.5**5)
+    compare(vf[0] * (vf[0] / 6), 5 * (5.0 / 6))
     compare(sin(vf[0]), math.sin(5))
     compare(cos(vf[0]), math.cos(5))
     compare(exp(vf[0]), math.exp(5))
@@ -181,13 +203,13 @@ def test_basic_expand_indices(self, fixt):
     compare(tf[1, 1], 19)
     compare(tf[1, 1] + 1, 20)
     compare(tf[1, 1] - 2.5, 16.5)
-    compare(tf[1, 1]/2, 9.5)
-    compare(tf[1, 1]/0.5, 38)
-    compare(tf[1, 1]**2, 19**2)
-    compare(tf[1, 1]**0.5, 19**0.5)
-    compare(tf[1, 1]**3, 19**3)
-    compare(0.5**tf[1, 1], 0.5**19)
-    compare(tf[1, 1] * (tf[1, 1]/6), 19*(19./6))
+    compare(tf[1, 1] / 2, 9.5)
+    compare(tf[1, 1] / 0.5, 38)
+    compare(tf[1, 1] ** 2, 19**2)
+    compare(tf[1, 1] ** 0.5, 19**0.5)
+    compare(tf[1, 1] ** 3, 19**3)
+    compare(0.5 ** tf[1, 1], 0.5**19)
+    compare(tf[1, 1] * (tf[1, 1] / 6), 19 * (19.0 / 6))
     compare(sin(tf[1, 1]), math.sin(19))
     compare(cos(tf[1, 1]), math.cos(19))
     compare(exp(tf[1, 1]), math.exp(19))
@@ -200,11 +222,14 @@ def test_expand_indices_index_sum(self, fixt):
     compare = fixt.compare
 
     # Basic index sums
-    compare(vf[i]*vf[i], 5*5+7*7)
-    compare(vf[j]*tf[i, j]*vf[i], 5*5*11 + 5*7*13 + 5*7*17 + 7*7*19)
-    compare(vf[j]*tf.T[j, i]*vf[i], 5*5*11 + 5*7*13 + 5*7*17 + 7*7*19)
+    compare(vf[i] * vf[i], 5 * 5 + 7 * 7)
+    compare(vf[j] * tf[i, j] * vf[i], 5 * 5 * 11 + 5 * 7 * 13 + 5 * 7 * 17 + 7 * 7 * 19)
+    compare(vf[j] * tf.T[j, i] * vf[i], 5 * 5 * 11 + 5 * 7 * 13 + 5 * 7 * 17 + 7 * 7 * 19)
     compare(tf[i, i], 11 + 19)
-    compare(tf[i, j]*(tf[j, i]+outer(vf, vf)[i, j]), (5*5+11)*11 + (7*5+17)*13 + (7*5+13)*17 + (7*7+19)*19)
+    compare(
+        tf[i, j] * (tf[j, i] + outer(vf, vf)[i, j]),
+        (5 * 5 + 11) * 11 + (7 * 5 + 17) * 13 + (7 * 5 + 13) * 17 + (7 * 7 + 19) * 19,
+    )
     compare(as_tensor(as_tensor(tf[i, j], (i, j))[k, l], (l, k))[i, i], 11 + 19)
 
 
@@ -216,8 +241,8 @@ def test_expand_indices_derivatives(self, fixt):
     # Basic derivatives
     compare(sf.dx(0), 0.3)
     compare(sf.dx(1), 0.31)
-    compare(sf.dx(i)*vf[i], 0.30*5 + 0.31*7)
-    compare(vf[j].dx(i)*vf[i].dx(j), 0.50*0.50 + 0.51*0.70 + 0.70*0.51 + 0.71*0.71)
+    compare(sf.dx(i) * vf[i], 0.30 * 5 + 0.31 * 7)
+    compare(vf[j].dx(i) * vf[i].dx(j), 0.50 * 0.50 + 0.51 * 0.70 + 0.70 * 0.51 + 0.71 * 0.71)
 
 
 def test_expand_indices_hyperelasticity(self, fixt):
@@ -240,25 +265,25 @@ def test_expand_indices_hyperelasticity(self, fixt):
     compare(F[1, 1], F11)
 
     J = det(F)
-    compare(J, (1 + 0.50)*(1 + 0.71) - 0.70*0.51)
+    compare(J, (1 + 0.50) * (1 + 0.71) - 0.70 * 0.51)
 
     # Strain tensors
-    C = F.T*F
+    C = F.T * F
     # Cij = sum_k Fki Fkj
-    C00 = F00*F00 + F10*F10
-    C01 = F00*F01 + F10*F11
-    C10 = F01*F00 + F11*F10
-    C11 = F01*F01 + F11*F11
+    C00 = F00 * F00 + F10 * F10
+    C01 = F00 * F01 + F10 * F11
+    C10 = F01 * F00 + F11 * F10
+    C11 = F01 * F01 + F11 * F11
     compare(C[0, 0], C00)
     compare(C[0, 1], C01)
     compare(C[1, 0], C10)
     compare(C[1, 1], C11)
 
-    E = (C-ident)/2
-    E00 = (C00-1)/2
-    E01 = (C01)/2
-    E10 = (C10)/2
-    E11 = (C11-1)/2
+    E = (C - ident) / 2
+    E00 = (C00 - 1) / 2
+    E01 = (C01) / 2
+    E10 = (C10) / 2
+    E11 = (C11 - 1) / 2
     compare(E[0, 0], E00)
     compare(E[0, 1], E01)
     compare(E[1, 0], E10)
@@ -270,8 +295,8 @@ def test_expand_indices_hyperelasticity(self, fixt):
     compare(Q, Qvalue)
 
     K = 0.5
-    psi = (K/2)*exp(Q)
-    compare(psi, 0.25*math.exp(Qvalue))
+    psi = (K / 2) * exp(Q)
+    compare(psi, 0.25 * math.exp(Qvalue))
 
 
 def test_expand_indices_div_grad(self, fixt):
@@ -291,18 +316,21 @@ def test_expand_indices_div_grad(self, fixt):
         Dvf = grad(vf)
         Lvf = div(Dvf)
         Lvf2 = dot(Lvf, Lvf)
-        pp = compute_form_data(Lvf2*dx).preprocessed_form.integrals()[0].integrand()
-        print(('vf', vf.ufl_shape, str(vf)))
-        print(('Dvf', Dvf.ufl_shape, str(Dvf)))
-        print(('Lvf', Lvf.ufl_shape, str(Lvf)))
-        print(('Lvf2', Lvf2.ufl_shape, str(Lvf2)))
-        print(('pp', pp.ufl_shape, str(pp)))
+        pp = compute_form_data(Lvf2 * dx).preprocessed_form.integrals()[0].integrand()
+        print(("vf", vf.ufl_shape, str(vf)))
+        print(("Dvf", Dvf.ufl_shape, str(Dvf)))
+        print(("Lvf", Lvf.ufl_shape, str(Lvf)))
+        print(("Lvf2", Lvf2.ufl_shape, str(Lvf2)))
+        print(("pp", pp.ufl_shape, str(pp)))
 
     a = div(grad(vf))
-    compare(dot(a, a), (0.20+0.40)**2 + (0.21+0.41)**2)
+    compare(dot(a, a), (0.20 + 0.40) ** 2 + (0.21 + 0.41) ** 2)
 
     a = div(grad(tf))
-    compare(inner(a, a), (10.00+11.00)**2 + (10.01+11.01)**2 + (10.10+11.10)**2 + (10.11+11.11)**2)
+    compare(
+        inner(a, a),
+        (10.00 + 11.00) ** 2 + (10.01 + 11.01) ** 2 + (10.10 + 11.10) ** 2 + (10.11 + 11.11) ** 2,
+    )
 
 
 def test_expand_indices_nabla_div_grad(self, fixt):
@@ -319,7 +347,10 @@ def test_expand_indices_nabla_div_grad(self, fixt):
     compare(a, 3.300 + 3.311)
 
     a = nabla_div(nabla_grad(vf))
-    compare(dot(a, a), (0.20+0.40)**2 + (0.21+0.41)**2)
+    compare(dot(a, a), (0.20 + 0.40) ** 2 + (0.21 + 0.41) ** 2)
 
     a = nabla_div(nabla_grad(tf))
-    compare(inner(a, a), (10.00+11.00)**2 + (10.01+11.01)**2 + (10.10+11.10)**2 + (10.11+11.11)**2)
+    compare(
+        inner(a, a),
+        (10.00 + 11.00) ** 2 + (10.01 + 11.01) ** 2 + (10.10 + 11.10) ** 2 + (10.11 + 11.11) ** 2,
+    )
diff --git a/test/test_external_operator.py b/test/test_external_operator.py
index 0cdebb422..27e5d102e 100644
--- a/test/test_external_operator.py
+++ b/test/test_external_operator.py
@@ -5,8 +5,25 @@
 
 import pytest
 
-from ufl import (Action, Argument, Coefficient, Constant, Form, FunctionSpace, Mesh, TestFunction, TrialFunction,
-                 action, adjoint, cos, derivative, dx, inner, sin, triangle)
+from ufl import (
+    Action,
+    Argument,
+    Coefficient,
+    Constant,
+    Form,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    action,
+    adjoint,
+    cos,
+    derivative,
+    dx,
+    inner,
+    sin,
+    triangle,
+)
 from ufl.algorithms import expand_derivatives
 from ufl.algorithms.apply_derivatives import apply_derivatives
 from ufl.core.external_operator import ExternalOperator
@@ -18,7 +35,7 @@
 
 @pytest.fixture
 def domain_2d():
-    return Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    return Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
 
 @pytest.fixture
@@ -62,13 +79,15 @@ def test_properties(V1):
     v1 = Argument(V1, 1)
 
     e = ExternalOperator(u, function_space=V1)
-    assert str(e) == 'e(w_0; v_0)'
+    assert str(e) == "e(w_0; v_0)"
 
     e = ExternalOperator(u, function_space=V1, derivatives=(1,))
-    assert str(e) == '∂e(w_0; v_0)/∂o1'
+    assert str(e) == "∂e(w_0; v_0)/∂o1"
 
-    e = ExternalOperator(u, r, 2 * s, t, function_space=V1, derivatives=(1, 0, 1, 2), argument_slots=(v0, v1))
-    assert str(e) == '∂e(w_0, w_1, 2 * w_2, w_3; v_1, v_0)/∂o1∂o3∂o4∂o4'
+    e = ExternalOperator(
+        u, r, 2 * s, t, function_space=V1, derivatives=(1, 0, 1, 2), argument_slots=(v0, v1)
+    )
+    assert str(e) == "∂e(w_0, w_1, 2 * w_2, w_3; v_1, v_0)/∂o1∂o3∂o4∂o4"
 
 
 def test_form(V1, V2):
@@ -82,7 +101,7 @@ def test_form(V1, V2):
     F = N * v * dx
     actual = derivative(F, u, u_hat)
 
-    vstar, = N.arguments()
+    (vstar,) = N.arguments()
     Nhat = TrialFunction(N.ufl_function_space())
 
     dNdu = N._ufl_expr_reconstruct_(u, m, derivatives=(1, 0), argument_slots=(vstar, u_hat))
@@ -96,7 +115,7 @@ def test_form(V1, V2):
     F = N * u * v * dx
     actual = derivative(F, u, u_hat)
 
-    vstar, = N.arguments()
+    (vstar,) = N.arguments()
     Nhat = TrialFunction(N.ufl_function_space())
 
     dNdu = N._ufl_expr_reconstruct_(u, m, derivatives=(1, 0), argument_slots=(vstar, u_hat))
@@ -126,8 +145,8 @@ def test_differentiation_procedure_action(V1, V2):
     assert N2.coefficients() == (s,)
 
     # Get v*
-    vstar_N1, = N1.arguments()
-    vstar_N2, = N2.arguments()
+    (vstar_N1,) = N1.arguments()
+    (vstar_N2,) = N2.arguments()
     assert vstar_N1.ufl_function_space().dual() == V1
     assert vstar_N2.ufl_function_space().dual() == V1
 
@@ -177,18 +196,23 @@ def test_differentiation_procedure_action(V1, V2):
 
     # Check argument slots
     assert dN1du.argument_slots() == (vstar_dN1du, u_hat)
-    assert dN2du.argument_slots() == (vstar_dN2du, - sin(s) * s_hat)
+    assert dN2du.argument_slots() == (vstar_dN2du, -sin(s) * s_hat)
 
 
 def test_extractions(domain_2d, V1):
-    from ufl.algorithms.analysis import (extract_arguments, extract_arguments_and_coefficients,
-                                         extract_base_form_operators, extract_coefficients, extract_constants)
+    from ufl.algorithms.analysis import (
+        extract_arguments,
+        extract_arguments_and_coefficients,
+        extract_base_form_operators,
+        extract_coefficients,
+        extract_constants,
+    )
 
     u = Coefficient(V1)
     c = Constant(domain_2d)
 
     e = ExternalOperator(u, c, function_space=V1)
-    vstar_e, = e.arguments()
+    (vstar_e,) = e.arguments()
 
     assert extract_coefficients(e) == [u]
     assert extract_arguments(e) == [vstar_e]
@@ -221,7 +245,7 @@ def test_extractions(domain_2d, V1):
 
     w = Coefficient(V1)
     e2 = ExternalOperator(w, e, function_space=V1)
-    vstar_e2, = e2.arguments()
+    (vstar_e2,) = e2.arguments()
 
     assert extract_coefficients(e2) == [u, w]
     assert extract_arguments(e2) == [vstar_e2, u_hat]
@@ -242,24 +266,23 @@ def get_external_operators(form_base):
     elif isinstance(form_base, BaseForm):
         return form_base.base_form_operators()
     else:
-        raise ValueError('Expecting FormBase argument!')
+        raise ValueError("Expecting FormBase argument!")
 
 
 def test_adjoint_action_jacobian(V1, V2, V3):
-
     u = Coefficient(V1)
     m = Coefficient(V2)
 
     # N(u, m; v*)
     N = ExternalOperator(u, m, function_space=V3)
-    vstar_N, = N.arguments()
+    (vstar_N,) = N.arguments()
 
     # Arguments for the Gateaux-derivative
     def u_hat(number):
-        return Argument(V1, number)   # V1: degree 1 # dFdu.arguments()[-1]
+        return Argument(V1, number)  # V1: degree 1 # dFdu.arguments()[-1]
 
     def m_hat(number):
-        return Argument(V2, number)   # V2: degree 2 # dFdm.arguments()[-1]
+        return Argument(V2, number)  # V2: degree 2 # dFdm.arguments()[-1]
 
     def vstar_N(number):
         return Argument(V3.dual(), number)  # V3: degree 3
@@ -273,7 +296,6 @@ def vstar_N(number):
     form_base_expressions = (N * dx, N * v2 * dx, N * v3 * dx)  # , N)
 
     for F in form_base_expressions:
-
         # Get test function
         v_F = F.arguments() if isinstance(F, Form) else ()
         # If we have a 0-form with an ExternalOperator: e.g. F = N * dx
@@ -331,7 +353,6 @@ def vstar_N(number):
 
 
 def test_multiple_external_operators(V1, V2):
-
     u = Coefficient(V1)
     m = Coefficient(V1)
     w = Coefficient(V2)
@@ -364,14 +385,18 @@ def test_multiple_external_operators(V1, V2):
     dFdN1 = inner(v_hat, v) * dx
     dFdN2 = inner(w_hat, v) * dx
     dFdN3 = inner(v_hat, v) * dx
-    dN1du = N1._ufl_expr_reconstruct_(u, m, derivatives=(1, 0), argument_slots=N1.arguments() + (v_hat,))
+    dN1du = N1._ufl_expr_reconstruct_(
+        u, m, derivatives=(1, 0), argument_slots=N1.arguments() + (v_hat,)
+    )
     dN3du = N3._ufl_expr_reconstruct_(u, derivatives=(1,), argument_slots=N3.arguments() + (v_hat,))
 
     assert dFdu == Action(dFdN1, dN1du) + Action(dFdN3, dN3du)
 
     # dFdm = Action(dFdN1, dN1dm)
     dFdm = expand_derivatives(derivative(F, m))
-    dN1dm = N1._ufl_expr_reconstruct_(u, m, derivatives=(0, 1), argument_slots=N1.arguments() + (v_hat,))
+    dN1dm = N1._ufl_expr_reconstruct_(
+        u, m, derivatives=(0, 1), argument_slots=N1.arguments() + (v_hat,)
+    )
 
     assert dFdm == Action(dFdN1, dN1dm)
 
@@ -397,23 +422,31 @@ def test_multiple_external_operators(V1, V2):
     #         Action(∂F/∂N4, Action(∂N4/∂N1, dN1/du))
     dFdu = expand_derivatives(derivative(F, u))
     dFdN4_partial = inner(v_hat, v) * dx
-    dN4dN1_partial = N4._ufl_expr_reconstruct_(N1, u, derivatives=(1, 0), argument_slots=N4.arguments() + (v_hat,))
-    dN4du_partial = N4._ufl_expr_reconstruct_(N1, u, derivatives=(0, 1), argument_slots=N4.arguments() + (v_hat,))
+    dN4dN1_partial = N4._ufl_expr_reconstruct_(
+        N1, u, derivatives=(1, 0), argument_slots=N4.arguments() + (v_hat,)
+    )
+    dN4du_partial = N4._ufl_expr_reconstruct_(
+        N1, u, derivatives=(0, 1), argument_slots=N4.arguments() + (v_hat,)
+    )
 
-    assert dFdu == Action(dFdN4_partial, Action(dN4dN1_partial, dN1du)) + Action(dFdN4_partial, dN4du_partial)
+    assert dFdu == Action(dFdN4_partial, Action(dN4dN1_partial, dN1du)) + Action(
+        dFdN4_partial, dN4du_partial
+    )
 
     # dFdm = Action(∂F/∂N4, Action(∂N4/∂N1, dN1/dm))
     dFdm = expand_derivatives(derivative(F, m))
 
     assert dFdm == Action(dFdN4_partial, Action(dN4dN1_partial, dN1dm))
 
-    # --- F = < N1(u, m; v*), v > + <N2(w; v*), v> + <N3(u; v*), v> + < N4(N1(u, m), u; v*), v > --- #
+    # --- F = < N1(u, m; v*), v > + <N2(w; v*), v> + <N3(u; v*), v> + <
+    # N4(N1(u, m), u; v*), v > --- #
 
     F = (inner(N1, v) + inner(N2, v) + inner(N3, v) + inner(N4, v)) * dx
 
     dFdu = expand_derivatives(derivative(F, u))
     assert dFdu == Action(dFdN1, dN1du) + Action(dFdN3, dN3du) + Action(
-        dFdN4_partial, Action(dN4dN1_partial, dN1du)) + Action(dFdN4_partial, dN4du_partial)
+        dFdN4_partial, Action(dN4dN1_partial, dN1du)
+    ) + Action(dFdN4_partial, dN4du_partial)
 
     dFdm = expand_derivatives(derivative(F, m))
     assert dFdm == Action(dFdN1, dN1dm) + Action(dFdN4_partial, Action(dN4dN1_partial, dN1dm))
@@ -421,7 +454,8 @@ def test_multiple_external_operators(V1, V2):
     dFdw = expand_derivatives(derivative(F, w))
     assert dFdw == Action(dFdN2, dN2dw)
 
-    # --- F = < N5(N4(N1(u, m), u), u; v*), v > + < N1(u, m; v*), v > + < u * N5(N4(N1(u, m), u), u; v*), v >--- #
+    # --- F = < N5(N4(N1(u, m), u), u; v*), v > + < N1(u, m; v*), v > +
+    # < u * N5(N4(N1(u, m), u), u; v*), v >--- #
 
     F = (inner(N5, v) + inner(N1, v) + inner(u * N5, v)) * dx
 
@@ -439,10 +473,17 @@ def test_multiple_external_operators(V1, V2):
     dFdu_partial = inner(w * N5, v) * dx
     dFdN1_partial = inner(w, v) * dx
     dFdN5_partial = (inner(w, v) + inner(u * w, v)) * dx
-    dN5dN4_partial = N5._ufl_expr_reconstruct_(N4, u, derivatives=(1, 0), argument_slots=N4.arguments() + (w,))
-    dN5du_partial = N5._ufl_expr_reconstruct_(N4, u, derivatives=(0, 1), argument_slots=N4.arguments() + (w,))
-    dN5du = Action(dN5dN4_partial, Action(dN4dN1_partial, dN1du)) + Action(
-        dN5dN4_partial, dN4du_partial) + dN5du_partial
+    dN5dN4_partial = N5._ufl_expr_reconstruct_(
+        N4, u, derivatives=(1, 0), argument_slots=N4.arguments() + (w,)
+    )
+    dN5du_partial = N5._ufl_expr_reconstruct_(
+        N4, u, derivatives=(0, 1), argument_slots=N4.arguments() + (w,)
+    )
+    dN5du = (
+        Action(dN5dN4_partial, Action(dN4dN1_partial, dN1du))
+        + Action(dN5dN4_partial, dN4du_partial)
+        + dN5du_partial
+    )
 
     dFdu = expand_derivatives(derivative(F, u))
     assert dFdu == dFdu_partial + Action(dFdN1_partial, dN1du) + Action(dFdN5_partial, dN5du)
diff --git a/test/test_ffcforms.py b/test/test_ffcforms.py
index 5ab8778ab..9b913947b 100755
--- a/test/test_ffcforms.py
+++ b/test/test_ffcforms.py
@@ -13,9 +13,36 @@
 # Examples copied from the FFC demo directory, examples contributed
 # by Johan Jansson, Kristian Oelgaard, Marie Rognes, and Garth Wells.
 
-from ufl import (Coefficient, Constant, Dx, FacetNormal, FunctionSpace, Mesh, TestFunction, TestFunctions,
-                 TrialFunction, TrialFunctions, VectorConstant, avg, curl, div, dot, ds, dS, dx, grad, i, inner, j,
-                 jump, lhs, rhs, sqrt, tetrahedron, triangle)
+from ufl import (
+    Coefficient,
+    Constant,
+    Dx,
+    FacetNormal,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TestFunctions,
+    TrialFunction,
+    TrialFunctions,
+    VectorConstant,
+    avg,
+    curl,
+    div,
+    dot,
+    dS,
+    ds,
+    dx,
+    grad,
+    i,
+    inner,
+    j,
+    jump,
+    lhs,
+    rhs,
+    sqrt,
+    tetrahedron,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import contravariant_piola, covariant_piola, identity_pullback
 from ufl.sobolevspace import H1, L2, HCurl, HDiv
@@ -23,7 +50,7 @@
 
 def testConstant():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -32,15 +59,15 @@ def testConstant():
     c = Constant(domain)
     d = VectorConstant(domain)
 
-    a = c * dot(grad(v), grad(u)) * dx  # noqa: F841
+    _ = c * dot(grad(v), grad(u)) * dx
 
     # FFC notation: L = dot(d, grad(v))*dx
-    L = inner(d, grad(v)) * dx  # noqa: F841
+    _ = inner(d, grad(v)) * dx
 
 
 def testElasticity():
-    element = FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -51,21 +78,21 @@ def eps(v):
         return grad(v) + (grad(v)).T
 
     # FFC notation: a = 0.25*dot(eps(v), eps(u))*dx
-    a = 0.25 * inner(eps(v), eps(u)) * dx  # noqa: F841
+    _ = 0.25 * inner(eps(v), eps(u)) * dx
 
 
 def testEnergyNorm():
     element = FiniteElement("Lagrange", tetrahedron, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = Coefficient(space)
-    a = (v * v + dot(grad(v), grad(v))) * dx  # noqa: F841
+    _ = (v * v + dot(grad(v), grad(v))) * dx
 
 
 def testEquation():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     k = 0.1
@@ -76,13 +103,13 @@ def testEquation():
 
     F = v * (u - u0) * dx + k * dot(grad(v), grad(0.5 * (u0 + u))) * dx
 
-    a = lhs(F)  # noqa: F841
-    L = rhs(F)  # noqa: F841
+    _ = lhs(F)
+    _ = rhs(F)
 
 
 def testFunctionOperators():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -92,12 +119,12 @@ def testFunctionOperators():
 
     # FFC notation: a = sqrt(1/modulus(1/f))*sqrt(g)*dot(grad(v), grad(u))*dx
     # + v*u*sqrt(f*g)*g*dx
-    a = sqrt(1 / abs(1 / f)) * sqrt(g) * dot(grad(v), grad(u)) * dx + v * u * sqrt(f * g) * g * dx  # noqa: F841
+    _ = sqrt(1 / abs(1 / f)) * sqrt(g) * dot(grad(v), grad(u)) * dx + v * u * sqrt(f * g) * g * dx
 
 
 def testHeat():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -107,19 +134,17 @@ def testHeat():
     f = Coefficient(space)
     k = Constant(domain)
 
-    a = v * u1 * dx + k * c * dot(grad(v), grad(u1)) * dx  # noqa: F841
-    L = v * u0 * dx + k * v * f * dx  # noqa: F841
+    _ = v * u1 * dx + k * c * dot(grad(v), grad(u1)) * dx
+    _ = v * u0 * dx + k * v * f * dx
 
 
 def testMass():
     element = FiniteElement("Lagrange", tetrahedron, 3, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
-
     v = TestFunction(space)
     u = TrialFunction(space)
-
-    a = v * u * dx  # noqa: F841
+    _ = v * u * dx
 
 
 def testMixedMixedElement():
@@ -129,40 +154,36 @@ def testMixedMixedElement():
 
 def testMixedPoisson():
     q = 1
-
-    BDM = FiniteElement("Brezzi-Douglas-Marini", triangle, q, (2, ), contravariant_piola, HDiv)
+    BDM = FiniteElement("Brezzi-Douglas-Marini", triangle, q, (2,), contravariant_piola, HDiv)
     DG = FiniteElement("Discontinuous Lagrange", triangle, q - 1, (), identity_pullback, L2)
 
     mixed_element = MixedElement([BDM, DG])
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, mixed_element)
 
     (tau, w) = TestFunctions(space)
     (sigma, u) = TrialFunctions(space)
-
     f = Coefficient(FunctionSpace(domain, DG))
-
-    a = (dot(tau, sigma) - div(tau) * u + w * div(sigma)) * dx  # noqa: F841
-    L = w * f * dx  # noqa: F841
+    _ = (dot(tau, sigma) - div(tau) * u + w * div(sigma)) * dx
+    _ = w * f * dx
 
 
 def testNavierStokes():
-    element = FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
     u = TrialFunction(space)
-
     w = Coefficient(space)
 
     # FFC notation: a = v[i]*w[j]*D(u[i], j)*dx
-    a = v[i] * w[j] * Dx(u[i], j) * dx  # noqa: F841
+    _ = v[i] * w[j] * Dx(u[i], j) * dx
 
 
 def testNeumannProblem():
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -171,23 +192,21 @@ def testNeumannProblem():
     g = Coefficient(space)
 
     # FFC notation: a = dot(grad(v), grad(u))*dx
-    a = inner(grad(v), grad(u)) * dx  # noqa: F841
+    _ = inner(grad(v), grad(u)) * dx
 
     # FFC notation: L = dot(v, f)*dx + dot(v, g)*ds
-    L = inner(v, f) * dx + inner(v, g) * ds  # noqa: F841
+    _ = inner(v, f) * dx + inner(v, g) * ds
 
 
 def testOptimization():
     element = FiniteElement("Lagrange", triangle, 3, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
-
     v = TestFunction(space)
     u = TrialFunction(space)
     f = Coefficient(space)
-
-    a = dot(grad(v), grad(u)) * dx  # noqa: F841
-    L = v * f * dx  # noqa: F841
+    _ = dot(grad(v), grad(u)) * dx
+    _ = v * f * dx
 
 
 def testP5tet():
@@ -200,20 +219,18 @@ def testP5tri():
 
 def testPoissonDG():
     element = FiniteElement("Discontinuous Lagrange", triangle, 1, (), identity_pullback, L2)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
     u = TrialFunction(space)
     f = Coefficient(space)
-
     n = FacetNormal(domain)
 
     # FFC notation: h = MeshSize(domain), not supported by UFL
     h = Constant(domain)
 
     gN = Coefficient(space)
-
     alpha = 4.0
     gamma = 8.0
 
@@ -229,17 +246,17 @@ def testPoissonDG():
     a = inner(grad(v), grad(u)) * dx
     a -= inner(avg(grad(v)), jump(u, n)) * dS
     a -= inner(jump(v, n), avg(grad(u))) * dS
-    a += alpha / h('+') * dot(jump(v, n), jump(u, n)) * dS
+    a += alpha / h("+") * dot(jump(v, n), jump(u, n)) * dS
     a -= inner(grad(v), u * n) * ds
     a -= inner(u * n, grad(u)) * ds
     a += gamma / h * v * u * ds
 
-    L = v * f * dx + v * gN * ds  # noqa: F841
+    _ = v * f * dx + v * gN * ds
 
 
 def testPoisson():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -247,13 +264,13 @@ def testPoisson():
     f = Coefficient(space)
 
     # Note: inner() also works
-    a = dot(grad(v), grad(u)) * dx  # noqa: F841
-    L = v * f * dx  # noqa: F841
+    _ = dot(grad(v), grad(u)) * dx
+    _ = v * f * dx
 
 
 def testPoissonSystem():
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -261,10 +278,10 @@ def testPoissonSystem():
     f = Coefficient(space)
 
     # FFC notation: a = dot(grad(v), grad(u))*dx
-    a = inner(grad(v), grad(u)) * dx  # noqa: F841
+    _ = inner(grad(v), grad(u)) * dx
 
     # FFC notation: L = dot(v, f)*dx
-    L = inner(v, f) * dx  # noqa: F841
+    _ = inner(v, f) * dx
 
 
 def testProjection():
@@ -273,11 +290,10 @@ def testProjection():
     # projection can be extended to handle also local projections.
 
     P1 = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, P1)
-
-    v = TestFunction(space)  # noqa: F841
-    f = Coefficient(space)  # noqa: F841
+    _ = TestFunction(space)
+    _ = Coefficient(space)
 
     # pi0 = Projection(P0)
     # pi1 = Projection(P1)
@@ -294,9 +310,9 @@ def testQuadratureElement():
     # sig = VectorQuadratureElement(triangle, 3)
 
     QE = FiniteElement("Quadrature", triangle, 3, (), identity_pullback, L2)
-    sig = FiniteElement("Quadrature", triangle, 3, (2, ), identity_pullback, L2)
+    sig = FiniteElement("Quadrature", triangle, 3, (2,), identity_pullback, L2)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -306,53 +322,48 @@ def testQuadratureElement():
     sig0 = Coefficient(FunctionSpace(domain, sig))
     f = Coefficient(space)
 
-    a = v.dx(i) * C * u.dx(i) * dx + v.dx(i) * 2 * u0 * u * u0.dx(i) * dx  # noqa: F841
-    L = v * f * dx - dot(grad(v), sig0) * dx  # noqa: F841
+    _ = v.dx(i) * C * u.dx(i) * dx + v.dx(i) * 2 * u0 * u * u0.dx(i) * dx
+    _ = v * f * dx - dot(grad(v), sig0) * dx
 
 
 def testStokes():
     # UFLException: Shape mismatch in sum.
 
-    P2 = FiniteElement("Lagrange", triangle, 2, (2, ), identity_pullback, H1)
+    P2 = FiniteElement("Lagrange", triangle, 2, (2,), identity_pullback, H1)
     P1 = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     TH = MixedElement([P2, P1])
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     th_space = FunctionSpace(domain, TH)
     p2_space = FunctionSpace(domain, P2)
 
     (v, q) = TestFunctions(th_space)
     (u, p) = TrialFunctions(th_space)
-
     f = Coefficient(p2_space)
 
     # FFC notation:
     # a = (dot(grad(v), grad(u)) - div(v)*p + q*div(u))*dx
-    a = (inner(grad(v), grad(u)) - div(v) * p + q * div(u)) * dx  # noqa: F841
-
-    L = dot(v, f) * dx  # noqa: F841
+    _ = (inner(grad(v), grad(u)) - div(v) * p + q * div(u)) * dx
+    _ = dot(v, f) * dx
 
 
 def testSubDomain():
     element = FiniteElement("Lagrange", tetrahedron, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
-
     f = Coefficient(space)
-
-    M = f * dx(2) + f * ds(5)  # noqa: F841
+    _ = f * dx(2) + f * ds(5)
 
 
 def testSubDomains():
     element = FiniteElement("Lagrange", tetrahedron, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
     u = TrialFunction(space)
-
     a = v * u * dx(0) + 10.0 * v * u * dx(1) + v * u * ds(0) + 2.0 * v * u * ds(1)
-    a += v('+') * u('+') * dS(0) + 4.3 * v('+') * u('+') * dS(1)
+    a += v("+") * u("+") * dS(0) + 4.3 * v("+") * u("+") * dS(1)
 
 
 def testTensorWeightedPoisson():
@@ -376,15 +387,14 @@ def testTensorWeightedPoisson():
     P1 = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     P0 = FiniteElement("Discontinuous Lagrange", triangle, 0, (2, 2), identity_pullback, L2)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     p1_space = FunctionSpace(domain, P1)
     p0_space = FunctionSpace(domain, P0)
 
     v = TestFunction(p1_space)
     u = TrialFunction(p1_space)
     C = Coefficient(p0_space)
-
-    a = inner(grad(v), C * grad(u)) * dx  # noqa: F841
+    _ = inner(grad(v), C * grad(u)) * dx
 
 
 def testVectorLaplaceGradCurl():
@@ -395,8 +405,12 @@ def HodgeLaplaceGradCurl(space, fspace):
 
         # FFC notation: a = (dot(tau, sigma) - dot(grad(tau), u) + dot(v,
         # grad(sigma)) + dot(curl(v), curl(u)))*dx
-        a = (inner(tau, sigma) - inner(grad(tau), u) +
-             inner(v, grad(sigma)) + inner(curl(v), curl(u))) * dx
+        a = (
+            inner(tau, sigma)
+            - inner(grad(tau), u)
+            + inner(v, grad(sigma))
+            + inner(curl(v), curl(u))
+        ) * dx
 
         # FFC notation: L = dot(v, f)*dx
         L = inner(v, f) * dx
@@ -409,10 +423,11 @@ def HodgeLaplaceGradCurl(space, fspace):
     GRAD = FiniteElement("Lagrange", shape, order, (), identity_pullback, H1)
 
     # FFC notation: CURL = FiniteElement("Nedelec", shape, order-1)
-    CURL = FiniteElement("N1curl", shape, order, (3, ), covariant_piola, HCurl)
+    CURL = FiniteElement("N1curl", shape, order, (3,), covariant_piola, HCurl)
 
-    VectorLagrange = FiniteElement("Lagrange", shape, order + 1, (3, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", shape, 1, (3, ), identity_pullback, H1))
+    VectorLagrange = FiniteElement("Lagrange", shape, order + 1, (3,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", shape, 1, (3,), identity_pullback, H1))
 
-    [a, L] = HodgeLaplaceGradCurl(FunctionSpace(domain, MixedElement([GRAD, CURL])),
-                                  FunctionSpace(domain, VectorLagrange))
+    [a, L] = HodgeLaplaceGradCurl(
+        FunctionSpace(domain, MixedElement([GRAD, CURL])), FunctionSpace(domain, VectorLagrange)
+    )
diff --git a/test/test_form.py b/test/test_form.py
index 30ca5117a..e83abcfcf 100755
--- a/test/test_form.py
+++ b/test/test_form.py
@@ -1,7 +1,23 @@
 import pytest
 
-from ufl import (Coefficient, Cofunction, Form, FormSum, FunctionSpace, Mesh, SpatialCoordinate, TestFunction,
-                 TrialFunction, dot, ds, dx, grad, inner, nabla_grad, triangle)
+from ufl import (
+    Coefficient,
+    Cofunction,
+    Form,
+    FormSum,
+    FunctionSpace,
+    Mesh,
+    SpatialCoordinate,
+    TestFunction,
+    TrialFunction,
+    dot,
+    ds,
+    dx,
+    grad,
+    inner,
+    nabla_grad,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.form import BaseForm
 from ufl.pullback import identity_pullback
@@ -18,7 +34,7 @@ def element():
 @pytest.fixture
 def domain():
     cell = triangle
-    return Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    return Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
 
 
 @pytest.fixture
@@ -44,7 +60,7 @@ def stiffness(domain):
 @pytest.fixture
 def convection(domain):
     cell = triangle
-    element = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
+    element = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
     u = TrialFunction(space)
@@ -74,7 +90,7 @@ def boundary_load(domain):
 
 def test_form_arguments(mass, stiffness, convection, load):
     v, u = mass.arguments()
-    f, = load.coefficients()
+    (f,) = load.coefficients()
 
     assert v.number() == 0
     assert u.number() == 1
@@ -104,7 +120,7 @@ def test_form_coefficients(element, domain):
 def test_form_domains():
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     V = FunctionSpace(domain, element)
 
     v = TestFunction(V)
@@ -136,32 +152,33 @@ def test_form_integrals(mass, boundary_load):
 
 def test_form_call():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     V = FunctionSpace(domain, element)
     v = TestFunction(V)
     u = TrialFunction(V)
     f = Coefficient(V)
     g = Coefficient(V)
-    a = g*inner(grad(v), grad(u))*dx
+    a = g * inner(grad(v), grad(u)) * dx
     M = a(f, f, coefficients={g: 1})
-    assert M == grad(f)**2*dx
+    assert M == grad(f) ** 2 * dx
 
     import sys
+
     if sys.version_info.major >= 3 and sys.version_info.minor >= 5:
-        a = u*v*dx
+        a = u * v * dx
         M = eval("(a @ f) @ g")
-        assert M == g*f*dx
+        assert M == g * f * dx
 
 
 def test_formsum(mass):
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     V = FunctionSpace(domain, element)
     v = Cofunction(V.dual())
 
     assert v + mass
     assert mass + v
-    assert isinstance((mass+v), FormSum)
+    assert isinstance((mass + v), FormSum)
 
     assert len((mass + v + v).components()) == 3
     # Variational forms are summed appropriately
@@ -169,7 +186,7 @@ def test_formsum(mass):
 
     assert v - mass
     assert mass - v
-    assert isinstance((mass+v), FormSum)
+    assert isinstance((mass + v), FormSum)
 
     assert -v
     assert isinstance(-v, BaseForm)
diff --git a/test/test_illegal.py b/test/test_illegal.py
index 9931946a4..acc2d33d5 100755
--- a/test/test_illegal.py
+++ b/test/test_illegal.py
@@ -15,12 +15,12 @@ def selement():
 
 @pytest.fixture
 def velement():
-    return FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
+    return FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
 
 
 @pytest.fixture
 def domain():
-    return Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    return Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
 
 @pytest.fixture
diff --git a/test/test_indexing.py b/test/test_indexing.py
index 4ffdc7eb5..8b4d69d29 100755
--- a/test/test_indexing.py
+++ b/test/test_indexing.py
@@ -9,7 +9,7 @@
 
 @pytest.fixture
 def domain():
-    return Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    return Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
 
 @pytest.fixture
diff --git a/test/test_indices.py b/test/test_indices.py
index 52ef28cf1..ec85f7aa0 100755
--- a/test/test_indices.py
+++ b/test/test_indices.py
@@ -1,85 +1,106 @@
 import pytest
 
-from ufl import (Argument, Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, as_matrix, as_tensor,
-                 as_vector, cos, dx, exp, i, indices, j, k, l, outer, sin, triangle)
+from ufl import (
+    Argument,
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    as_matrix,
+    as_tensor,
+    as_vector,
+    cos,
+    dx,
+    exp,
+    i,
+    indices,
+    j,
+    k,
+    l,
+    outer,
+    sin,
+    triangle,
+)
 from ufl.classes import IndexSum
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
 
-# TODO: add more expressions to test as many possible combinations of index notation as feasible...
+# TODO: add more expressions to test as many possible combinations of
+# index notation as feasible...
 
 
 def test_vector_indices(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     u = Argument(space, 2)
     f = Coefficient(space)
-    u[i]*f[i]*dx
-    u[j]*f[j]*dx
+    u[i] * f[i] * dx
+    u[j] * f[j] * dx
 
 
 def test_tensor_indices(self):
     element = FiniteElement("Lagrange", triangle, 1, (2, 2), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     u = Argument(space, 2)
     f = Coefficient(space)
-    u[i, j]*f[i, j]*dx
-    u[j, i]*f[i, j]*dx
-    u[j, i]*f[j, i]*dx
+    u[i, j] * f[i, j] * dx
+    u[j, i] * f[i, j] * dx
+    u[j, i] * f[j, i] * dx
     with pytest.raises(BaseException):
-        (u[i, i]+f[j, i])*dx
+        (u[i, i] + f[j, i]) * dx
 
 
 def test_indexed_sum1(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     u = Argument(space, 2)
     f = Coefficient(space)
-    a = u[i]+f[i]
+    a = u[i] + f[i]
     with pytest.raises(BaseException):
-        a*dx
+        a * dx
 
 
 def test_indexed_sum2(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = Argument(space, 2)
     u = Argument(space, 3)
     f = Coefficient(space)
-    a = u[j]+f[j]+v[j]+2*v[j]+exp(u[i]*u[i])/2*f[j]
+    a = u[j] + f[j] + v[j] + 2 * v[j] + exp(u[i] * u[i]) / 2 * f[j]
     with pytest.raises(BaseException):
-        a*dx
+        a * dx
 
 
 def test_indexed_sum3(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     u = Argument(space, 2)
     f = Coefficient(space)
     with pytest.raises(BaseException):
-        u[i]+f[j]
+        u[i] + f[j]
 
 
 def test_indexed_function1(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = Argument(space, 2)
     u = Argument(space, 3)
     f = Coefficient(space)
-    aarg = (u[i]+f[i])*v[i]
-    exp(aarg)*dx
+    aarg = (u[i] + f[i]) * v[i]
+    exp(aarg) * dx
 
 
 def test_indexed_function2(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = Argument(space, 2)
     u = Argument(space, 3)
@@ -95,19 +116,19 @@ def test_indexed_function2(self):
 
 
 def test_indexed_function3(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     Argument(space, 2)
     u = Argument(space, 3)
     f = Coefficient(space)
     with pytest.raises(BaseException):
-        sin(u[i] + f[i])*dx
+        sin(u[i] + f[i]) * dx
 
 
 def test_vector_from_indices(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
     u = TrialFunction(space)
@@ -124,14 +145,14 @@ def test_vector_from_indices(self):
 
 
 def test_matrix_from_indices(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
     u = TrialFunction(space)
 
-    A = as_matrix(u[i]*v[j], (i, j))
-    B = as_matrix(v[k]*v[k]*u[i]*v[j], (j, i))
+    A = as_matrix(u[i] * v[j], (i, j))
+    B = as_matrix(v[k] * v[k] * u[i] * v[j], (j, i))
     C = A + A
     C = B + B
     D = A + B
@@ -142,8 +163,8 @@ def test_matrix_from_indices(self):
 
 
 def test_vector_from_list(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
     u = TrialFunction(space)
@@ -156,8 +177,8 @@ def test_vector_from_list(self):
 
 
 def test_matrix_from_list(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
     u = TrialFunction(space)
@@ -165,7 +186,7 @@ def test_matrix_from_list(self):
     # create matrix from list
     A = as_matrix([[u[0], u[1]], [v[0], v[1]]])
     # create matrix from indices
-    B = as_matrix((v[k]*v[k]) * u[i]*v[j], (j, i))
+    B = as_matrix((v[k] * v[k]) * u[i] * v[j], (j, i))
     # Test addition
     C = A + A
     C = B + B
@@ -177,8 +198,8 @@ def test_matrix_from_list(self):
 
 
 def test_tensor(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
     u = TrialFunction(space)
@@ -186,7 +207,7 @@ def test_tensor(self):
     g = Coefficient(space)
 
     # define the components of a fourth order tensor
-    Cijkl = u[i]*v[j]*f[k]*g[l]
+    Cijkl = u[i] * v[j] * f[k] * g[l]
     assert len(Cijkl.ufl_shape) == 0
     assert set(Cijkl.ufl_free_indices) == {i.count(), j.count(), k.count(), l.count()}
 
@@ -205,7 +226,7 @@ def test_tensor(self):
 
     # legal?
     vv = as_vector([u[i], v[i]])
-    f[i]*vv  # this is well defined: ww = sum_i <f_i*u_i, f_i*v_i>
+    f[i] * vv  # this is well defined: ww = sum_i <f_i*u_i, f_i*v_i>
 
     # illegal
     with pytest.raises(BaseException):
@@ -217,8 +238,8 @@ def test_tensor(self):
 
 
 def test_indexed(self):
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
     u = TrialFunction(space)
@@ -238,8 +259,8 @@ def test_indexed(self):
 
 def test_spatial_derivative(self):
     cell = triangle
-    element = FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
     u = TrialFunction(space)
@@ -256,7 +277,7 @@ def test_spatial_derivative(self):
     self.assertNotIsInstance(a, IndexSum)
     assert a.ufl_shape == ()
 
-    a = (v[i]*u[j]).dx(i, j)
+    a = (v[i] * u[j]).dx(i, j)
     self.assertSameIndices(a, ())
     self.assertIsInstance(a, IndexSum)
     assert a.ufl_shape == ()
@@ -272,7 +293,7 @@ def test_spatial_derivative(self):
     self.assertNotIsInstance(a, IndexSum)
     assert a.ufl_shape == ()
 
-    a = (v[i]*u[j]).dx(0, 1)
+    a = (v[i] * u[j]).dx(0, 1)
     assert set(a.ufl_free_indices) == {i.count(), j.count()}
     self.assertNotIsInstance(a, IndexSum)
     assert a.ufl_shape == ()
diff --git a/test/test_interpolate.py b/test/test_interpolate.py
index 71f3cd145..877f55a35 100644
--- a/test/test_interpolate.py
+++ b/test/test_interpolate.py
@@ -5,11 +5,31 @@
 
 import pytest
 
-from ufl import (Action, Adjoint, Argument, Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, action,
-                 adjoint, derivative, dx, grad, inner, replace, triangle)
+from ufl import (
+    Action,
+    Adjoint,
+    Argument,
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    action,
+    adjoint,
+    derivative,
+    dx,
+    grad,
+    inner,
+    replace,
+    triangle,
+)
 from ufl.algorithms.ad import expand_derivatives
-from ufl.algorithms.analysis import (extract_arguments, extract_arguments_and_coefficients, extract_base_form_operators,
-                                     extract_coefficients)
+from ufl.algorithms.analysis import (
+    extract_arguments,
+    extract_arguments_and_coefficients,
+    extract_base_form_operators,
+    extract_coefficients,
+)
 from ufl.algorithms.expand_indices import expand_indices
 from ufl.core.interpolate import Interpolate
 from ufl.finiteelement import FiniteElement
@@ -19,7 +39,7 @@
 
 @pytest.fixture
 def domain_2d():
-    return Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    return Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
 
 
 @pytest.fixture
@@ -35,7 +55,6 @@ def V2(domain_2d):
 
 
 def test_symbolic(V1, V2):
-
     # Set dual of V2
     V2_dual = V2.dual()
 
@@ -51,7 +70,6 @@ def test_symbolic(V1, V2):
 
 
 def test_action_adjoint(V1, V2):
-
     # Set dual of V2
     V2_dual = V2.dual()
     vstar = Argument(V2_dual, 0)
@@ -78,7 +96,6 @@ def test_action_adjoint(V1, V2):
 
 
 def test_differentiation(V1, V2):
-
     u = Coefficient(V1)
     v = TestFunction(V1)
 
@@ -133,7 +150,6 @@ def test_differentiation(V1, V2):
 
 
 def test_extract_base_form_operators(V1, V2):
-
     u = Coefficient(V1)
     uhat = TrialFunction(V1)
     vstar = Argument(V2.dual(), 0)
diff --git a/test/test_lhs_rhs.py b/test/test_lhs_rhs.py
index 2be0e584c..bb99eab3a 100755
--- a/test/test_lhs_rhs.py
+++ b/test/test_lhs_rhs.py
@@ -3,8 +3,23 @@
 # First added: 2011-11-09
 # Last changed: 2011-11-09
 
-from ufl import (Argument, Coefficient, Constant, FunctionSpace, Mesh, TestFunction, TrialFunction, action, derivative,
-                 ds, dS, dx, exp, interval, system)
+from ufl import (
+    Argument,
+    Coefficient,
+    Constant,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    action,
+    derivative,
+    dS,
+    ds,
+    dx,
+    exp,
+    interval,
+    system,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
@@ -12,7 +27,7 @@
 
 def test_lhs_rhs_simple():
     V = FiniteElement("Lagrange", interval, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", interval, 1, (1, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     v = TestFunction(space)
     u = TrialFunction(space)
@@ -41,13 +56,13 @@ def test_lhs_rhs_simple():
 
 def test_lhs_rhs_derivatives():
     V = FiniteElement("Lagrange", interval, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", interval, 1, (1, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     v = TestFunction(space)
     u = TrialFunction(space)
     f = Coefficient(space)
 
-    F0 = exp(f) * u * v * dx + v * dx + f * v * ds + exp(f)('+') * v * dS
+    F0 = exp(f) * u * v * dx + v * dx + f * v * ds + exp(f)("+") * v * dS
     a, L = system(F0)
     assert len(a.integrals()) == 1
     assert len(L.integrals()) == 3
@@ -58,7 +73,7 @@ def test_lhs_rhs_derivatives():
 
 def test_lhs_rhs_slightly_obscure():
     V = FiniteElement("Lagrange", interval, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", interval, 1, (1, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     u = TrialFunction(space)
     w = Argument(space, 2)
diff --git a/test/test_literals.py b/test/test_literals.py
index aed180b24..7e63c89bf 100755
--- a/test/test_literals.py
+++ b/test/test_literals.py
@@ -16,7 +16,8 @@ def test_zero(self):
     self.assertNotEqual(z1, 1.0)
     self.assertFalse(z1)
 
-    # If zero() == 0 is to be allowed, it must not have the same hash or it will collide with 0 as key in dicts...
+    # If zero() == 0 is to be allowed, it must not have the same hash or
+    # it will collide with 0 as key in dicts...
     self.assertNotEqual(hash(z1), hash(0.0))
     self.assertNotEqual(hash(z1), hash(0))
 
@@ -77,7 +78,7 @@ def test_scalar_sums(self):
     s = [as_ufl(i) for i in range(n)]
 
     for i in range(n):
-        self.assertNotEqual(s[i], i+1)
+        self.assertNotEqual(s[i], i + 1)
 
     for i in range(n):
         assert s[i] == i
@@ -98,9 +99,9 @@ def test_scalar_sums(self):
     assert s[1] + s[2] == 3
     assert s[1] + s[2] + s[3] == s[6]
     assert s[5] - s[2] == 3
-    assert 1*s[5] == 5
-    assert 2*s[5] == 10
-    assert s[6]/3 == 2
+    assert 1 * s[5] == 5
+    assert 2 * s[5] == 10
+    assert s[6] / 3 == 2
 
 
 def test_identity(self):
@@ -114,7 +115,7 @@ def test_permutation_symbol_3(self):
     for i in range(3):
         for j in range(3):
             for k in range(3):
-                value = (j-i)*(k-i)*(k-j)/2
+                value = (j - i) * (k - i) * (k - j) / 2
                 self.assertEqual(e[i, j, k], value)
     i, j, k = indices(3)
     self.assertIsInstance(e[i, j, k], Indexed)
@@ -125,17 +126,18 @@ def test_permutation_symbol_3(self):
 def test_permutation_symbol_n(self):
     for n in range(2, 5):  # tested with upper limit 7, but evaluation is a bit slow then
         e = PermutationSymbol(n)
-        assert e.ufl_shape == (n,)*n
+        assert e.ufl_shape == (n,) * n
         assert eval(repr(e)) == e
 
         ii = indices(n)
-        x = (0,)*n
-        nfac = product(m for m in range(1, n+1))
+        x = (0,) * n
+        nfac = product(m for m in range(1, n + 1))
         assert (e[ii] * e[ii])(x) == nfac
 
 
 def test_unit_dyads(self):
     from ufl.tensors import unit_matrices, unit_vectors
+
     ei, ej = unit_vectors(2)
     self.assertEqual(as_vector((1, 0)), ei)
     self.assertEqual(as_vector((0, 1)), ej)
diff --git a/test/test_measures.py b/test/test_measures.py
index 539151672..eaaffd745 100755
--- a/test/test_measures.py
+++ b/test/test_measures.py
@@ -60,18 +60,18 @@ def test_construct_forms_from_default_measures():
 
     # Check that we can create a basic form with default measure
     one = as_ufl(1)
-    one * dx(Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)))
+    one * dx(Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)))
 
 
 def test_foo():
-
     # Define a manifold domain, allows checking gdim/tdim mixup errors
     gdim = 3
     tdim = 2
     cell = Cell("triangle")
     mymesh = MockMesh(9)
-    mydomain = Mesh(FiniteElement("Lagrange", cell, 1, (gdim, ), identity_pullback, H1),
-                    ufl_id=9, cargo=mymesh)
+    mydomain = Mesh(
+        FiniteElement("Lagrange", cell, 1, (gdim,), identity_pullback, H1), ufl_id=9, cargo=mymesh
+    )
 
     assert cell.topological_dimension() == tdim
     assert cell.cellname() == "triangle"
@@ -87,10 +87,7 @@ def test_foo():
 
     # Test definition of a custom measure with explicit parameters
     metadata = {"opt": True}
-    mydx = Measure("dx",
-                   domain=mydomain,
-                   subdomain_id=3,
-                   metadata=metadata)
+    mydx = Measure("dx", domain=mydomain, subdomain_id=3, metadata=metadata)
     assert mydx.ufl_domain().ufl_id() == mydomain.ufl_id()
     assert mydx.metadata() == metadata
     M = f * mydx
@@ -120,7 +117,7 @@ def test_foo():
     # Set subdomain_id to (2,3), still no domain set
     dx23 = dx((2, 3))
     assert dx23.ufl_domain() is None
-    assert dx23.subdomain_id(), (2 == 3)
+    assert dx23.subdomain_id(), 2 == 3
 
     # Map metadata to metadata, ffc interprets as before
     dxm = dx(metadata={"dummy": 123})
@@ -161,29 +158,29 @@ def test_foo():
 
     # Create some forms with these measures (used in checks below):
     Mx = f * dxd
-    Ms = f ** 2 * dsd
-    MS = f('+') * dSd
-    M = f * dxd + f ** 2 * dsd + f('+') * dSd
+    Ms = f**2 * dsd
+    MS = f("+") * dSd
+    M = f * dxd + f**2 * dsd + f("+") * dSd
 
     # Test extracting domain data from a form for each measure:
-    domain, = Mx.ufl_domains()
+    (domain,) = Mx.ufl_domains()
     assert domain.ufl_id() == mydomain.ufl_id()
     assert domain.ufl_cargo() == mymesh
     assert len(Mx.subdomain_data()[mydomain]["cell"]) == 1
     assert Mx.subdomain_data()[mydomain]["cell"][0] == cell_domains
 
-    domain, = Ms.ufl_domains()
+    (domain,) = Ms.ufl_domains()
     assert domain.ufl_cargo() == mymesh
     assert len(Ms.subdomain_data()[mydomain]["exterior_facet"]) == 1
     assert Ms.subdomain_data()[mydomain]["exterior_facet"][0] == exterior_facet_domains
 
-    domain, = MS.ufl_domains()
+    (domain,) = MS.ufl_domains()
     assert domain.ufl_cargo() == mymesh
     assert len(MS.subdomain_data()[mydomain]["interior_facet"]) == 1
     assert MS.subdomain_data()[mydomain]["interior_facet"][0] == interior_facet_domains
 
     # Test joining of these domains in a single form
-    domain, = M.ufl_domains()
+    (domain,) = M.ufl_domains()
     assert domain.ufl_cargo() == mymesh
     assert len(M.subdomain_data()[mydomain]["cell"]) == 1
     assert M.subdomain_data()[mydomain]["cell"][0] == cell_domains
diff --git a/test/test_mixed_function_space.py b/test/test_mixed_function_space.py
index 6e3e68356..476be6271 100644
--- a/test/test_mixed_function_space.py
+++ b/test/test_mixed_function_space.py
@@ -1,8 +1,17 @@
 __authors__ = "Cecile Daversin Catty"
 __date__ = "2019-03-26 -- 2019-03-26"
 
-from ufl import (FunctionSpace, Measure, Mesh, MixedFunctionSpace, TestFunctions, TrialFunctions, interval, tetrahedron,
-                 triangle)
+from ufl import (
+    FunctionSpace,
+    Measure,
+    Mesh,
+    MixedFunctionSpace,
+    TestFunctions,
+    TrialFunctions,
+    interval,
+    tetrahedron,
+    triangle,
+)
 from ufl.algorithms.formsplitter import extract_blocks
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
@@ -11,9 +20,9 @@
 
 def test_mixed_functionspace(self):
     # Domains
-    domain_3d = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
-    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
-    domain_1d = Mesh(FiniteElement("Lagrange", interval, 1, (1, ), identity_pullback, H1))
+    domain_3d = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
+    domain_2d = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
+    domain_1d = Mesh(FiniteElement("Lagrange", interval, 1, (1,), identity_pullback, H1))
     # Finite elements
     f_1d = FiniteElement("Lagrange", interval, 1, (), identity_pullback, H1)
     f_2d = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
@@ -42,20 +51,20 @@ def test_mixed_functionspace(self):
 
     # Mixed variational form
     # LHS
-    a_11 = u_1d*v_1d*dx1
-    a_22 = u_2d*v_2d*dx2
-    a_33 = u_3d*v_3d*dx3
-    a_21 = u_2d*v_1d*dx1
-    a_12 = u_1d*v_2d*dx1
-    a_32 = u_3d*v_2d*dx2
-    a_23 = u_2d*v_3d*dx2
-    a_31 = u_3d*v_1d*dx1
-    a_13 = u_1d*v_3d*dx1
+    a_11 = u_1d * v_1d * dx1
+    a_22 = u_2d * v_2d * dx2
+    a_33 = u_3d * v_3d * dx3
+    a_21 = u_2d * v_1d * dx1
+    a_12 = u_1d * v_2d * dx1
+    a_32 = u_3d * v_2d * dx2
+    a_23 = u_2d * v_3d * dx2
+    a_31 = u_3d * v_1d * dx1
+    a_13 = u_1d * v_3d * dx1
     a = a_11 + a_22 + a_33 + a_21 + a_12 + a_32 + a_23 + a_31 + a_13
     # RHS
-    f_1 = v_1d*dx1
-    f_2 = v_2d*dx2
-    f_3 = v_3d*dx3
+    f_1 = v_1d * dx1
+    f_2 = v_2d * dx2
+    f_3 = v_3d * dx3
     f = f_1 + f_2 + f_3
 
     # Check extract_block algorithm
diff --git a/test/test_new_ad.py b/test/test_new_ad.py
index 7fc69e850..38ef9de44 100755
--- a/test/test_new_ad.py
+++ b/test/test_new_ad.py
@@ -1,7 +1,32 @@
-from ufl import (CellVolume, Coefficient, Constant, FacetNormal, FunctionSpace, Identity, Mesh, SpatialCoordinate,
-                 TestFunction, VectorConstant, as_ufl, cos, derivative, diff, exp, grad, ln, sin, tan, triangle,
-                 variable, zero)
-from ufl.algorithms.apply_derivatives import GenericDerivativeRuleset, GradRuleset, apply_derivatives
+from ufl import (
+    CellVolume,
+    Coefficient,
+    Constant,
+    FacetNormal,
+    FunctionSpace,
+    Identity,
+    Mesh,
+    SpatialCoordinate,
+    TestFunction,
+    VectorConstant,
+    as_ufl,
+    cos,
+    derivative,
+    diff,
+    exp,
+    grad,
+    ln,
+    sin,
+    tan,
+    triangle,
+    variable,
+    zero,
+)
+from ufl.algorithms.apply_derivatives import (
+    GenericDerivativeRuleset,
+    GradRuleset,
+    apply_derivatives,
+)
 from ufl.algorithms.renumbering import renumber_indices
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
@@ -21,7 +46,7 @@ def test_apply_derivatives_doesnt_change_expression_without_derivatives():
     V0 = FiniteElement("Discontinuous Lagrange", cell, 0, (), identity_pullback, L2)
     V1 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1))
     v0_space = FunctionSpace(domain, V0)
     v1_space = FunctionSpace(domain, V1)
 
@@ -50,7 +75,7 @@ def test_apply_derivatives_doesnt_change_expression_without_derivatives():
 
     # Expressions
     e0 = f0 + f1
-    e1 = v0 * (f1/3 - f0**2)
+    e1 = v0 * (f1 / 3 - f0**2)
     e2 = exp(sin(cos(tan(ln(x[0])))))
     expressions = [e0, e1, e2]
 
@@ -73,7 +98,7 @@ def test_literal_derivatives_are_zero():
 
     # Generic ruleset handles literals directly:
     for lit in literals:
-        for sh in [(), (d,), (d, d+1)]:
+        for sh in [(), (d,), (d, d + 1)]:
             assert GenericDerivativeRuleset(sh)(lit) == zero(lit.ufl_shape + sh)
 
     # Variables
@@ -89,7 +114,7 @@ def test_literal_derivatives_are_zero():
 
     V0 = FiniteElement("Discontinuous Lagrange", cell, 0, (), identity_pullback, L2)
     V1 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1))
     v0_space = FunctionSpace(domain, V0)
     v1_space = FunctionSpace(domain, V1)
     u0 = Coefficient(v0_space)
@@ -115,11 +140,11 @@ def test_grad_ruleset():
     V0 = FiniteElement("Discontinuous Lagrange", cell, 0, (), identity_pullback, L2)
     V1 = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
     V2 = FiniteElement("Lagrange", cell, 2, (), identity_pullback, H1)
-    W0 = FiniteElement("Discontinuous Lagrange", cell, 0, (2, ), identity_pullback, L2)
-    W1 = FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1)
-    W2 = FiniteElement("Lagrange", cell, 2, (d, ), identity_pullback, H1)
+    W0 = FiniteElement("Discontinuous Lagrange", cell, 0, (2,), identity_pullback, L2)
+    W1 = FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1)
+    W2 = FiniteElement("Lagrange", cell, 2, (d,), identity_pullback, H1)
 
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1))
     v0_space = FunctionSpace(domain, V0)
     v1_space = FunctionSpace(domain, V1)
     v2_space = FunctionSpace(domain, V2)
@@ -197,10 +222,14 @@ def test_grad_ruleset():
     assert renumber_indices(apply_derivatives(grad(vf2[1])[0])) == renumber_indices(grad(vf2)[1, 0])
 
     # Grad of gradually more complex expressions
-    assert apply_derivatives(grad(2*f0)) == zero((d,))
-    assert renumber_indices(apply_derivatives(grad(2*f1))) == renumber_indices(2*grad(f1))
-    assert renumber_indices(apply_derivatives(grad(sin(f1)))) == renumber_indices(cos(f1) * grad(f1))
-    assert renumber_indices(apply_derivatives(grad(cos(f1)))) == renumber_indices(-sin(f1) * grad(f1))
+    assert apply_derivatives(grad(2 * f0)) == zero((d,))
+    assert renumber_indices(apply_derivatives(grad(2 * f1))) == renumber_indices(2 * grad(f1))
+    assert renumber_indices(apply_derivatives(grad(sin(f1)))) == renumber_indices(
+        cos(f1) * grad(f1)
+    )
+    assert renumber_indices(apply_derivatives(grad(cos(f1)))) == renumber_indices(
+        -sin(f1) * grad(f1)
+    )
 
 
 def test_variable_ruleset():
diff --git a/test/test_pickle.py b/test/test_pickle.py
index 5ab4026f7..e2611c48a 100755
--- a/test/test_pickle.py
+++ b/test/test_pickle.py
@@ -10,9 +10,37 @@
 
 import pickle
 
-from ufl import (Coefficient, Constant, Dx, FacetNormal, FunctionSpace, Identity, Mesh, TestFunction, TestFunctions,
-                 TrialFunction, TrialFunctions, VectorConstant, avg, curl, div, dot, dS, ds, dx, grad, i, inner, j,
-                 jump, lhs, rhs, sqrt, tetrahedron, triangle)
+from ufl import (
+    Coefficient,
+    Constant,
+    Dx,
+    FacetNormal,
+    FunctionSpace,
+    Identity,
+    Mesh,
+    TestFunction,
+    TestFunctions,
+    TrialFunction,
+    TrialFunctions,
+    VectorConstant,
+    avg,
+    curl,
+    div,
+    dot,
+    dS,
+    ds,
+    dx,
+    grad,
+    i,
+    inner,
+    j,
+    jump,
+    lhs,
+    rhs,
+    sqrt,
+    tetrahedron,
+    triangle,
+)
 from ufl.algorithms import compute_form_data
 from ufl.finiteelement import FiniteElement, MixedElement
 from ufl.pullback import contravariant_piola, covariant_piola, identity_pullback
@@ -23,7 +51,7 @@
 
 def testConstant():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -47,8 +75,8 @@ def testConstant():
 
 
 def testElasticity():
-    element = FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -69,7 +97,7 @@ def eps(v):
 
 def testEnergyNorm():
     element = FiniteElement("Lagrange", tetrahedron, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = Coefficient(space)
@@ -83,7 +111,7 @@ def testEnergyNorm():
 
 def testEquation():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     k = 0.1
@@ -108,7 +136,7 @@ def testEquation():
 
 def testFunctionOperators():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -118,8 +146,7 @@ def testFunctionOperators():
 
     # FFC notation: a = sqrt(1/modulus(1/f))*sqrt(g)*dot(grad(v), grad(u))*dx
     # + v*u*sqrt(f*g)*g*dx
-    a = sqrt(1 / abs(1 / f)) * sqrt(g) * \
-        dot(grad(v), grad(u)) * dx + v * u * sqrt(f * g) * g * dx
+    a = sqrt(1 / abs(1 / f)) * sqrt(g) * dot(grad(v), grad(u)) * dx + v * u * sqrt(f * g) * g * dx
 
     a_pickle = pickle.dumps(a, p)
     a_restore = pickle.loads(a_pickle)
@@ -129,7 +156,7 @@ def testFunctionOperators():
 
 def testHeat():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -153,7 +180,7 @@ def testHeat():
 
 def testMass():
     element = FiniteElement("Lagrange", tetrahedron, 3, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -181,11 +208,11 @@ def testMixedMixedElement():
 def testMixedPoisson():
     q = 1
 
-    BDM = FiniteElement("Brezzi-Douglas-Marini", triangle, q, (2, ), contravariant_piola, HDiv)
+    BDM = FiniteElement("Brezzi-Douglas-Marini", triangle, q, (2,), contravariant_piola, HDiv)
     DG = FiniteElement("Discontinuous Lagrange", triangle, q - 1, (), identity_pullback, L2)
 
     mixed_element = MixedElement([BDM, DG])
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     mixed_space = FunctionSpace(domain, mixed_element)
     dg_space = FunctionSpace(domain, DG)
 
@@ -207,8 +234,8 @@ def testMixedPoisson():
 
 
 def testNavierStokes():
-    element = FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -226,8 +253,8 @@ def testNavierStokes():
 
 
 def testNeumannProblem():
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -252,7 +279,7 @@ def testNeumannProblem():
 
 def testOptimization():
     element = FiniteElement("Lagrange", triangle, 3, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -289,7 +316,7 @@ def testP5tri():
 
 def testPoissonDG():
     element = FiniteElement("Discontinuous Lagrange", triangle, 1, (), identity_pullback, L2)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -315,13 +342,15 @@ def testPoissonDG():
     #    - dot(mult(v,n), grad(u))*ds \
     #    + gamma/h*v*u*ds
 
-    a = inner(grad(v), grad(u)) * dx \
-        - inner(avg(grad(v)), jump(u, n)) * dS \
-        - inner(jump(v, n), avg(grad(u))) * dS \
-        + alpha / h('+') * dot(jump(v, n), jump(u, n)) * dS \
-        - inner(grad(v), u * n) * ds \
-        - inner(u * n, grad(u)) * ds \
+    a = (
+        inner(grad(v), grad(u)) * dx
+        - inner(avg(grad(v)), jump(u, n)) * dS
+        - inner(jump(v, n), avg(grad(u))) * dS
+        + alpha / h("+") * dot(jump(v, n), jump(u, n)) * dS
+        - inner(grad(v), u * n) * ds
+        - inner(u * n, grad(u)) * ds
         + gamma / h * v * u * ds
+    )
 
     L = v * f * dx + v * gN * ds
 
@@ -336,7 +365,7 @@ def testPoissonDG():
 
 def testPoisson():
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -357,8 +386,8 @@ def testPoisson():
 
 
 def testPoissonSystem():
-    element = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    element = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
@@ -388,9 +417,9 @@ def testQuadratureElement():
     # sig = VectorQuadratureElement(triangle, 3)
 
     QE = FiniteElement("Quadrature", triangle, 3, (), identity_pullback, L2)
-    sig = FiniteElement("Quadrature", triangle, 3, (2, ), identity_pullback, L2)
+    sig = FiniteElement("Quadrature", triangle, 3, (2,), identity_pullback, L2)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     qe_space = FunctionSpace(domain, QE)
     sig_space = FunctionSpace(domain, sig)
@@ -417,11 +446,11 @@ def testQuadratureElement():
 def testStokes():
     # UFLException: Shape mismatch in sum.
 
-    P2 = FiniteElement("Lagrange", triangle, 2, (2, ), identity_pullback, H1)
+    P2 = FiniteElement("Lagrange", triangle, 2, (2,), identity_pullback, H1)
     P1 = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     TH = MixedElement([P2, P1])
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     th_space = FunctionSpace(domain, TH)
     p2_space = FunctionSpace(domain, P2)
 
@@ -447,7 +476,7 @@ def testStokes():
 
 def testSubDomain():
     element = FiniteElement("Lagrange", tetrahedron, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     f = Coefficient(space)
@@ -462,14 +491,20 @@ def testSubDomain():
 
 def testSubDomains():
     element = FiniteElement("Lagrange", tetrahedron, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
     u = TrialFunction(space)
 
-    a = v * u * dx(0) + 10.0 * v * u * dx(1) + v * u * ds(0) + 2.0 * v * u * \
-        ds(1) + v('+') * u('+') * dS(0) + 4.3 * v('+') * u('+') * dS(1)
+    a = (
+        v * u * dx(0)
+        + 10.0 * v * u * dx(1)
+        + v * u * ds(0)
+        + 2.0 * v * u * ds(1)
+        + v("+") * u("+") * dS(0)
+        + 4.3 * v("+") * u("+") * dS(1)
+    )
 
     a_pickle = pickle.dumps(a, p)
     a_restore = pickle.loads(a_pickle)
@@ -498,7 +533,7 @@ def testTensorWeightedPoisson():
     P1 = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
     P0 = FiniteElement("Discontinuous Lagrange", triangle, 0, (2, 2), identity_pullback, L2)
 
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     p1_space = FunctionSpace(domain, P1)
     p0_space = FunctionSpace(domain, P0)
 
@@ -522,8 +557,12 @@ def HodgeLaplaceGradCurl(space, fspace):
 
         # FFC notation: a = (dot(tau, sigma) - dot(grad(tau), u) + dot(v,
         # grad(sigma)) + dot(curl(v), curl(u)))*dx
-        a = (inner(tau, sigma) - inner(grad(tau), u) +
-             inner(v, grad(sigma)) + inner(curl(v), curl(u))) * dx
+        a = (
+            inner(tau, sigma)
+            - inner(grad(tau), u)
+            + inner(v, grad(sigma))
+            + inner(curl(v), curl(u))
+        ) * dx
 
         # FFC notation: L = dot(v, f)*dx
         L = inner(v, f) * dx
@@ -536,13 +575,14 @@ def HodgeLaplaceGradCurl(space, fspace):
     GRAD = FiniteElement("Lagrange", shape, order, (), identity_pullback, H1)
 
     # FFC notation: CURL = FiniteElement("Nedelec", shape, order-1)
-    CURL = FiniteElement("N1curl", shape, order, (3, ), covariant_piola, HCurl)
+    CURL = FiniteElement("N1curl", shape, order, (3,), covariant_piola, HCurl)
 
-    VectorLagrange = FiniteElement("Lagrange", shape, order + 1, (3, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", shape, 1, (3, ), identity_pullback, H1))
+    VectorLagrange = FiniteElement("Lagrange", shape, order + 1, (3,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", shape, 1, (3,), identity_pullback, H1))
 
-    [a, L] = HodgeLaplaceGradCurl(FunctionSpace(domain, MixedElement([GRAD, CURL])),
-                                  FunctionSpace(domain, VectorLagrange))
+    [a, L] = HodgeLaplaceGradCurl(
+        FunctionSpace(domain, MixedElement([GRAD, CURL])), FunctionSpace(domain, VectorLagrange)
+    )
 
     a_pickle = pickle.dumps(a, p)
     a_restore = pickle.loads(a_pickle)
@@ -562,7 +602,7 @@ def testIdentity():
 
 def testFormData():
     element = FiniteElement("Lagrange", tetrahedron, 3, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
 
     v = TestFunction(space)
diff --git a/test/test_piecewise_checks.py b/test/test_piecewise_checks.py
index f0b1955f6..baeb13c59 100755
--- a/test/test_piecewise_checks.py
+++ b/test/test_piecewise_checks.py
@@ -2,12 +2,37 @@
 
 import pytest
 
-from ufl import (Cell, CellDiameter, CellVolume, Circumradius, Coefficient, Constant, FacetArea, FacetNormal,
-                 FunctionSpace, Jacobian, JacobianDeterminant, JacobianInverse, MaxFacetEdgeLength, Mesh,
-                 MinFacetEdgeLength, SpatialCoordinate, TestFunction, hexahedron, interval, quadrilateral, tetrahedron,
-                 triangle)
+from ufl import (
+    Cell,
+    CellDiameter,
+    CellVolume,
+    Circumradius,
+    Coefficient,
+    Constant,
+    FacetArea,
+    FacetNormal,
+    FunctionSpace,
+    Jacobian,
+    JacobianDeterminant,
+    JacobianInverse,
+    MaxFacetEdgeLength,
+    Mesh,
+    MinFacetEdgeLength,
+    SpatialCoordinate,
+    TestFunction,
+    hexahedron,
+    interval,
+    quadrilateral,
+    tetrahedron,
+    triangle,
+)
 from ufl.checks import is_cellwise_constant
-from ufl.classes import CellCoordinate, FacetJacobian, FacetJacobianDeterminant, FacetJacobianInverse
+from ufl.classes import (
+    CellCoordinate,
+    FacetJacobian,
+    FacetJacobianDeterminant,
+    FacetJacobianInverse,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1, L2, HInf
@@ -22,15 +47,27 @@ def get_domains():
         tetrahedron,
         hexahedron,
     ]
-    return [Mesh(FiniteElement("Lagrange", cell, 1, (cell.topological_dimension(), ),
-                               identity_pullback, H1)) for cell in all_cells]
+    return [
+        Mesh(
+            FiniteElement(
+                "Lagrange", cell, 1, (cell.topological_dimension(),), identity_pullback, H1
+            )
+        )
+        for cell in all_cells
+    ]
 
 
 def get_nonlinear():
     domains_with_quadratic_coordinates = []
     for D in get_domains():
-        V = FiniteElement("Lagrange", D.ufl_cell(), 2, (D.ufl_cell().topological_dimension(), ),
-                          identity_pullback, H1)
+        V = FiniteElement(
+            "Lagrange",
+            D.ufl_cell(),
+            2,
+            (D.ufl_cell().topological_dimension(),),
+            identity_pullback,
+            H1,
+        )
         E = Mesh(V)
         domains_with_quadratic_coordinates.append(E)
 
@@ -53,8 +90,14 @@ def domains(request):
     domains = get_domains()
     domains_with_linear_coordinates = []
     for D in domains:
-        V = FiniteElement("Lagrange", D.ufl_cell(), 1, (D.ufl_cell().topological_dimension(), ),
-                          identity_pullback, H1)
+        V = FiniteElement(
+            "Lagrange",
+            D.ufl_cell(),
+            1,
+            (D.ufl_cell().topological_dimension(),),
+            identity_pullback,
+            H1,
+        )
         E = Mesh(V)
         domains_with_linear_coordinates.append(E)
 
@@ -69,19 +112,29 @@ def affine_domains(request):
         triangle,
         tetrahedron,
     ]
-    affine_domains = [Mesh(FiniteElement("Lagrange", cell, 1, (cell.topological_dimension(), ),
-                                         identity_pullback, H1))
-                      for cell in affine_cells]
+    affine_domains = [
+        Mesh(
+            FiniteElement(
+                "Lagrange", cell, 1, (cell.topological_dimension(),), identity_pullback, H1
+            )
+        )
+        for cell in affine_cells
+    ]
 
     affine_domains_with_linear_coordinates = []
     for D in affine_domains:
-        V = FiniteElement("Lagrange", D.ufl_cell(), 1, (D.ufl_cell().topological_dimension(), ),
-                          identity_pullback, H1)
+        V = FiniteElement(
+            "Lagrange",
+            D.ufl_cell(),
+            1,
+            (D.ufl_cell().topological_dimension(),),
+            identity_pullback,
+            H1,
+        )
         E = Mesh(V)
         affine_domains_with_linear_coordinates.append(E)
 
-    all_affine_domains = affine_domains + \
-        affine_domains_with_linear_coordinates
+    all_affine_domains = affine_domains + affine_domains_with_linear_coordinates
     return all_affine_domains[request.param]
 
 
@@ -93,18 +146,28 @@ def affine_facet_domains(request):
         quadrilateral,
         tetrahedron,
     ]
-    affine_facet_domains = [Mesh(FiniteElement(
-        "Lagrange", cell, 1, (cell.topological_dimension(), ),
-        identity_pullback, H1)) for cell in affine_facet_cells]
+    affine_facet_domains = [
+        Mesh(
+            FiniteElement(
+                "Lagrange", cell, 1, (cell.topological_dimension(),), identity_pullback, H1
+            )
+        )
+        for cell in affine_facet_cells
+    ]
     affine_facet_domains_with_linear_coordinates = []
     for D in affine_facet_domains:
-        V = FiniteElement("Lagrange", D.ufl_cell(), 1, (D.ufl_cell().topological_dimension(), ),
-                          identity_pullback, H1)
+        V = FiniteElement(
+            "Lagrange",
+            D.ufl_cell(),
+            1,
+            (D.ufl_cell().topological_dimension(),),
+            identity_pullback,
+            H1,
+        )
         E = Mesh(V)
         affine_facet_domains_with_linear_coordinates.append(E)
 
-    all_affine_facet_domains = affine_facet_domains + \
-        affine_facet_domains_with_linear_coordinates
+    all_affine_facet_domains = affine_facet_domains + affine_facet_domains_with_linear_coordinates
 
     return all_affine_facet_domains[request.param]
 
@@ -115,18 +178,28 @@ def nonaffine_domains(request):
         quadrilateral,
         hexahedron,
     ]
-    nonaffine_domains = [Mesh(FiniteElement(
-        "Lagrange", cell, 1, (cell.topological_dimension(), ),
-        identity_pullback, H1)) for cell in nonaffine_cells]
+    nonaffine_domains = [
+        Mesh(
+            FiniteElement(
+                "Lagrange", cell, 1, (cell.topological_dimension(),), identity_pullback, H1
+            )
+        )
+        for cell in nonaffine_cells
+    ]
     nonaffine_domains_with_linear_coordinates = []
     for D in nonaffine_domains:
-        V = FiniteElement("Lagrange", D.ufl_cell(), 1, (D.ufl_cell().topological_dimension(), ),
-                          identity_pullback, H1)
+        V = FiniteElement(
+            "Lagrange",
+            D.ufl_cell(),
+            1,
+            (D.ufl_cell().topological_dimension(),),
+            identity_pullback,
+            H1,
+        )
         E = Mesh(V)
         nonaffine_domains_with_linear_coordinates.append(E)
 
-    all_nonaffine_domains = nonaffine_domains + \
-        nonaffine_domains_with_linear_coordinates
+    all_nonaffine_domains = nonaffine_domains + nonaffine_domains_with_linear_coordinates
 
     return all_nonaffine_domains[request.param]
 
@@ -136,18 +209,30 @@ def nonaffine_facet_domains(request):
     nonaffine_facet_cells = [
         hexahedron,
     ]
-    nonaffine_facet_domains = [Mesh(FiniteElement(
-        "Lagrange", cell, 1, (cell.topological_dimension(), ),
-        identity_pullback, H1)) for cell in nonaffine_facet_cells]
+    nonaffine_facet_domains = [
+        Mesh(
+            FiniteElement(
+                "Lagrange", cell, 1, (cell.topological_dimension(),), identity_pullback, H1
+            )
+        )
+        for cell in nonaffine_facet_cells
+    ]
     nonaffine_facet_domains_with_linear_coordinates = []
     for D in nonaffine_facet_domains:
-        V = FiniteElement("Lagrange", D.ufl_cell(), 1, (D.ufl_cell().topological_dimension(), ),
-                          identity_pullback, H1)
+        V = FiniteElement(
+            "Lagrange",
+            D.ufl_cell(),
+            1,
+            (D.ufl_cell().topological_dimension(),),
+            identity_pullback,
+            H1,
+        )
         E = Mesh(V)
         nonaffine_facet_domains_with_linear_coordinates.append(E)
 
-    all_nonaffine_facet_domains = nonaffine_facet_domains + \
-        nonaffine_facet_domains_with_linear_coordinates
+    all_nonaffine_facet_domains = (
+        nonaffine_facet_domains + nonaffine_facet_domains_with_linear_coordinates
+    )
 
     return all_nonaffine_facet_domains[request.param]
 
@@ -177,7 +262,7 @@ def test_coordinates_never_cellwise_constant(domains):
 
 def test_coordinates_never_cellwise_constant_vertex():
     # The only exception here:
-    domains = Mesh(FiniteElement("Lagrange", Cell("vertex"), 1, (3, ), identity_pullback, H1))
+    domains = Mesh(FiniteElement("Lagrange", Cell("vertex"), 1, (3,), identity_pullback, H1))
     assert domains.ufl_cell().cellname() == "vertex"
     e = SpatialCoordinate(domains)
     assert is_cellwise_constant(e)
@@ -234,9 +319,13 @@ def test_coefficient_sometimes_cellwise_constant(domains_not_linear):
     e = Constant(domains_not_linear)
     assert is_cellwise_constant(e)
 
-    V = FiniteElement("Discontinuous Lagrange", domains_not_linear.ufl_cell(), 0, (), identity_pullback, L2)
+    V = FiniteElement(
+        "Discontinuous Lagrange", domains_not_linear.ufl_cell(), 0, (), identity_pullback, L2
+    )
     d = domains_not_linear.ufl_cell().topological_dimension()
-    domain = Mesh(FiniteElement("Lagrange", domains_not_linear.ufl_cell(), 1, (d, ), identity_pullback, H1))
+    domain = Mesh(
+        FiniteElement("Lagrange", domains_not_linear.ufl_cell(), 1, (d,), identity_pullback, H1)
+    )
     space = FunctionSpace(domain, V)
     e = Coefficient(space)
     assert is_cellwise_constant(e)
@@ -255,9 +344,13 @@ def test_coefficient_sometimes_cellwise_constant(domains_not_linear):
 
 
 def test_coefficient_mostly_not_cellwise_constant(domains_not_linear):
-    V = FiniteElement("Discontinuous Lagrange", domains_not_linear.ufl_cell(), 1, (), identity_pullback, L2)
+    V = FiniteElement(
+        "Discontinuous Lagrange", domains_not_linear.ufl_cell(), 1, (), identity_pullback, L2
+    )
     d = domains_not_linear.ufl_cell().topological_dimension()
-    domain = Mesh(FiniteElement("Lagrange", domains_not_linear.ufl_cell(), 1, (d, ), identity_pullback, H1))
+    domain = Mesh(
+        FiniteElement("Lagrange", domains_not_linear.ufl_cell(), 1, (d,), identity_pullback, H1)
+    )
     space = FunctionSpace(domain, V)
     e = Coefficient(space)
     assert not is_cellwise_constant(e)
diff --git a/test/test_reference_shapes.py b/test/test_reference_shapes.py
index 69c0a2983..d5aec17a3 100755
--- a/test/test_reference_shapes.py
+++ b/test/test_reference_shapes.py
@@ -8,14 +8,14 @@
 def test_reference_shapes():
     # show_elements()
     cell = Cell("triangle")
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1))
 
-    V = FiniteElement("N1curl", cell, 1, (2, ), covariant_piola, HCurl)
+    V = FiniteElement("N1curl", cell, 1, (2,), covariant_piola, HCurl)
     Vspace = FunctionSpace(domain, V)
     assert Vspace.value_shape == (3,)
     assert V.reference_value_shape == (2,)
 
-    U = FiniteElement("Raviart-Thomas", cell, 1, (2, ), contravariant_piola, HDiv)
+    U = FiniteElement("Raviart-Thomas", cell, 1, (2,), contravariant_piola, HDiv)
     Uspace = FunctionSpace(domain, U)
     assert Uspace.value_shape == (3,)
     assert U.reference_value_shape == (2,)
@@ -25,7 +25,7 @@ def test_reference_shapes():
     assert Wspace.value_shape == ()
     assert W.reference_value_shape == ()
 
-    Q = FiniteElement("Lagrange", cell, 1, (3, ), identity_pullback, H1)
+    Q = FiniteElement("Lagrange", cell, 1, (3,), identity_pullback, H1)
     Qspace = FunctionSpace(domain, Q)
     assert Qspace.value_shape == (3,)
     assert Q.reference_value_shape == (3,)
@@ -36,8 +36,19 @@ def test_reference_shapes():
     assert T.reference_value_shape == (3, 3)
 
     S = SymmetricElement(
-        {(0, 0): 0, (1, 0): 1, (2, 0): 2, (0, 1): 1, (1, 1): 3, (2, 1): 4, (0, 2): 2, (1, 2): 4, (2, 2): 5},
-        [FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1) for _ in range(6)])
+        {
+            (0, 0): 0,
+            (1, 0): 1,
+            (2, 0): 2,
+            (0, 1): 1,
+            (1, 1): 3,
+            (2, 1): 4,
+            (0, 2): 2,
+            (1, 2): 4,
+            (2, 2): 5,
+        },
+        [FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1) for _ in range(6)],
+    )
     Sspace = FunctionSpace(domain, S)
     assert Sspace.value_shape == (3, 3)
     assert S.reference_value_shape == (6,)
diff --git a/test/test_scratch.py b/test/test_scratch.py
index 32ced3346..5b429e532 100755
--- a/test/test_scratch.py
+++ b/test/test_scratch.py
@@ -8,8 +8,22 @@
 
 import warnings
 
-from ufl import (Coefficient, FunctionSpace, Identity, Mesh, TestFunction, as_matrix, as_tensor, as_vector, dx, grad,
-                 indices, inner, outer, triangle)
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Identity,
+    Mesh,
+    TestFunction,
+    as_matrix,
+    as_tensor,
+    as_vector,
+    dx,
+    grad,
+    indices,
+    inner,
+    outer,
+    triangle,
+)
 from ufl.classes import FixedIndex, FormArgument, Grad, Indexed, ListTensor, Zero
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
@@ -18,15 +32,14 @@
 
 
 class MockForwardAD:
-
     def __init__(self):
         self._w = ()
         self._v = ()
 
         class Obj:
-
             def __init__(self):
                 self._data = {}
+
         self._cd = Obj()
 
     def grad(self, g):
@@ -39,25 +52,25 @@ def grad(self, g):
         ngrads = 0
         o = g
         while isinstance(o, Grad):
-            o, = o.ufl_operands
+            (o,) = o.ufl_operands
             ngrads += 1
         if not isinstance(o, FormArgument):
             raise ValueError("Expecting gradient of a FormArgument, not %s" % repr(o))
 
         def apply_grads(f):
             if not isinstance(f, FormArgument):
-                print((','*60))
+                print(("," * 60))
                 print(f)
                 print(o)
                 print(g)
-                print((','*60))
+                print(("," * 60))
                 raise ValueError("What?")
             for i in range(ngrads):
                 f = Grad(f)
             return f
 
         # Find o among all w without any indexing, which makes this easy
-        for (w, v) in zip(self._w, self._v):
+        for w, v in zip(self._w, self._v):
             if o == w and isinstance(v, FormArgument):
                 # Case: d/dt [w + t v]
                 return (g, apply_grads(v))
@@ -85,18 +98,17 @@ def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
             # Apply gradients directly to argument vval,
             # and get the right indexed scalar component(s)
             kk = indices(ngrads)
-            Dvkk = apply_grads(vval)[vcomp+kk]
+            Dvkk = apply_grads(vval)[vcomp + kk]
             # Place scalar component(s) Dvkk into the right tensor positions
             if wshape:
                 Ejj, jj = unit_indexed_tensor(wshape, wcomp)
             else:
                 Ejj, jj = 1, ()
-            gprimeterm = as_tensor(Ejj*Dvkk, jj+kk)
+            gprimeterm = as_tensor(Ejj * Dvkk, jj + kk)
             return gprimeterm
 
         # Accumulate contributions from variations in different components
-        for (w, v) in zip(self._w, self._v):
-
+        for w, v in zip(self._w, self._v):
             # Analyse differentiation variable coefficient
             if isinstance(w, FormArgument):
                 if not w == o:
@@ -112,7 +124,9 @@ def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
                     for wcomp, vsub in unwrap_list_tensor(v):
                         if not isinstance(vsub, Zero):
                             vval, vcomp = analyse_variation_argument(vsub)
-                            gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
+                            gprimesum = gprimesum + compute_gprimeterm(
+                                ngrads, vval, vcomp, wshape, wcomp
+                            )
 
                 else:
                     if wshape != ():
@@ -123,7 +137,9 @@ def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
                     vval, vcomp = analyse_variation_argument(v)
                     gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
 
-            elif isinstance(w, Indexed):  # This path is tested in unit tests, but not actually used?
+            elif isinstance(
+                w, Indexed
+            ):  # This path is tested in unit tests, but not actually used?
                 # Case: d/dt [w[...] + t v[...]]
                 # Case: d/dt [w[...] + t v]
                 wval, wcomp = w.ufl_operands
@@ -154,20 +170,22 @@ def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
                 if not isinstance(oprimes, tuple):
                     oprimes = (oprimes,)
                     if len(oprimes) != len(self._v):
-                        raise ValueError("Got a tuple of arguments, "
-                                         "expecting a matching tuple of coefficient derivatives.")
+                        raise ValueError(
+                            "Got a tuple of arguments, "
+                            "expecting a matching tuple of coefficient derivatives."
+                        )
 
                 # Compute dg/dw_j = dg/dw_h : v.
                 # Since we may actually have a tuple of oprimes and vs in a
                 # 'mixed' space, sum over them all to get the complete inner
                 # product. Using indices to define a non-compound inner product.
-                for (oprime, v) in zip(oprimes, self._v):
+                for oprime, v in zip(oprimes, self._v):
                     raise ValueError("FIXME: Figure out how to do this with ngrads")
                     so, oi = as_scalar(oprime)
                     rv = len(v.ufl_shape)
                     oi1 = oi[:-rv]
                     oi2 = oi[-rv:]
-                    prod = so*v[oi2]
+                    prod = so * v[oi2]
                     if oi1:
                         gprimesum += as_tensor(prod, oi1)
                     else:
@@ -185,36 +203,41 @@ def test_unit_tensor(self):
 
 def test_unwrap_list_tensor(self):
     lt = as_tensor((1, 2))
-    expected = [((0,), 1),
-                ((1,), 2), ]
+    expected = [
+        ((0,), 1),
+        ((1,), 2),
+    ]
     comp = unwrap_list_tensor(lt)
     assert comp == expected
 
     lt = as_tensor(((1, 2), (3, 4)))
-    expected = [((0, 0), 1),
-                ((0, 1), 2),
-                ((1, 0), 3),
-                ((1, 1), 4), ]
+    expected = [
+        ((0, 0), 1),
+        ((0, 1), 2),
+        ((1, 0), 3),
+        ((1, 1), 4),
+    ]
     comp = unwrap_list_tensor(lt)
     assert comp == expected
 
-    lt = as_tensor((((1, 2), (3, 4)),
-                    ((11, 12), (13, 14))))
-    expected = [((0, 0, 0), 1),
-                ((0, 0, 1), 2),
-                ((0, 1, 0), 3),
-                ((0, 1, 1), 4),
-                ((1, 0, 0), 11),
-                ((1, 0, 1), 12),
-                ((1, 1, 0), 13),
-                ((1, 1, 1), 14), ]
+    lt = as_tensor((((1, 2), (3, 4)), ((11, 12), (13, 14))))
+    expected = [
+        ((0, 0, 0), 1),
+        ((0, 0, 1), 2),
+        ((0, 1, 0), 3),
+        ((0, 1, 1), 4),
+        ((1, 0, 0), 11),
+        ((1, 0, 1), 12),
+        ((1, 1, 0), 13),
+        ((1, 1, 1), 14),
+    ]
     comp = unwrap_list_tensor(lt)
     assert comp == expected
 
 
 def test__forward_coefficient_ad__grad_of_scalar_coefficient(self):
     U = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, U)
     u = Coefficient(space)
     du = TestFunction(space)
@@ -239,8 +262,8 @@ def test__forward_coefficient_ad__grad_of_scalar_coefficient(self):
 
 
 def test__forward_coefficient_ad__grad_of_vector_coefficient(self):
-    V = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    V = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     v = Coefficient(space)
     dv = TestFunction(space)
@@ -265,8 +288,8 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient(self):
 
 
 def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_variation(self):
-    V = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    V = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     v = Coefficient(space)
     dv = TestFunction(space)
@@ -280,19 +303,20 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     f = grad(v)
     df = grad(as_vector((dv[1], 0)))  # Mathematically this would be the natural result
     j, k = indices(2)
-    df = as_tensor(Identity(2)[0, j]*grad(dv)[1, k], (j, k))  # Actual representation should have grad right next to dv
+    df = as_tensor(
+        Identity(2)[0, j] * grad(dv)[1, k], (j, k)
+    )  # Actual representation should have grad right next to dv
     g, dg = mad.grad(f)
     if 0:
-        print(('\nf    ', f))
-        print(('df   ', df))
-        print(('g    ', g))
-        print(('dg   ', dg))
+        print(("\nf    ", f))
+        print(("df   ", df))
+        print(("g    ", g))
+        print(("dg   ", dg))
     assert f.ufl_shape == df.ufl_shape
     assert g.ufl_shape == f.ufl_shape
     assert dg.ufl_shape == df.ufl_shape
     assert g == f
-    self.assertEqual((inner(dg, dg)*dx).signature(),
-                     (inner(df, df)*dx).signature())
+    self.assertEqual((inner(dg, dg) * dx).signature(), (inner(df, df) * dx).signature())
     # assert dg == df # Expected to fail because of different index numbering
 
     # Multiple components of variation:
@@ -305,25 +329,27 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     # Actual representation should have grad right next to dv:
     j0, k0 = indices(2)
     j1, k1 = indices(2)  # Using j0,k0 for both terms gives different signature
-    df = (as_tensor(Identity(2)[0, j0]*grad(dv)[1, k0], (j0, k0))
-          + as_tensor(Identity(2)[1, j1]*grad(dv)[0, k1], (j1, k1)))
+    df = as_tensor(Identity(2)[0, j0] * grad(dv)[1, k0], (j0, k0)) + as_tensor(
+        Identity(2)[1, j1] * grad(dv)[0, k1], (j1, k1)
+    )
     g, dg = mad.grad(f)
-    print(('\nf    ', f))
-    print(('df   ', df))
-    print(('g    ', g))
-    print(('dg   ', dg))
+    print(("\nf    ", f))
+    print(("df   ", df))
+    print(("g    ", g))
+    print(("dg   ", dg))
     assert f.ufl_shape == df.ufl_shape
     assert g.ufl_shape == f.ufl_shape
     assert dg.ufl_shape == df.ufl_shape
     assert g == f
-    self.assertEqual((inner(dg, dg)*dx).signature(),
-                     (inner(df, df)*dx).signature())
+    self.assertEqual((inner(dg, dg) * dx).signature(), (inner(df, df) * dx).signature())
     # assert dg == df # Expected to fail because of different index numbering
 
 
-def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_variation_in_list(self):
-    V = FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_variation_in_list(
+    self,
+):
+    V = FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1)
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     v = Coefficient(space)
     dv = TestFunction(space)
@@ -337,24 +363,25 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     f = grad(v)
     df = grad(as_vector((dv[1], 0)))  # Mathematically this would be the natural result
     j, k = indices(2)
-    df = as_tensor(Identity(2)[0, j]*grad(dv)[1, k], (j, k))  # Actual representation should have grad right next to dv
+    df = as_tensor(
+        Identity(2)[0, j] * grad(dv)[1, k], (j, k)
+    )  # Actual representation should have grad right next to dv
     g, dg = mad.grad(f)
     if 0:
-        print(('\nf    ', f))
-        print(('df   ', df))
-        print(('g    ', g))
-        print(('dg   ', dg))
+        print(("\nf    ", f))
+        print(("df   ", df))
+        print(("g    ", g))
+        print(("dg   ", dg))
     assert f.ufl_shape == df.ufl_shape
     assert g.ufl_shape == f.ufl_shape
     assert dg.ufl_shape == df.ufl_shape
     assert g == f
-    self.assertEqual((inner(dg, dg)*dx).signature(),
-                     (inner(df, df)*dx).signature())
+    self.assertEqual((inner(dg, dg) * dx).signature(), (inner(df, df) * dx).signature())
     # assert dg == df # Expected to fail because of different index numbering
 
     # Multiple components of variation:
     # grad(grad(c))[0,1,:,:] -> grad(grad(dc))[1,0,:,:]
-    mad._w = (v, )
+    mad._w = (v,)
     mad._v = (as_vector((dv[1], dv[0])),)
     f = grad(v)
     # Mathematically this would be the natural result:
@@ -362,25 +389,25 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     # Actual representation should have grad right next to dv:
     j0, k0 = indices(2)
     j1, k1 = indices(2)  # Using j0,k0 for both terms gives different signature
-    df = (as_tensor(Identity(2)[0, j0]*grad(dv)[1, k0], (j0, k0))
-          + as_tensor(Identity(2)[1, j1]*grad(dv)[0, k1], (j1, k1)))
+    df = as_tensor(Identity(2)[0, j0] * grad(dv)[1, k0], (j0, k0)) + as_tensor(
+        Identity(2)[1, j1] * grad(dv)[0, k1], (j1, k1)
+    )
     g, dg = mad.grad(f)
-    print(('\nf    ', f))
-    print(('df   ', df))
-    print(('g    ', g))
-    print(('dg   ', dg))
+    print(("\nf    ", f))
+    print(("df   ", df))
+    print(("g    ", g))
+    print(("dg   ", dg))
     assert f.ufl_shape == df.ufl_shape
     assert g.ufl_shape == f.ufl_shape
     assert dg.ufl_shape == df.ufl_shape
     assert g == f
-    self.assertEqual((inner(dg, dg)*dx).signature(),
-                     (inner(df, df)*dx).signature())
+    self.assertEqual((inner(dg, dg) * dx).signature(), (inner(df, df) * dx).signature())
     # assert dg == df # Expected to fail because of different index numbering
 
 
 def test__forward_coefficient_ad__grad_of_tensor_coefficient(self):
     W = FiniteElement("Lagrange", triangle, 1, (2, 2), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, W)
     w = Coefficient(space)
     dw = TestFunction(space)
@@ -406,7 +433,7 @@ def test__forward_coefficient_ad__grad_of_tensor_coefficient(self):
 
 def test__forward_coefficient_ad__grad_of_tensor_coefficient__with_component_variation(self):
     W = FiniteElement("Lagrange", triangle, 1, (2, 2), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, W)
     w = Coefficient(space)
     dw = TestFunction(space)
@@ -424,17 +451,16 @@ def test__forward_coefficient_ad__grad_of_tensor_coefficient__with_component_var
     i, j, k = indices(3)
     E = outer(Identity(2)[wc[0], i], Identity(2)[wc[1], j])
     Ddw = grad(dw)[dwc + (k,)]
-    df = as_tensor(E*Ddw, (i, j, k))  # Actual representation should have grad next to dv
+    df = as_tensor(E * Ddw, (i, j, k))  # Actual representation should have grad next to dv
     g, dg = mad.grad(f)
     if 0:
-        print(('\nf    ', f))
-        print(('df   ', df))
-        print(('g    ', g))
-        print(('dg   ', dg))
+        print(("\nf    ", f))
+        print(("df   ", df))
+        print(("g    ", g))
+        print(("dg   ", dg))
     assert f.ufl_shape == df.ufl_shape
     assert g.ufl_shape == f.ufl_shape
     assert dg.ufl_shape == df.ufl_shape
     assert g == f
-    self.assertEqual((inner(dg, dg)*dx).signature(),
-                     (inner(df, df)*dx).signature())
+    self.assertEqual((inner(dg, dg) * dx).signature(), (inner(df, df) * dx).signature())
     # assert dg == df # Expected to fail because of different index numbering
diff --git a/test/test_signature.py b/test/test_signature.py
index 660758fe7..aa8c57877 100755
--- a/test/test_signature.py
+++ b/test/test_signature.py
@@ -1,8 +1,32 @@
 """Test the computation of form signatures."""
 
-from ufl import (Argument, CellDiameter, CellVolume, Circumradius, Coefficient, FacetArea, FacetNormal, FunctionSpace,
-                 Identity, Mesh, SpatialCoordinate, TestFunction, as_vector, diff, dot, ds, dx, hexahedron, indices,
-                 inner, interval, quadrilateral, tetrahedron, triangle, variable)
+from ufl import (
+    Argument,
+    CellDiameter,
+    CellVolume,
+    Circumradius,
+    Coefficient,
+    FacetArea,
+    FacetNormal,
+    FunctionSpace,
+    Identity,
+    Mesh,
+    SpatialCoordinate,
+    TestFunction,
+    as_vector,
+    diff,
+    dot,
+    ds,
+    dx,
+    hexahedron,
+    indices,
+    inner,
+    interval,
+    quadrilateral,
+    tetrahedron,
+    triangle,
+    variable,
+)
 from ufl.algorithms.signature import compute_multiindex_hashdata, compute_terminal_hashdata
 from ufl.classes import FixedIndex, MultiIndex
 from ufl.finiteelement import FiniteElement, SymmetricElement
@@ -22,7 +46,7 @@ def domain_numbering(*cells):
     renumbering = {}
     for i, cell in enumerate(cells):
         d = cell.topological_dimension()
-        domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1), ufl_id=i)
+        domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1), ufl_id=i)
         renumbering[domain] = i
     return renumbering
 
@@ -60,12 +84,14 @@ def test_terminal_hashdata_depends_on_literals(self):
     def forms():
         i, j = indices(2)
         for d, cell in [(2, triangle), (3, tetrahedron)]:
-            domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1), ufl_id=d-2)
+            domain = Mesh(
+                FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1), ufl_id=d - 2
+            )
             x = SpatialCoordinate(domain)
             ident = Identity(d)
             for fv in (1.1, 2.2):
                 for iv in (5, 7):
-                    expr = (ident[0, j]*(fv*x[j]))**iv
+                    expr = (ident[0, j] * (fv * x[j])) ** iv
 
                     reprs.add(repr(expr))
                     hashes.add(hash(expr))
@@ -89,7 +115,7 @@ def forms():
         cells = (triangle, tetrahedron)
         for i, cell in enumerate(cells):
             d = cell.topological_dimension()
-            domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1), ufl_id=i)
+            domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1), ufl_id=i)
 
             x = SpatialCoordinate(domain)
             n = FacetNormal(domain)
@@ -104,14 +130,14 @@ def forms():
             qs = (h, r, a, v)  # , s)
             for w in ws:
                 for q in qs:
-                    expr = (ident[0, j]*(q*w[j]))
+                    expr = ident[0, j] * (q * w[j])
 
                     reprs.add(repr(expr))
                     hashes.add(hash(expr))
                     yield compute_terminal_hashdata(expr, domain_numbering(*cells))
 
     c, d, r, h = compute_unique_terminal_hashdatas(forms())
-    assert c == 2*4*2  # len(ws)*len(qs)*len(cells)
+    assert c == 2 * 4 * 2  # len(ws)*len(qs)*len(cells)
     assert d == c
     assert r == c
     assert h == c
@@ -134,25 +160,48 @@ def forms():
         for rep in range(nreps):
             for i, cell in enumerate(cells):
                 d = cell.topological_dimension()
-                domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1), ufl_id=i)
+                domain = Mesh(
+                    FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1), ufl_id=i
+                )
                 for degree in degrees:
                     for family, sobolev in families:
                         V = FiniteElement(family, cell, degree, (), identity_pullback, sobolev)
-                        W = FiniteElement(family, cell, degree, (d, ), identity_pullback, sobolev)
-                        W2 = FiniteElement(family, cell, degree, (d+1, ), identity_pullback, sobolev)
+                        W = FiniteElement(family, cell, degree, (d,), identity_pullback, sobolev)
+                        W2 = FiniteElement(
+                            family, cell, degree, (d + 1,), identity_pullback, sobolev
+                        )
                         T = FiniteElement(family, cell, degree, (d, d), identity_pullback, sobolev)
                         if d == 2:
                             S = SymmetricElement(
                                 {(0, 0): 0, (0, 1): 1, (1, 0): 1, (1, 1): 2},
-                                [FiniteElement(family, cell, degree, (), identity_pullback, sobolev)
-                                 for _ in range(3)])
+                                [
+                                    FiniteElement(
+                                        family, cell, degree, (), identity_pullback, sobolev
+                                    )
+                                    for _ in range(3)
+                                ],
+                            )
                         else:
                             assert d == 3
                             S = SymmetricElement(
-                                {(0, 0): 0, (0, 1): 1, (0, 2): 2, (1, 0): 1, (1, 1): 3,
-                                 (1, 2): 4, (2, 0): 2, (2, 1): 4, (2, 2): 5},
-                                [FiniteElement(family, cell, degree, (), identity_pullback, sobolev)
-                                 for _ in range(6)])
+                                {
+                                    (0, 0): 0,
+                                    (0, 1): 1,
+                                    (0, 2): 2,
+                                    (1, 0): 1,
+                                    (1, 1): 3,
+                                    (1, 2): 4,
+                                    (2, 0): 2,
+                                    (2, 1): 4,
+                                    (2, 2): 5,
+                                },
+                                [
+                                    FiniteElement(
+                                        family, cell, degree, (), identity_pullback, sobolev
+                                    )
+                                    for _ in range(6)
+                                ],
+                            )
                         elements = [V, W, W2, T, S]
                         assert len(elements) == nelm
 
@@ -174,7 +223,7 @@ def forms():
     c1 = nreps * len(cells) * len(degrees) * len(families) * nelm * 2
     assert c == c1
 
-    c0 = len(cells) * len(degrees) * (len(families)-1) * nelm * 2
+    c0 = len(cells) * len(degrees) * (len(families) - 1) * nelm * 2
     assert d == c0
     assert r == c0
     assert h == c0
@@ -194,12 +243,14 @@ def forms():
         for rep in range(nreps):
             for i, cell in enumerate(cells):
                 d = cell.topological_dimension()
-                domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1), ufl_id=i)
+                domain = Mesh(
+                    FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1), ufl_id=i
+                )
                 for k in counts:
                     V = FiniteElement("Lagrange", cell, 2, (), identity_pullback, H1)
                     space = FunctionSpace(domain, V)
                     f = Coefficient(space, count=k)
-                    g = Coefficient(space, count=k+2)
+                    g = Coefficient(space, count=k + 2)
                     expr = inner(f, g)
 
                     renumbering = domain_numbering(*cells)
@@ -233,12 +284,14 @@ def forms():
         for rep in range(nreps):
             for i, cell in enumerate(cells):
                 d = cell.topological_dimension()
-                domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1), ufl_id=i)
+                domain = Mesh(
+                    FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1), ufl_id=i
+                )
                 for k in counts:
                     V = FiniteElement("Lagrange", cell, 2, (), identity_pullback, H1)
                     space = FunctionSpace(domain, V)
                     f = Argument(space, k)
-                    g = Argument(space, k+2)
+                    g = Argument(space, k + 2)
                     expr = inner(f, g)
 
                     reprs.add(repr(expr))
@@ -246,7 +299,9 @@ def forms():
                     yield compute_terminal_hashdata(expr, domain_numbering(*cells))
 
     c, d, r, h = compute_unique_terminal_hashdatas(forms())
-    c0 = len(cells) * len(counts)  # Number of actually unique cases from a code generation perspective
+    c0 = len(cells) * len(
+        counts
+    )  # Number of actually unique cases from a code generation perspective
     c1 = 1 * c0  # Number of unique cases from a symbolic representation perspective
     assert len(reprs) == c1
     assert len(hashes) == c1
@@ -263,7 +318,7 @@ def test_domain_signature_data_does_not_depend_on_domain_label_value(self):
     s2s = set()
     for i, cell in enumerate(cells):
         d = cell.topological_dimension()
-        domain = FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1)
+        domain = FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1)
         d0 = Mesh(domain)
         d1 = Mesh(domain, ufl_id=1)
         d2 = Mesh(domain, ufl_id=2)
@@ -285,17 +340,26 @@ def test_terminal_hashdata_does_not_depend_on_domain_label_value(self):
     hashes = set()
     ufl_ids = [1, 2]
     cells = [triangle, quadrilateral]
-    domains = [Mesh(FiniteElement("Lagrange", cell, 1, (cell.topological_dimension(), ),
-                                  identity_pullback, H1),
-                    ufl_id=ufl_id) for cell in cells for ufl_id in ufl_ids]
+    domains = [
+        Mesh(
+            FiniteElement(
+                "Lagrange", cell, 1, (cell.topological_dimension(),), identity_pullback, H1
+            ),
+            ufl_id=ufl_id,
+        )
+        for cell in cells
+        for ufl_id in ufl_ids
+    ]
     nreps = 2
     num_exprs = 2
 
     def forms():
         for rep in range(nreps):
             for domain in domains:
-                V = FunctionSpace(domain, FiniteElement("Lagrange", domain.ufl_cell(), 2, (),
-                                  identity_pullback, H1))
+                V = FunctionSpace(
+                    domain,
+                    FiniteElement("Lagrange", domain.ufl_cell(), 2, (), identity_pullback, H1),
+                )
                 f = Coefficient(V, count=0)
                 v = TestFunction(V)
                 x = SpatialCoordinate(domain)
@@ -312,8 +376,12 @@ def forms():
                     yield compute_terminal_hashdata(expr, renumbering)
 
     c, d, r, h = compute_unique_terminal_hashdatas(forms())
-    c0 = num_exprs * len(cells)  # Number of actually unique cases from a code generation perspective
-    c1 = num_exprs * len(domains)  # Number of unique cases from a symbolic representation perspective
+    c0 = num_exprs * len(
+        cells
+    )  # Number of actually unique cases from a code generation perspective
+    c1 = num_exprs * len(
+        domains
+    )  # Number of unique cases from a symbolic representation perspective
     assert len(reprs) == c1
     assert len(hashes) == c1
     self.assertEqual(c, nreps * c1)  # number of inner loop executions in forms() above
@@ -350,9 +418,9 @@ def hashdatas():
 
     c, d, r, h = compute_unique_multiindex_hashdatas(hashdatas())
     assert c == 9
-    assert d == 9-1  # (1,0 is repeated, therefore -1)
-    assert len(reprs) == 9-1
-    assert len(hashes) == 9-1
+    assert d == 9 - 1  # (1,0 is repeated, therefore -1)
+    assert len(reprs) == 9 - 1
+    assert len(hashes) == 9 - 1
 
 
 def test_multiindex_hashdata_does_not_depend_on_counts(self):
@@ -373,11 +441,12 @@ def hashdatas():
             reprs.add(repr(expr))
             hashes.add(hash(expr))
             yield compute_multiindex_hashdata(expr, {})
+
     c, d, r, h = compute_unique_multiindex_hashdatas(hashdatas())
-    assert c == 3+9+9
-    assert d == 1+1
-    assert len(reprs) == 3+9+9
-    assert len(hashes) == 3+9+9
+    assert c == 3 + 9 + 9
+    assert d == 1 + 1
+    assert len(reprs) == 3 + 9 + 9
+    assert len(hashes) == 3 + 9 + 9
 
 
 def test_multiindex_hashdata_depends_on_the_order_indices_are_observed(self):
@@ -387,28 +456,31 @@ def test_multiindex_hashdata_depends_on_the_order_indices_are_observed(self):
 
     def hashdatas():
         for rep in range(nrep):
-            # Resetting index_numbering for each repetition,
-            # resulting in hashdata staying the same for
-            # each repetition but repr and hashes changing
-            # because new indices are created each repetition.
+            # Resetting index_numbering for each repetition, resulting
+            # in hashdata staying the same for each repetition but repr
+            # and hashes changing because new indices are created each
+            # repetition.
             index_numbering = {}
             i, j, k, l = indices(4)  # noqa: E741
-            for expr in (MultiIndex((i,)),
-                         MultiIndex((i,)),  # r
-                         MultiIndex((i, j)),
-                         MultiIndex((j, i)),
-                         MultiIndex((i, j)),  # r
-                         MultiIndex((i, j, k)),
-                         MultiIndex((k, j, i)),
-                         MultiIndex((j, i))):  # r
+            for expr in (
+                MultiIndex((i,)),
+                MultiIndex((i,)),  # r
+                MultiIndex((i, j)),
+                MultiIndex((j, i)),
+                MultiIndex((i, j)),  # r
+                MultiIndex((i, j, k)),
+                MultiIndex((k, j, i)),
+                MultiIndex((j, i)),
+            ):  # r
                 reprs.add(repr(expr))
                 hashes.add(hash(expr))
                 yield compute_multiindex_hashdata(expr, index_numbering)
+
     c, d, r, h = compute_unique_multiindex_hashdatas(hashdatas())
-    assert c == nrep*8
+    assert c == nrep * 8
     assert d == 5
-    assert len(reprs) == nrep*5
-    assert len(hashes) == nrep*5
+    assert len(reprs) == nrep * 5
+    assert len(hashes) == nrep * 5
 
 
 def check_unique_signatures(forms):
@@ -437,17 +509,18 @@ def forms():
         for family, sobolev in (("Lagrange", H1), ("Discontinuous Lagrange", L2)):
             for cell in (triangle, tetrahedron, quadrilateral):
                 d = cell.topological_dimension()
-                domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1))
+                domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1))
                 for degree in (1, 2):
                     V = FiniteElement(family, cell, degree, (), identity_pullback, sobolev)
                     space = FunctionSpace(domain, V)
                     u = Coefficient(space)
                     v = TestFunction(space)
                     x = SpatialCoordinate(domain)
-                    w = as_vector([v]*x.ufl_shape[0])
-                    f = dot(w, u*x)
-                    a = f*dx
+                    w = as_vector([v] * x.ufl_shape[0])
+                    f = dot(w, u * x)
+                    a = f * dx
                     yield a
+
     check_unique_signatures(forms())
 
 
@@ -455,15 +528,16 @@ def test_signature_is_affected_by_domains(self):
     def forms():
         for cell in (triangle, tetrahedron):
             d = cell.topological_dimension()
-            domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1))
+            domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1))
             for di in (1, 2):
                 for dj in (1, 2):
                     for dk in (1, 2):
                         V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
                         space = FunctionSpace(domain, V)
                         u = Coefficient(space)
-                        a = u*dx(di) + 2*u*dx(dj) + 3*u*ds(dk)
+                        a = u * dx(di) + 2 * u * dx(dj) + 3 * u * ds(dk)
                         yield a
+
     check_unique_signatures(forms())
 
 
@@ -471,35 +545,36 @@ def test_signature_of_forms_with_diff(self):
     def forms():
         for i, cell in enumerate([triangle, tetrahedron]):
             d = cell.topological_dimension()
-            domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1), ufl_id=i)
+            domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1), ufl_id=i)
             for k in (1, 2, 3):
                 d = cell.topological_dimension()
                 V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-                W = FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1)
+                W = FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1)
                 v_space = FunctionSpace(domain, V)
                 w_space = FunctionSpace(domain, W)
                 u = Coefficient(v_space)
                 w = Coefficient(w_space)
                 vu = variable(u)
                 vw = variable(w)
-                f = vu*dot(vw, vu**k*vw)
+                f = vu * dot(vw, vu**k * vw)
                 g = diff(f, vu)
                 h = dot(diff(f, vw), FacetNormal(domain))
-                a = f*dx(1) + g*dx(2) + h*ds(0)
+                a = f * dx(1) + g * dx(2) + h * ds(0)
                 yield a
+
     check_unique_signatures(forms())
 
 
 def test_signature_of_form_depend_on_coefficient_numbering_across_integrals(self):
     cell = triangle
     V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, V)
     f = Coefficient(space)
     g = Coefficient(space)
-    M1 = f*dx(0) + g*dx(1)
-    M2 = g*dx(0) + f*dx(1)
-    M3 = g*dx(0) + g*dx(1)
+    M1 = f * dx(0) + g * dx(1)
+    M2 = g * dx(0) + f * dx(1)
+    M3 = g * dx(0) + g * dx(1)
     self.assertTrue(M1.signature() != M2.signature())
     self.assertTrue(M1.signature() != M3.signature())
     self.assertTrue(M2.signature() != M3.signature())
@@ -510,19 +585,21 @@ def forms():
         for cell in (triangle, tetrahedron):
             d = cell.topological_dimension()
             V = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-            domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1))
+            domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1))
             space = FunctionSpace(domain, V)
             u = Coefficient(space)
             v = Coefficient(space)
-            fs = [(u*v)+(u/v),
-                  (u+v)+(u/v),
-                  (u+v)*(u/v),
-                  (u*v)*(u*v),
-                  (u+v)*(u*v),  # H1 same
-                  # (u*v)*(u+v), # H1 same
-                  (u*v)+(u+v),
-                  ]
+            fs = [
+                (u * v) + (u / v),
+                (u + v) + (u / v),
+                (u + v) * (u / v),
+                (u * v) * (u * v),
+                (u + v) * (u * v),  # H1 same
+                # (u*v)*(u+v), # H1 same
+                (u * v) + (u + v),
+            ]
             for f in fs:
-                a = f*dx
+                a = f * dx
                 yield a
+
     check_unique_signatures(forms())
diff --git a/test/test_simplify.py b/test/test_simplify.py
index 66a176d9d..1bbef4ba5 100755
--- a/test/test_simplify.py
+++ b/test/test_simplify.py
@@ -1,7 +1,33 @@
 import math
 
-from ufl import (Coefficient, FunctionSpace, Mesh, TestFunction, TrialFunction, VectorConstant, acos, as_tensor, as_ufl,
-                 asin, atan, cos, cosh, dx, exp, i, j, ln, max_value, min_value, outer, sin, sinh, tan, tanh, triangle)
+from ufl import (
+    Coefficient,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    VectorConstant,
+    acos,
+    as_tensor,
+    as_ufl,
+    asin,
+    atan,
+    cos,
+    cosh,
+    dx,
+    exp,
+    i,
+    j,
+    ln,
+    max_value,
+    min_value,
+    outer,
+    sin,
+    sinh,
+    tan,
+    tanh,
+    triangle,
+)
 from ufl.algorithms import compute_form_data
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
@@ -11,13 +37,13 @@
 def xtest_zero_times_argument(self):
     # FIXME: Allow zero forms
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     v = TestFunction(space)
     u = TrialFunction(space)
-    L = 0*v*dx
-    a = 0*(u*v)*dx
-    b = (0*u)*v*dx
+    L = 0 * v * dx
+    a = 0 * (u * v) * dx
+    b = (0 * u) * v * dx
     assert len(compute_form_data(L).arguments) == 1
     assert len(compute_form_data(a).arguments) == 2
     assert len(compute_form_data(b).arguments) == 2
@@ -25,23 +51,23 @@ def xtest_zero_times_argument(self):
 
 def test_divisions(self):
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     f = Coefficient(space)
 
     # Test simplification of division by 1
     a = f
-    b = f/1
+    b = f / 1
     assert a == b
 
     # Test simplification of division by 1.0
     a = f
-    b = f/1.0
+    b = f / 1.0
     assert a == b
 
     # Test simplification of division by of zero by something
-    a = 0/f
-    b = 0*f
+    a = 0 / f
+    b = 0 * f
     assert a == b
 
     # Test simplification of division by self (this simplification has been disabled)
@@ -52,21 +78,21 @@ def test_divisions(self):
 
 def test_products(self):
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     f = Coefficient(space)
     g = Coefficient(space)
 
     # Test simplification of literal multiplication
-    assert f*0 == as_ufl(0)
-    assert 0*f == as_ufl(0)
-    assert 1*f == f
-    assert f*1 == f
-    assert as_ufl(2)*as_ufl(3) == as_ufl(6)
-    assert as_ufl(2.0)*as_ufl(3.0) == as_ufl(6.0)
+    assert f * 0 == as_ufl(0)
+    assert 0 * f == as_ufl(0)
+    assert 1 * f == f
+    assert f * 1 == f
+    assert as_ufl(2) * as_ufl(3) == as_ufl(6)
+    assert as_ufl(2.0) * as_ufl(3.0) == as_ufl(6.0)
 
     # Test reordering of operands
-    assert f*g == g*f
+    assert f * g == g * f
 
     # Test simplification of self-multiplication (this simplification has been disabled)
     # assert f*f == f**2
@@ -74,7 +100,7 @@ def test_products(self):
 
 def test_sums(self):
     element = FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     space = FunctionSpace(domain, element)
     f = Coefficient(space)
     g = Coefficient(space)
@@ -118,13 +144,13 @@ def test_mathfunctions(self):
         assert math.exp(a) == exp(a)
         assert math.log(a) == ln(a)
         # TODO: Implement automatic simplification of conditionals?
-        assert a == float(max_value(a, a-1))
+        assert a == float(max_value(a, a - 1))
         # TODO: Implement automatic simplification of conditionals?
-        assert a == float(min_value(a, a+1))
+        assert a == float(min_value(a, a + 1))
 
 
 def test_indexing(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     u = VectorConstant(domain)
     v = VectorConstant(domain)
 
@@ -132,7 +158,7 @@ def test_indexing(self):
     A2 = as_tensor(A[i, j], (i, j))
     assert A2 == A
 
-    Bij = u[i]*v[j]
+    Bij = u[i] * v[j]
     Bij2 = as_tensor(Bij, (i, j))[i, j]
     as_tensor(Bij, (i, j))
     assert Bij2 == Bij
diff --git a/test/test_sobolevspace.py b/test/test_sobolevspace.py
index 28e42a24d..b21760f63 100755
--- a/test/test_sobolevspace.py
+++ b/test/test_sobolevspace.py
@@ -6,8 +6,10 @@
 from ufl import H1, H2, L2, HCurl, HDiv, HInf, triangle
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import contravariant_piola, covariant_piola, identity_pullback
-from ufl.sobolevspace import SobolevSpace  # noqa: F401
-from ufl.sobolevspace import DirectionalSobolevSpace
+from ufl.sobolevspace import (
+    DirectionalSobolevSpace,
+    SobolevSpace,  # noqa: F401
+)
 
 # Construct directional Sobolev spaces, with varying smoothness in
 # spatial coordinates
@@ -26,10 +28,10 @@
 
 
 def test_inclusion():
-    assert H2 < H1       # Inclusion
-    assert not H2 > H1   # Not included
+    assert H2 < H1  # Inclusion
+    assert not H2 > H1  # Not included
     assert HDiv <= HDiv  # Reflexivity
-    assert H2 < L2       # Transitivity
+    assert H2 < L2  # Transitivity
     assert H1 > H2
     assert L2 > H1
 
@@ -84,7 +86,7 @@ def test_contains_h1():
         FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1),
         FiniteElement("Lagrange", triangle, 2, (), identity_pullback, H1),
         # Some special elements:
-        FiniteElement("MTW", triangle, 3, (2, ), contravariant_piola, H1),
+        FiniteElement("MTW", triangle, 3, (2,), contravariant_piola, H1),
         FiniteElement("Hermite", triangle, 3, (), "custom", H1),
     ]
     for h1_element in h1_elements:
@@ -115,9 +117,7 @@ def test_contains_h2():
 
 
 def test_contains_hinf():
-    hinf_elements = [
-        FiniteElement("Real", triangle, 0, (), identity_pullback, HInf)
-    ]
+    hinf_elements = [FiniteElement("Real", triangle, 0, (), identity_pullback, HInf)]
     for hinf_element in hinf_elements:
         assert hinf_element in HInf
         assert hinf_element in H2
@@ -132,9 +132,9 @@ def test_contains_hinf():
 
 def test_contains_hdiv():
     hdiv_elements = [
-        FiniteElement("Raviart-Thomas", triangle, 1, (2, ), contravariant_piola, HDiv),
-        FiniteElement("BDM", triangle, 1, (2, ), contravariant_piola, HDiv),
-        FiniteElement("BDFM", triangle, 2, (2, ), contravariant_piola, HDiv),
+        FiniteElement("Raviart-Thomas", triangle, 1, (2,), contravariant_piola, HDiv),
+        FiniteElement("BDM", triangle, 1, (2,), contravariant_piola, HDiv),
+        FiniteElement("BDFM", triangle, 2, (2,), contravariant_piola, HDiv),
     ]
     for hdiv_element in hdiv_elements:
         assert hdiv_element in HDiv
@@ -149,8 +149,8 @@ def test_contains_hdiv():
 
 def test_contains_hcurl():
     hcurl_elements = [
-        FiniteElement("N1curl", triangle, 1, (2, ), covariant_piola, HCurl),
-        FiniteElement("N2curl", triangle, 1, (2, ), covariant_piola, HCurl),
+        FiniteElement("N1curl", triangle, 1, (2,), covariant_piola, HCurl),
+        FiniteElement("N2curl", triangle, 1, (2,), covariant_piola, HCurl),
     ]
     for hcurl_element in hcurl_elements:
         assert hcurl_element in HCurl
diff --git a/test/test_split.py b/test/test_split.py
index 33b0a5885..91eb4b0b6 100755
--- a/test/test_split.py
+++ b/test/test_split.py
@@ -10,14 +10,17 @@
 def test_split(self):
     cell = triangle
     d = cell.topological_dimension()
-    domain = Mesh(FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", cell, 1, (d,), identity_pullback, H1))
     f = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
-    v = FiniteElement("Lagrange", cell, 1, (d, ), identity_pullback, H1,
-                      sub_elements=[f for _ in range(d)])
-    w = FiniteElement("Lagrange", cell, 1, (d+1, ), identity_pullback, H1,
-                      sub_elements=[f for _ in range(d + 1)])
-    t = FiniteElement("Lagrange", cell, 1, (d, d), identity_pullback, H1,
-                      sub_elements=[f for _ in range(d ** 2)])
+    v = FiniteElement(
+        "Lagrange", cell, 1, (d,), identity_pullback, H1, sub_elements=[f for _ in range(d)]
+    )
+    w = FiniteElement(
+        "Lagrange", cell, 1, (d + 1,), identity_pullback, H1, sub_elements=[f for _ in range(d + 1)]
+    )
+    t = FiniteElement(
+        "Lagrange", cell, 1, (d, d), identity_pullback, H1, sub_elements=[f for _ in range(d**2)]
+    )
     s = SymmetricElement({(0, 0): 0, (0, 1): 1, (1, 0): 1, (1, 1): 2}, [f for _ in range(3)])
     m = MixedElement([f, v, w, t, s, s])
 
@@ -31,15 +34,15 @@ def test_split(self):
     # Check that shapes of all these functions are correct:
     assert () == Coefficient(f_space).ufl_shape
     assert (d,) == Coefficient(v_space).ufl_shape
-    assert (d+1,) == Coefficient(w_space).ufl_shape
+    assert (d + 1,) == Coefficient(w_space).ufl_shape
     assert (d, d) == Coefficient(t_space).ufl_shape
     assert (d, d) == Coefficient(s_space).ufl_shape
     # sum of value sizes, not accounting for symmetries:
-    assert (3*d*d + 2*d + 2,) == Coefficient(m_space).ufl_shape
+    assert (3 * d * d + 2 * d + 2,) == Coefficient(m_space).ufl_shape
 
     # Shapes of subelements are reproduced:
     g = Coefficient(m_space)
-    s, = g.ufl_shape
+    (s,) = g.ufl_shape
     for g2 in split(g):
         s -= product(g2.ufl_shape)
     assert s == 0
@@ -51,8 +54,8 @@ def test_split(self):
     m2_space = FunctionSpace(domain, m2)
     # assert d == 2
     # assert (2,2) == Coefficient(v2_space).ufl_shape
-    assert (d+d,) == Coefficient(v2_space).ufl_shape
-    assert (2*d*d,) == Coefficient(m2_space).ufl_shape
+    assert (d + d,) == Coefficient(v2_space).ufl_shape
+    assert (2 * d * d,) == Coefficient(m2_space).ufl_shape
 
     # Split simple element
     t = TestFunction(f_space)
@@ -67,8 +70,7 @@ def test_split(self):
     assert split(t) == (t[0], as_vector((t[1], t[2], t[3])))
     assert split(split(t)[1]) == (t[1], as_vector((t[2], t[3])))
     t = TestFunction(FunctionSpace(domain, MixedElement([[v, f], [f, v]])))
-    assert split(t) == (as_vector((t[0], t[1], t[2])),
-                        as_vector((t[3], t[4], t[5])))
+    assert split(t) == (as_vector((t[0], t[1], t[2])), as_vector((t[3], t[4], t[5])))
     assert split(split(t)[0]) == (as_vector((t[0], t[1])), t[2])
     assert split(split(t)[1]) == (t[3], as_vector((t[4], t[5])))
     assert split(split(split(t)[0])[0]) == (t[0], t[1])
diff --git a/test/test_str.py b/test/test_str.py
index df80d8215..085aee7b2 100755
--- a/test/test_str.py
+++ b/test/test_str.py
@@ -1,6 +1,22 @@
-from ufl import (CellDiameter, CellVolume, Circumradius, FacetArea, FacetNormal, FunctionSpace, Index, Mesh,
-                 SpatialCoordinate, TestFunction, TrialFunction, as_matrix, as_ufl, as_vector, quadrilateral,
-                 tetrahedron, triangle)
+from ufl import (
+    CellDiameter,
+    CellVolume,
+    Circumradius,
+    FacetArea,
+    FacetNormal,
+    FunctionSpace,
+    Index,
+    Mesh,
+    SpatialCoordinate,
+    TestFunction,
+    TrialFunction,
+    as_matrix,
+    as_ufl,
+    as_vector,
+    quadrilateral,
+    tetrahedron,
+    triangle,
+)
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
 from ufl.sobolevspace import H1
@@ -15,11 +31,11 @@ def test_str_float_value(self):
 
 
 def test_str_zero(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x = SpatialCoordinate(domain)
     assert str(as_ufl(0)) == "0"
-    assert str(0*x) == "0 (shape (2,))"
-    assert str(0*x*x[Index(42)]) == "0 (shape (2,), index labels (42,))"
+    assert str(0 * x) == "0 (shape (2,))"
+    assert str(0 * x * x[Index(42)]) == "0 (shape (2,), index labels (42,))"
 
 
 def test_str_index(self):
@@ -28,41 +44,45 @@ def test_str_index(self):
 
 
 def test_str_coordinate(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     assert str(SpatialCoordinate(domain)) == "x"
     assert str(SpatialCoordinate(domain)[0]) == "x[0]"
 
 
 def test_str_normal(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     assert str(FacetNormal(domain)) == "n"
     assert str(FacetNormal(domain)[0]) == "n[0]"
 
 
 def test_str_circumradius(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     assert str(Circumradius(domain)) == "circumradius"
 
 
 def test_str_diameter(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     assert str(CellDiameter(domain)) == "diameter"
 
 
 def test_str_facetarea(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     assert str(FacetArea(domain)) == "facetarea"
 
 
 def test_str_volume(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     assert str(CellVolume(domain)) == "volume"
 
 
 def test_str_scalar_argument(self):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
-    v = TestFunction(FunctionSpace(domain, FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)))
-    u = TrialFunction(FunctionSpace(domain, FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1)))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
+    v = TestFunction(
+        FunctionSpace(domain, FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1))
+    )
+    u = TrialFunction(
+        FunctionSpace(domain, FiniteElement("Lagrange", triangle, 1, (), identity_pullback, H1))
+    )
     assert str(v) == "v_0"
     assert str(u) == "v_1"
 
@@ -75,38 +95,36 @@ def test_str_scalar_argument(self):
 
 
 def test_str_list_vector():
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     x, y, z = SpatialCoordinate(domain)
     v = as_vector((x, y, z))
     assert str(v) == ("[%s, %s, %s]" % (x, y, z))
 
 
 def test_str_list_vector_with_zero():
-    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", tetrahedron, 1, (3,), identity_pullback, H1))
     x, y, z = SpatialCoordinate(domain)
     v = as_vector((x, 0, 0))
     assert str(v) == ("[%s, 0, 0]" % (x,))
 
 
 def test_str_list_matrix():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x, y = SpatialCoordinate(domain)
-    v = as_matrix(((2*x, 3*y),
-                   (4*x, 5*y)))
-    a = str(2*x)
-    b = str(3*y)
-    c = str(4*x)
-    d = str(5*y)
+    v = as_matrix(((2 * x, 3 * y), (4 * x, 5 * y)))
+    a = str(2 * x)
+    b = str(3 * y)
+    c = str(4 * x)
+    d = str(5 * y)
     assert str(v) == ("[\n  [%s, %s],\n  [%s, %s]\n]" % (a, b, c, d))
 
 
 def test_str_list_matrix_with_zero():
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     x, y = SpatialCoordinate(domain)
-    v = as_matrix(((2*x, 3*y),
-                   (0, 0)))
-    a = str(2*x)
-    b = str(3*y)
+    v = as_matrix(((2 * x, 3 * y), (0, 0)))
+    a = str(2 * x)
+    b = str(3 * y)
     c = str(as_vector((0, 0)))
     assert str(v) == ("[\n  [%s, %s],\n%s\n]" % (a, b, c))
 
@@ -117,5 +135,8 @@ def test_str_list_matrix_with_zero():
 
 def test_str_element():
     elem = FiniteElement("Q", quadrilateral, 1, (), identity_pullback, H1)
-    assert repr(elem) == "ufl.finiteelement.FiniteElement(\"Q\", quadrilateral, 1, (), IdentityPullback(), H1)"
+    assert (
+        repr(elem)
+        == 'ufl.finiteelement.FiniteElement("Q", quadrilateral, 1, (), IdentityPullback(), H1)'
+    )
     assert str(elem) == "<Q1 on a quadrilateral>"
diff --git a/test/test_strip_forms.py b/test/test_strip_forms.py
index b58eea904..9b5a0fff9 100644
--- a/test/test_strip_forms.py
+++ b/test/test_strip_forms.py
@@ -1,7 +1,18 @@
 import gc
 import sys
 
-from ufl import Coefficient, Constant, FunctionSpace, Mesh, TestFunction, TrialFunction, dx, grad, inner, triangle
+from ufl import (
+    Coefficient,
+    Constant,
+    FunctionSpace,
+    Mesh,
+    TestFunction,
+    TrialFunction,
+    dx,
+    grad,
+    inner,
+    triangle,
+)
 from ufl.algorithms import replace_terminal_data, strip_terminal_data
 from ufl.core.ufl_id import attach_ufl_id
 from ufl.core.ufl_type import UFLObject
@@ -51,8 +62,9 @@ def test_strip_form_arguments_strips_data_refs():
     assert sys.getrefcount(const_data) == MIN_REF_COUNT
 
     cell = triangle
-    domain = AugmentedMesh(FiniteElement("Lagrange", cell, 1, (2, ),
-                                         identity_pullback, H1), data=mesh_data)
+    domain = AugmentedMesh(
+        FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), data=mesh_data
+    )
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
     V = AugmentedFunctionSpace(domain, element, data=fs_data)
 
@@ -61,7 +73,7 @@ def test_strip_form_arguments_strips_data_refs():
     f = AugmentedCoefficient(V, data=coeff_data)
     k = AugmentedConstant(V, data=const_data)
 
-    form = k*f*inner(grad(v), grad(u))*dx
+    form = k * f * inner(grad(v), grad(u)) * dx
 
     # Remove extraneous references
     del cell, domain, element, V, v, u, f, k
@@ -89,8 +101,9 @@ def test_strip_form_arguments_does_not_change_form():
     const_data = object()
 
     cell = triangle
-    domain = AugmentedMesh(FiniteElement("Lagrange", cell, 1, (2, ),
-                                         identity_pullback, H1), data=mesh_data)
+    domain = AugmentedMesh(
+        FiniteElement("Lagrange", cell, 1, (2,), identity_pullback, H1), data=mesh_data
+    )
     element = FiniteElement("Lagrange", cell, 1, (), identity_pullback, H1)
     V = AugmentedFunctionSpace(domain, element, data=fs_data)
 
@@ -99,7 +112,7 @@ def test_strip_form_arguments_does_not_change_form():
     f = AugmentedCoefficient(V, data=coeff_data)
     k = AugmentedConstant(V, data=const_data)
 
-    form = k*f*inner(grad(v), grad(u))*dx
+    form = k * f * inner(grad(v), grad(u)) * dx
     stripped_form, mapping = strip_terminal_data(form)
 
     assert stripped_form.signature() == form.signature()
diff --git a/test/test_tensoralgebra.py b/test/test_tensoralgebra.py
index bdb6ad406..4d80e671d 100755
--- a/test/test_tensoralgebra.py
+++ b/test/test_tensoralgebra.py
@@ -2,8 +2,30 @@
 
 import pytest
 
-from ufl import (FacetNormal, Mesh, as_matrix, as_tensor, as_vector, cofac, cross, det, dev, diag, diag_vector, dot,
-                 inner, inv, outer, perp, skew, sym, tr, transpose, triangle, zero)
+from ufl import (
+    FacetNormal,
+    Mesh,
+    as_matrix,
+    as_tensor,
+    as_vector,
+    cofac,
+    cross,
+    det,
+    dev,
+    diag,
+    diag_vector,
+    dot,
+    inner,
+    inv,
+    outer,
+    perp,
+    skew,
+    sym,
+    tr,
+    transpose,
+    triangle,
+    zero,
+)
 from ufl.algorithms.remove_complex_nodes import remove_complex_nodes
 from ufl.finiteelement import FiniteElement
 from ufl.pullback import identity_pullback
@@ -43,13 +65,13 @@ def test_repeated_as_tensor(self, A, B, u, v):
 
 def test_outer(self, A, B, u, v):
     C = outer(u, v)
-    D = as_matrix([[10*30, 10*40], [20*30, 20*40]])
+    D = as_matrix([[10 * 30, 10 * 40], [20 * 30, 20 * 40]])
     self.assertEqualValues(C, D)
 
     C = outer(A, v)
     A, v = A, v
     dims = (0, 1)
-    D = as_tensor([[[A[i, j]*v[k] for k in dims] for j in dims] for i in dims])
+    D = as_tensor([[[A[i, j] * v[k] for k in dims] for j in dims] for i in dims])
     self.assertEqualValues(C, D)
 
     # TODO: Test other ranks
@@ -57,18 +79,18 @@ def test_outer(self, A, B, u, v):
 
 def test_inner(self, A, B, u, v):
     C = inner(A, B)
-    D = 2*6 + 3*7 + 4*8 + 5*9
+    D = 2 * 6 + 3 * 7 + 4 * 8 + 5 * 9
     self.assertEqualValues(C, D)
 
     C = inner(u, v)
-    D = 10*30 + 20*40
+    D = 10 * 30 + 20 * 40
     self.assertEqualValues(C, D)
 
 
 def test_pow2_inner(self, A, u):
-    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2, ), identity_pullback, H1))
+    domain = Mesh(FiniteElement("Lagrange", triangle, 1, (2,), identity_pullback, H1))
     f = FacetNormal(domain)[0]
-    f2 = f*f
+    f2 = f * f
     assert f2 == remove_complex_nodes(inner(f, f))
 
     u2 = u**2
@@ -83,13 +105,12 @@ def test_pow2_inner(self, A, u):
 
 def test_dot(self, A, B, u, v):
     C = dot(u, v)
-    D = 10*30 + 20*40
+    D = 10 * 30 + 20 * 40
     self.assertEqualValues(C, D)
 
     C = dot(A, B)
     dims = (0, 1)
-    D = as_matrix([[sum(A[i, k]*B[k, j] for k in dims)
-                    for j in dims] for i in dims])
+    D = as_matrix([[sum(A[i, k] * B[k, j] for k in dims) for j in dims] for i in dims])
     self.assertEqualValues(C, D)
 
 
@@ -131,21 +152,21 @@ def test_perp(self):
 
 def xtest_dev(self, A):
     C = dev(A)
-    D = 0*C  # FIXME: Add expected value here
+    D = 0 * C  # FIXME: Add expected value here
     self.assertEqualValues(C, D)
 
 
 def test_skew(self, A):
     C = skew(A)
     A, dims = A, (0, 1)
-    D = 0.5*as_matrix([[A[i, j] - A[j, i] for j in dims] for i in dims])
+    D = 0.5 * as_matrix([[A[i, j] - A[j, i] for j in dims] for i in dims])
     self.assertEqualValues(C, D)
 
 
 def test_sym(self, A):
     C = sym(A)
     A, dims = A, (0, 1)
-    D = 0.5*as_matrix([[A[i, j] + A[j, i] for j in dims] for i in dims])
+    D = 0.5 * as_matrix([[A[i, j] + A[j, i] for j in dims] for i in dims])
     self.assertEqualValues(C, D)
 
 
@@ -185,7 +206,7 @@ def test_tr(self, A):
 def test_det(self, A):
     dims = (0, 1)
     C = det(A)
-    D = sum((-A[i, 0]*A[0, i] if i != 0 else A[i-1, -1]*A[i, 0]) for i in dims)
+    D = sum((-A[i, 0] * A[0, i] if i != 0 else A[i - 1, -1] * A[i, 0]) for i in dims)
     self.assertEqualValues(C, D)
 
 
@@ -198,6 +219,6 @@ def test_cofac(self, A):
 def xtest_inv(self, A):
     # FIXME: Test fails probably due to integer division
     C = inv(A)
-    detA = sum((-A[i, 0]*A[0, i] if i != 0 else A[i-1, -1]*A[i, 0]) for i in (0, 1))
+    detA = sum((-A[i, 0] * A[0, i] if i != 0 else A[i - 1, -1] * A[i, 0]) for i in (0, 1))
     D = as_matrix([[(-A[i, j] if i != j else A[i, j]) for j in (-1, 0)] for i in (-1, 0)]) / detA
     self.assertEqualValues(C, D)
diff --git a/test/test_utilities.py b/test/test_utilities.py
index 4fdf660d6..a06252898 100755
--- a/test/test_utilities.py
+++ b/test/test_utilities.py
@@ -31,11 +31,14 @@ def test_indexing_to_component():
     for i in range(5):
         for j in range(3):
             for k in range(2):
-                assert 15*k+5*j+i == flatten_multiindex((k, j, i), shape_to_strides((2, 3, 5)))
+                assert 15 * k + 5 * j + i == flatten_multiindex(
+                    (k, j, i), shape_to_strides((2, 3, 5))
+                )
 
 
 def test_component_numbering():
     from ufl.permutation import build_component_numbering
+
     sh = (2, 2)
     sm = {(1, 0): (0, 1)}
     v, s = build_component_numbering(sh, sm)
@@ -45,8 +48,17 @@ def test_component_numbering():
     sh = (3, 3)
     sm = {(1, 0): (0, 1), (2, 0): (0, 2), (2, 1): (1, 2)}
     v, s = build_component_numbering(sh, sm)
-    assert v == {(0, 1): 1, (1, 2): 4, (0, 0): 0, (2, 1): 4, (1, 1): 3,
-                 (2, 0): 2, (2, 2): 5, (1, 0): 1, (0, 2): 2}
+    assert v == {
+        (0, 1): 1,
+        (1, 2): 4,
+        (0, 0): 0,
+        (2, 1): 4,
+        (1, 1): 3,
+        (2, 0): 2,
+        (2, 2): 5,
+        (1, 0): 1,
+        (0, 2): 2,
+    }
     assert s == [(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)]
 
 
@@ -143,11 +155,12 @@ def test_index_flattening():
         i -= 0
         # map back to tensor component:
         c2 = unflatten_index(i, shape_to_strides(ts))
-        assert (k//2, k % 2) == c2
+        assert (k // 2, k % 2) == c2
 
 
 def test_stackdict():
     from ufl.utils.stacks import StackDict
+
     d = StackDict(a=1)
     assert d["a"] == 1
     d.push("a", 2)