Skip to content

MLR112: Raw .points access assumes a fixed points-per-curve layout

qual reports MLR112 when a method of a confirmed VMobject subclass reshapes or strides self.points with a literal per-curve count — self.points.reshape((-1, 4, 3)) / self.points[a::4] (the Cairo cubic layout) or the 3-point forms (the OpenGL quadratic layout) — while an active profile targets the other renderer.

  • Default severity: warning
  • Minimum confidence: high
  • Implementation phase: 4
  • Fix: none (suggests the public path APIs)

Geometry storage is renderer-specific (DESIGN 3.6): the Cairo VMobject stores cubic Bezier curves as 4 points per curve (n_points_per_cubic_curve = 4), the OpenGLVMobject quadratic curves as 3 (n_points_per_curve = 3). A hard-coded layout silently regroups the wrong points under the other renderer. Public APIs such as get_curves(), get_nth_curve_points(), set_points_as_corners(), and point_from_proportion() are layout-independent.

Raw access is only diagnosed when shape and target renderer are both definite: the receiver must be the literal self of a confirmed VMobject subclass and the shape/stride a literal. Other receivers, non-literal shapes, layout-free reshapes like (-1, 3), and runs without a contradicting-renderer profile stay silent; applicable_profiles lists exactly the profiles the assumption breaks under (DESIGN 15.8).

Wrong (with an OpenGL profile active):

class ZigZag(VMobject):
    def cubic_curves(self):
        return self.points.reshape((-1, 4, 3))

Right:

class ZigZag(VMobject):
    def cubic_curves(self):
        return self.get_curves()