diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 48a51afc73..2fb0348f59 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,17 +12,6 @@ repos: - id: end-of-file-fixer - id: check-toml name: Validate Poetry - - repo: https://github.com/pycqa/isort - rev: 5.13.2 - hooks: - - id: isort - name: isort (python) - - id: isort - name: isort (cython) - types: [cython] - - id: isort - name: isort (pyi) - types: [pyi] - repo: https://github.com/asottile/pyupgrade rev: v3.15.2 hooks: @@ -37,6 +26,10 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.4.7 hooks: + - id: ruff + name: ruff lint + types: [python] + args: [--exit-non-zero-on-fix] - id: ruff-format types: [python] - repo: https://github.com/PyCQA/flake8 diff --git a/conftest.py b/conftest.py index dacb730a29..683bd2bc05 100644 --- a/conftest.py +++ b/conftest.py @@ -5,12 +5,6 @@ from __future__ import annotations -try: - # https://github.com/moderngl/moderngl/issues/517 - import readline # required to prevent a segfault on Python 3.10 -except ModuleNotFoundError: # windows - pass - import cairo import moderngl diff --git a/manim/animation/indication.py b/manim/animation/indication.py index 8e2c3996c3..89bf506ebe 100644 --- a/manim/animation/indication.py +++ b/manim/animation/indication.py @@ -63,7 +63,6 @@ def construct(self): from ..mobject.types.vectorized_mobject import VGroup, VMobject from ..utils.bezier import interpolate, inverse_interpolate from ..utils.color import GREY, YELLOW, ParsableManimColor -from ..utils.deprecation import deprecated from ..utils.rate_functions import smooth, there_and_back, wiggle from ..utils.space_ops import normalize diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 9859ced29f..dfc5f231a4 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -5,11 +5,8 @@ import os import shutil -import subprocess from typing import Callable -from ..._config import config - __all__ = ["HEALTH_CHECKS"] HEALTH_CHECKS = [] diff --git a/manim/cli/default_group.py b/manim/cli/default_group.py index 06f1c0520a..f4c8c33dbb 100644 --- a/manim/cli/default_group.py +++ b/manim/cli/default_group.py @@ -10,6 +10,8 @@ of ``click.Group``. """ +from __future__ import annotations + import warnings import cloup diff --git a/manim/mobject/graph.py b/manim/mobject/graph.py index 53d7ed464a..d54c1e0457 100644 --- a/manim/mobject/graph.py +++ b/manim/mobject/graph.py @@ -18,6 +18,7 @@ if TYPE_CHECKING: from typing_extensions import TypeAlias + from manim.scene.scene import Scene from manim.typing import Point3D NxGraph: TypeAlias = nx.classes.graph.Graph | nx.classes.digraph.DiGraph @@ -477,7 +478,7 @@ def _determine_graph_layout( return cast(LayoutFunction, layout)( nx_graph, scale=layout_scale, **layout_config ) - except TypeError as e: + except TypeError: raise ValueError( f"The layout '{layout}' is neither a recognized layout, a layout function," "nor a vertex placement dictionary.", diff --git a/manim/mobject/graphing/scale.py b/manim/mobject/graphing/scale.py index b301d1ff15..5a3a30410b 100644 --- a/manim/mobject/graphing/scale.py +++ b/manim/mobject/graphing/scale.py @@ -146,7 +146,9 @@ def inverse_function(self, value: float) -> float: """Inverse of ``function``. The value must be greater than 0""" if isinstance(value, np.ndarray): condition = value.any() <= 0 - func = lambda value, base: np.log(value) / np.log(base) + + def func(value, base): + return np.log(value) / np.log(base) else: condition = value <= 0 func = math.log diff --git a/manim/mobject/opengl/opengl_mobject.py b/manim/mobject/opengl/opengl_mobject.py index 3bdbd7c0b5..ac34e73509 100644 --- a/manim/mobject/opengl/opengl_mobject.py +++ b/manim/mobject/opengl/opengl_mobject.py @@ -952,33 +952,6 @@ def replace_submobject(self, index, new_submob): self.assemble_family() return self - def invert(self, recursive=False): - """Inverts the list of :attr:`submobjects`. - - Parameters - ---------- - recursive - If ``True``, all submobject lists of this mobject's family are inverted. - - Examples - -------- - - .. manim:: InvertSumobjectsExample - - class InvertSumobjectsExample(Scene): - def construct(self): - s = VGroup(*[Dot().shift(i*0.1*RIGHT) for i in range(-20,20)]) - s2 = s.copy() - s2.invert() - s2.shift(DOWN) - self.play(Write(s), Write(s2)) - """ - if recursive: - for submob in self.submobjects: - submob.invert(recursive=True) - list.reverse(self.submobjects) - self.assemble_family() - # Submobject organization def arrange(self, direction=RIGHT, center=True, **kwargs): @@ -1319,7 +1292,8 @@ def construct(self): if recursive: for submob in self.submobjects: submob.invert(recursive=True) - list.reverse(self.submobjects) + self.submobjects.reverse() + # Is there supposed to be an assemble_family here? # Copying diff --git a/manim/mobject/opengl/opengl_surface.py b/manim/mobject/opengl/opengl_surface.py index bcf608909f..565b8c71cf 100644 --- a/manim/mobject/opengl/opengl_surface.py +++ b/manim/mobject/opengl/opengl_surface.py @@ -12,7 +12,6 @@ from manim.utils.bezier import integer_interpolate, interpolate from manim.utils.color import * from manim.utils.config_ops import _Data, _Uniforms -from manim.utils.deprecation import deprecated from manim.utils.images import change_to_rgba_array, get_full_raster_image_path from manim.utils.iterables import listify from manim.utils.space_ops import normalize_along_axis diff --git a/manim/mobject/text/code_mobject.py b/manim/mobject/text/code_mobject.py index e85f3bf0ba..b7aa6a7980 100644 --- a/manim/mobject/text/code_mobject.py +++ b/manim/mobject/text/code_mobject.py @@ -17,7 +17,6 @@ from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename from pygments.styles import get_all_styles -from manim import logger from manim.constants import * from manim.mobject.geometry.arc import Dot from manim.mobject.geometry.polygram import RoundedRectangle diff --git a/manim/mobject/text/text_mobject.py b/manim/mobject/text/text_mobject.py index 39a1cdd171..6f7b4d9d9f 100644 --- a/manim/mobject/text/text_mobject.py +++ b/manim/mobject/text/text_mobject.py @@ -56,7 +56,6 @@ def construct(self): import copy import hashlib -import os import re from collections.abc import Iterable, Sequence from contextlib import contextmanager diff --git a/manim/mobject/three_d/three_dimensions.py b/manim/mobject/three_d/three_dimensions.py index 540a99bfe9..accb077746 100644 --- a/manim/mobject/three_d/three_dimensions.py +++ b/manim/mobject/three_d/three_dimensions.py @@ -34,14 +34,8 @@ from manim.mobject.opengl.opengl_mobject import OpenGLMobject from manim.mobject.types.vectorized_mobject import VGroup, VMobject from manim.utils.color import ( - BLUE, - BLUE_D, - BLUE_E, - LIGHT_GREY, - WHITE, ManimColor, ParsableManimColor, - interpolate_color, ) from manim.utils.iterables import tuplify from manim.utils.space_ops import normalize, perpendicular_bisector, z_to_vector diff --git a/manim/mobject/types/vectorized_mobject.py b/manim/mobject/types/vectorized_mobject.py index cc938065d3..328a8acce8 100644 --- a/manim/mobject/types/vectorized_mobject.py +++ b/manim/mobject/types/vectorized_mobject.py @@ -911,7 +911,6 @@ def add_line_to(self, point: Point3D) -> Self: :class:`VMobject` ``self`` """ - nppcc = self.n_points_per_cubic_curve self.add_cubic_bezier_curve_to( *( interpolate(self.get_last_point(), point, t) @@ -1060,7 +1059,6 @@ def construct(self): vmob.set_points_as_corners(corners).scale(2) self.add(vmob) """ - nppcc = self.n_points_per_cubic_curve points = np.array(points) # This will set the handles aligned with the anchors. # Id est, a bezier curve will be the segment from the two anchors such that the handles belongs to this segment. diff --git a/manim/renderer/opengl_renderer.py b/manim/renderer/opengl_renderer.py index 5a4d692657..8347f8a49e 100644 --- a/manim/renderer/opengl_renderer.py +++ b/manim/renderer/opengl_renderer.py @@ -1,7 +1,6 @@ from __future__ import annotations import itertools as it -import sys import time from functools import cached_property from typing import Any @@ -569,7 +568,7 @@ def pixel_coords_to_space_coords(self, px, py, relative=False, top_left=False): if pixel_shape is None: return np.array([0, 0, 0]) pw, ph = pixel_shape - fw, fh = config["frame_width"], config["frame_height"] + fh = config["frame_height"] fc = self.camera.get_center() if relative: return 2 * np.array([px / pw, py / ph, 0]) diff --git a/manim/scene/scene.py b/manim/scene/scene.py index 1f5faed4ec..3f80c91864 100644 --- a/manim/scene/scene.py +++ b/manim/scene/scene.py @@ -230,7 +230,7 @@ def render(self, preview: bool = False): self.construct() except EndSceneEarlyException: pass - except RerunSceneException as e: + except RerunSceneException: self.remove(*self.mobjects) self.renderer.clear_screen() self.renderer.num_plays = 0 diff --git a/manim/utils/bezier.py b/manim/utils/bezier.py index 709f8b3bf4..ed1c659b4c 100644 --- a/manim/utils/bezier.py +++ b/manim/utils/bezier.py @@ -2,17 +2,6 @@ from __future__ import annotations -from manim.typing import ( - BezierPoints, - ColVector, - MatrixMN, - Point3D, - Point3D_Array, - PointDType, - QuadraticBezierPoints, - QuadraticBezierPoints_Array, -) - __all__ = [ "bezier", "partial_bezier_points", @@ -35,15 +24,31 @@ from collections.abc import Sequence from functools import reduce -from typing import Any, Callable, overload +from typing import TYPE_CHECKING, Any, Callable, overload import numpy as np -import numpy.typing as npt from scipy import linalg +from manim.typing import PointDType + from ..utils.simple_functions import choose from ..utils.space_ops import cross2d, find_intersection +if TYPE_CHECKING: + import numpy.typing as npt + + from manim.typing import ( + BezierPoints, + BezierPoints_Array, + ColVector, + MatrixMN, + Point3D, + Point3D_Array, + ) + +# l is a commonly used name in linear algebra +# ruff: noqa: E741 + def bezier( points: Sequence[Point3D] | Point3D_Array, diff --git a/manim/utils/color/AS2700.py b/manim/utils/color/AS2700.py index 83a3e6abd0..7b6dc6256c 100644 --- a/manim/utils/color/AS2700.py +++ b/manim/utils/color/AS2700.py @@ -24,6 +24,8 @@ """ +from __future__ import annotations + from .core import ManimColor B11_RICH_BLUE = ManimColor("#2B3770") diff --git a/manim/utils/color/BS381.py b/manim/utils/color/BS381.py index 50ae95b96c..60e8567a50 100644 --- a/manim/utils/color/BS381.py +++ b/manim/utils/color/BS381.py @@ -25,6 +25,8 @@ """ +from __future__ import annotations + from .core import ManimColor BS381_101 = ManimColor("#94BFAC") diff --git a/manim/utils/color/X11.py b/manim/utils/color/X11.py index 0379717eac..4338660200 100644 --- a/manim/utils/color/X11.py +++ b/manim/utils/color/X11.py @@ -23,6 +23,8 @@ .. automanimcolormodule:: manim.utils.color.X11 """ +from __future__ import annotations + from .core import ManimColor ALICEBLUE = ManimColor("#F0F8FF") diff --git a/manim/utils/color/XKCD.py b/manim/utils/color/XKCD.py index db9bccaed3..4c38af6862 100644 --- a/manim/utils/color/XKCD.py +++ b/manim/utils/color/XKCD.py @@ -24,6 +24,8 @@ """ +from __future__ import annotations + from .core import ManimColor ACIDGREEN = ManimColor("#8FFE09") diff --git a/manim/utils/color/__init__.py b/manim/utils/color/__init__.py index cfffc4edc9..362a31ac25 100644 --- a/manim/utils/color/__init__.py +++ b/manim/utils/color/__init__.py @@ -47,7 +47,7 @@ """ -from typing import Dict, List +from __future__ import annotations from . import AS2700, BS381, X11, XKCD from .core import * diff --git a/manim/utils/color/manim_colors.py b/manim/utils/color/manim_colors.py index 863cb5a99f..a3eacc83a4 100644 --- a/manim/utils/color/manim_colors.py +++ b/manim/utils/color/manim_colors.py @@ -121,7 +121,7 @@ def named_lines_group(length, colors, names, text_colors, align_to_block): """ -from typing import List +from __future__ import annotations from .core import ManimColor diff --git a/manim/utils/docbuild/autoaliasattr_directive.py b/manim/utils/docbuild/autoaliasattr_directive.py index 6dd645a9fd..6cb4137833 100644 --- a/manim/utils/docbuild/autoaliasattr_directive.py +++ b/manim/utils/docbuild/autoaliasattr_directive.py @@ -12,7 +12,6 @@ if TYPE_CHECKING: from sphinx.application import Sphinx - from typing_extensions import TypeAlias __all__ = ["AliasAttrDocumenter"] @@ -49,7 +48,9 @@ def smart_replace(base: str, alias: str, substitution: str) -> str: occurrences = [] len_alias = len(alias) len_base = len(base) - condition = lambda char: (not char.isalnum()) and char != "_" + + def condition(char: str) -> bool: + return not char.isalnum() and char != "_" start = 0 i = 0 diff --git a/manim/utils/docbuild/manim_directive.py b/manim/utils/docbuild/manim_directive.py index 111b40fa4d..8b65293956 100644 --- a/manim/utils/docbuild/manim_directive.py +++ b/manim/utils/docbuild/manim_directive.py @@ -82,7 +82,6 @@ def construct(self): import csv import itertools as it -import os import re import shutil import sys diff --git a/manim/utils/docbuild/module_parsing.py b/manim/utils/docbuild/module_parsing.py index 87bfa76c40..5166ff4801 100644 --- a/manim/utils/docbuild/module_parsing.py +++ b/manim/utils/docbuild/module_parsing.py @@ -47,6 +47,7 @@ # In the following, we will use ``type(xyz) is xyz_type`` instead of # isinstance checks to make sure no subclasses of the type pass the # check +# ruff: noqa: E721 def parse_module_attributes() -> tuple[AliasDocsDict, DataDict]: diff --git a/manim/utils/file_ops.py b/manim/utils/file_ops.py index 58c82464a1..7efcee02c5 100644 --- a/manim/utils/file_ops.py +++ b/manim/utils/file_ops.py @@ -32,7 +32,7 @@ from manim import __version__, config, logger -from .. import config, console +from .. import console def is_mp4_format() -> bool: diff --git a/manim/utils/ipython_magic.py b/manim/utils/ipython_magic.py index 7911da9cf3..601d4d6f8e 100644 --- a/manim/utils/ipython_magic.py +++ b/manim/utils/ipython_magic.py @@ -3,13 +3,12 @@ from __future__ import annotations import mimetypes -import os import shutil from datetime import datetime from pathlib import Path from typing import Any -from manim import Group, config, logger, tempconfig +from manim import config, logger, tempconfig from manim.__main__ import main from manim.renderer.shader import shader_program_cache diff --git a/manim/utils/module_ops.py b/manim/utils/module_ops.py index 2ff7291470..03f297030d 100644 --- a/manim/utils/module_ops.py +++ b/manim/utils/module_ops.py @@ -2,7 +2,6 @@ import importlib.util import inspect -import os import re import sys import types diff --git a/manim/utils/simple_functions.py b/manim/utils/simple_functions.py index 72a0f8ddbd..898c1d527b 100644 --- a/manim/utils/simple_functions.py +++ b/manim/utils/simple_functions.py @@ -10,9 +10,7 @@ ] -import inspect from functools import lru_cache -from types import MappingProxyType from typing import Callable import numpy as np diff --git a/manim/utils/space_ops.py b/manim/utils/space_ops.py index ec47d136eb..197621fce6 100644 --- a/manim/utils/space_ops.py +++ b/manim/utils/space_ops.py @@ -10,7 +10,7 @@ from mapbox_earcut import triangulate_float32 as earcut from scipy.spatial.transform import Rotation -from manim.constants import DOWN, OUT, PI, RIGHT, TAU, UP, RendererType +from manim.constants import DOWN, OUT, PI, RIGHT, TAU, UP from manim.utils.iterables import adjacent_pairs if TYPE_CHECKING: diff --git a/pyproject.toml b/pyproject.toml index 7b05d004df..ebf7a27b5d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -134,6 +134,47 @@ extend-exclude = [ ] fix = true +[tool.ruff.lint] +select = [ + "E", + "F", + "I", +] + +ignore = [ + # due to the import * used in manim + "F403", + "F405", + # as recommended by https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules + "E111", + "E114", + "E117", + "E501", +] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.lint.per-file-ignores] +"tests/*" = [ + # unused variable + "F841", + # from __future__ import annotations + "I002", +] + +"example_scenes/*" = [ + "I002", +] + +"__init__.py" = [ + "F401", + "F403", +] + +[tool.ruff.lint.isort] +required-imports = ["from __future__ import annotations"] + [tool.ruff.format] docstring-code-format = true diff --git a/scripts/dev_changelog.py b/scripts/dev_changelog.py index d226b0195f..35e77dd798 100755 --- a/scripts/dev_changelog.py +++ b/scripts/dev_changelog.py @@ -301,7 +301,6 @@ def main(token, prior, tag, additional, outfile): for PR in pr_by_labels[label]: num = PR.number - url = PR.html_url title = PR.title label = PR.labels f.write(f"* :pr:`{num}`: {title}\n") diff --git a/scripts/extract_frames.py b/scripts/extract_frames.py index d3c7691895..a8900de5c0 100644 --- a/scripts/extract_frames.py +++ b/scripts/extract_frames.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pathlib import sys diff --git a/tests/interface/test_commands.py b/tests/interface/test_commands.py index d902d3b07b..c6223a78cb 100644 --- a/tests/interface/test_commands.py +++ b/tests/interface/test_commands.py @@ -8,7 +8,7 @@ from click.testing import CliRunner -from manim import __version__, capture, tempconfig +from manim import __version__, capture from manim.__main__ import main from manim.cli.checkhealth.checks import HEALTH_CHECKS diff --git a/tests/module/mobject/geometry/test_unit_geometry.py b/tests/module/mobject/geometry/test_unit_geometry.py index 1729752fff..45f4da279f 100644 --- a/tests/module/mobject/geometry/test_unit_geometry.py +++ b/tests/module/mobject/geometry/test_unit_geometry.py @@ -4,10 +4,10 @@ import numpy as np -logger = logging.getLogger(__name__) - from manim import BackgroundRectangle, Circle, Sector +logger = logging.getLogger(__name__) + def test_get_arc_center(): np.testing.assert_array_equal( diff --git a/tests/module/mobject/graphing/test_coordinate_system.py b/tests/module/mobject/graphing/test_coordinate_system.py index 4aa71f8968..727bb0ba68 100644 --- a/tests/module/mobject/graphing/test_coordinate_system.py +++ b/tests/module/mobject/graphing/test_coordinate_system.py @@ -5,9 +5,22 @@ import numpy as np import pytest -from manim import LEFT, ORIGIN, PI, UR, Axes, Circle, ComplexPlane +from manim import ( + LEFT, + ORIGIN, + PI, + UR, + Axes, + Circle, + ComplexPlane, + Dot, + NumberPlane, + PolarPlane, + ThreeDAxes, + config, + tempconfig, +) from manim import CoordinateSystem as CS -from manim import Dot, NumberPlane, PolarPlane, ThreeDAxes, config, tempconfig def test_initial_config(): diff --git a/tests/module/mobject/text/test_texmobject.py b/tests/module/mobject/text/test_texmobject.py index 9f487be4e8..c8d4f51f84 100644 --- a/tests/module/mobject/text/test_texmobject.py +++ b/tests/module/mobject/text/test_texmobject.py @@ -6,8 +6,6 @@ import pytest from manim import MathTex, SingleStringMathTex, Tex, TexTemplate, config, tempconfig -from manim.mobject.types.vectorized_mobject import VMobject -from manim.utils.color import RED def test_MathTex(): diff --git a/tests/module/utils/test_space_ops.py b/tests/module/utils/test_space_ops.py index eef307b4b6..13584c797d 100644 --- a/tests/module/utils/test_space_ops.py +++ b/tests/module/utils/test_space_ops.py @@ -4,7 +4,7 @@ import pytest from manim.utils.space_ops import * -from manim.utils.space_ops import shoelace, shoelace_direction +from manim.utils.space_ops import shoelace def test_rotate_vector(): diff --git a/tests/opengl/test_coordinate_system_opengl.py b/tests/opengl/test_coordinate_system_opengl.py index 603f8eba54..ed596d7e9d 100644 --- a/tests/opengl/test_coordinate_system_opengl.py +++ b/tests/opengl/test_coordinate_system_opengl.py @@ -5,9 +5,21 @@ import numpy as np import pytest -from manim import LEFT, ORIGIN, PI, UR, Axes, Circle, ComplexPlane +from manim import ( + LEFT, + ORIGIN, + PI, + UR, + Axes, + Circle, + ComplexPlane, + NumberPlane, + PolarPlane, + ThreeDAxes, + config, + tempconfig, +) from manim import CoordinateSystem as CS -from manim import NumberPlane, PolarPlane, ThreeDAxes, config, tempconfig def test_initial_config(using_opengl_renderer): diff --git a/tests/test_config.py b/tests/test_config.py index ed2f4b59c0..0c60d59b10 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,6 +1,5 @@ from __future__ import annotations -import os import tempfile from pathlib import Path @@ -103,7 +102,6 @@ def test_custom_dirs(tmp_path): "frame_rate": 15, "pixel_height": 854, "pixel_width": 480, - "save_sections": True, "sections_dir": "{media_dir}/test_sections", "video_dir": "{media_dir}/test_video", "partial_movie_dir": "{media_dir}/test_partial_movie_dir", diff --git a/tests/test_graphical_units/test_axes.py b/tests/test_graphical_units/test_axes.py index 8e450511d2..2e06300e46 100644 --- a/tests/test_graphical_units/test_axes.py +++ b/tests/test_graphical_units/test_axes.py @@ -293,7 +293,10 @@ def test_get_z_axis_label(scene): @frames_comparison def test_polar_graph(scene): polar = PolarPlane() - r = lambda theta: 4 * np.sin(theta * 4) + + def r(theta): + return 4 * np.sin(theta * 4) + polar_graph = polar.plot_polar_graph(r) scene.add(polar, polar_graph) diff --git a/tests/test_graphical_units/test_tex_mobject.py b/tests/test_graphical_units/test_tex_mobject.py index d92162b379..b229e1cb0f 100644 --- a/tests/test_graphical_units/test_tex_mobject.py +++ b/tests/test_graphical_units/test_tex_mobject.py @@ -1,5 +1,3 @@ -import pytest - from manim import * from manim.utils.testing.frames_comparison import frames_comparison diff --git a/tests/test_graphical_units/test_text.py b/tests/test_graphical_units/test_text.py index 21649222be..ab5d4fbeb1 100644 --- a/tests/test_graphical_units/test_text.py +++ b/tests/test_graphical_units/test_text.py @@ -1,6 +1,4 @@ -import pytest - -from manim import RED, MarkupText, Text, VGroup, VMobject +from manim import RED, MarkupText, Text, VMobject __module_test__ = "text"