Repository: ManimCommunity/manim
File: manim/animation/transform.py (Python)

Code before:
                                             arc_angle=angle * DEGREES)
                    desc = Text('%d°' % examples[idx]).next_to(left_c, LEFT)
                    # Make the circles in front of the text in front of the arcs.
                    self.add(
                        path_arc.set_z_index(1),
                        desc.set_z_index(2),
                        left_c.set_z_index(3),
                    )
                    anims.append(Transform(left_c, right_c, path_arc=angle * DEGREES))

                self.play(*anims, run_time=2)
                self.wait()

    See also
    --------
    :class:`~.ReplacementTransform`, :meth:`~.Mobject.interpolate`, :meth:`~.Mobject.align_data`
    """

    def __init__(
        self,
        mobject: Mobject | None,
        target_mobject: Mobject | None = None,
        path_func: Callable | None = None,
        path_arc: float = 0,
        path_arc_axis: np.ndarray = OUT,
        path_arc_centers: Point3DLike = None,
        replace_mobject_with_target_in_scene: bool = False,
        **kwargs,
    ) -> None:
        self.path_arc_axis: np.ndarray = path_arc_axis
        self.path_arc_centers: Point3DLike = path_arc_centers
        self.path_arc: float = path_arc

        # path_func is a property a few lines below so it doesn't need to be set in any case
        if path_func is not None:
            self.path_func: Callable = path_func
        elif self.path_arc_centers is not None:
            self.path_func = path_along_circles(
                path_arc,
                self.path_arc_centers,
                self.path_arc_axis,
            )

        self.replace_mobject_with_target_in_scene: bool = (
            replace_mobject_with_target_in_scene
        )
        self.target_mobject: Mobject = (
            target_mobject if target_mobject is not None else Mobject()
        )
        super().__init__(mobject, **kwargs)


Review comment (suggestion):
We need to also include the possibility of `None` in the typehint, given that that's the default value.

Taking a look at `path_along_circles()`: back in the day, I typed the `circles_centers` parameter as `Point3DLike_Array`, based on the name (plural) and how the parameter was used inside that function. Now, upon closer inspection and noticing how `Rotation.__init__()` and `test_TransformWithPathArcCenters()` decide to pass a single point rather than an array of points, I realize that `circles_centers` can actually be `Point3DLike | Point3DLike_Array`. Thus, the type of `path_arc_centers` should actually be:
```suggestion
        path_arc_centers: Point3DLike | Point3DLike_Array | None = None,
```

Feel free to also modify the typehints for `path_along_circles()` if you want to!

Code after:
                                             arc_angle=angle * DEGREES)
                    desc = Text('%d°' % examples[idx]).next_to(left_c, LEFT)
                    # Make the circles in front of the text in front of the arcs.
                    self.add(
                        path_arc.set_z_index(1),
                        desc.set_z_index(2),
                        left_c.set_z_index(3),
                    )
                    anims.append(Transform(left_c, right_c, path_arc=angle * DEGREES))

                self.play(*anims, run_time=2)
                self.wait()

    See also
    --------
    :class:`~.ReplacementTransform`, :meth:`~.Mobject.interpolate`, :meth:`~.Mobject.align_data`
    """

    def __init__(
        self,
        mobject: Mobject | None,
        target_mobject: Mobject | None = None,
        path_func: Callable | None = None,
        path_arc: float = 0,
        path_arc_axis: np.ndarray = OUT,
        path_arc_centers: Point3DLike | Point3DLike_Array | None = None,
        replace_mobject_with_target_in_scene: bool = False,
        **kwargs,
    ) -> None:
        self.path_arc_axis: np.ndarray = path_arc_axis
        self.path_arc_centers: Point3DLike | Point3DLike_Array | None = path_arc_centers
        self.path_arc: float = path_arc

        # path_func is a property a few lines below so it doesn't need to be set in any case
        if path_func is not None:
            self.path_func: Callable = path_func
        elif self.path_arc_centers is not None:
            self.path_func = path_along_circles(
                path_arc,
                self.path_arc_centers,
                self.path_arc_axis,
            )

        self.replace_mobject_with_target_in_scene: bool = (
            replace_mobject_with_target_in_scene
        )
        self.target_mobject: Mobject = (
            target_mobject if target_mobject is not None else Mobject()
        )
        super().__init__(mobject, **kwargs)