Repository: ManimCommunity/manim
File: manim/renderer/shader.py (Python)

Code before:
    def match_updaters(self, mobject: Mobject) -> Self:
        self.clear_updaters()
        for updater in mobject.get_updaters():
            self.add_updater(updater)
        return self

    def suspend_updating(self) -> Self:
        self.updating_suspended = True
        return self

    def resume_updating(self, call_updater: bool = True) -> Self:
        self.updating_suspended = False
        if call_updater:
            self.update(dt=0)
        return self

    def refresh_has_updater_status(self) -> Self:
        self.has_updaters = len(self.get_updaters()) > 0
        return self


class Mesh(Object3D):
    def __init__(
        self,
        shader: Shader | None = None,
        attributes: list[Attribute] | None = None,
        # Based on the current codebase, the geometry parameter can only be set to None.
        geometry: None = None,
        # Based on the current codebase, the material parameter can only be set to None.
        material: None = None,
        indices: npt.NDArray = None,
        use_depth_test: bool = True,
        primitive: int = moderngl.TRIANGLES,
    ):
        super().__init__()
        if shader is not None and attributes is not None:
            self.shader: Shader = shader
            self.attributes = attributes
            self.indices = indices
        elif geometry is not None and material is not None:
            self.shader = material
            self.attributes = geometry.attributes
            self.indices = geometry.index
        else:
            raise Exception(
                "Mesh requires either attributes and a Shader or a Geometry and a "
                "Material",
            )
        self.use_depth_test = use_depth_test
        self.primitive = primitive
        self.skip_render: bool = False

Review comment (suggestion):
It seems like `attributes` should be a NumPy array, just like the `unfiltered_attributes` in an earlier function.
```suggestion
        attributes: npt.NDArray | None = None,
```

Code after:
        while update_function in self.time_based_updaters:
            self.time_based_updaters.remove(update_function)  # type: ignore[arg-type]
        while update_function in self.non_time_updaters:
            self.non_time_updaters.remove(update_function)  # type: ignore[arg-type]
        self.refresh_has_updater_status()
        return self

    def clear_updaters(self) -> Self:
        self.time_based_updaters = []
        self.non_time_updaters = []
        self.refresh_has_updater_status()
        return self

    def match_updaters(self, mesh: Object3D) -> Self:
        self.clear_updaters()
        for updater in mesh.get_updaters():
            self.add_updater(updater)
        return self

    def suspend_updating(self) -> Self:
        self.updating_suspended = True
        return self

    def resume_updating(self, call_updater: bool = True) -> Self:
        self.updating_suspended = False
        if call_updater:
            self.update(dt=0)
        return self

    def refresh_has_updater_status(self) -> Self:
        self.has_updaters = len(self.get_updaters()) > 0
        return self


class Mesh(Object3D):
    def __init__(
        self,
        shader: Shader | None = None,
        attributes: npt.NDArray | None = None,
        geometry: Mesh | None = None,
        material: Shader | None = None,
        indices: npt.NDArray | None = None,
        use_depth_test: bool = True,
        primitive: int = moderngl.TRIANGLES,
    ):
        super().__init__()
        if shader is not None and attributes is not None:
            self.shader: Shader = shader
            self.attributes = attributes
            self.indices = indices
        elif geometry is not None and material is not None: