Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/ManimCommunity/manim into e…
Browse files Browse the repository at this point in the history
…xperimental
  • Loading branch information
JasonGrace2282 committed Nov 25, 2024
2 parents b51d3fe + fac0aa5 commit c0d842a
Show file tree
Hide file tree
Showing 50 changed files with 1,591 additions and 515 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ repos:
- id: check-toml
name: Validate Poetry
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.0
rev: v0.8.0
hooks:
- id: ruff
name: ruff lint
Expand All @@ -22,7 +22,7 @@ repos:
- id: ruff-format
types: [python]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.12.1
rev: v1.13.0
hooks:
- id: mypy
additional_dependencies:
Expand Down
2 changes: 1 addition & 1 deletion docs/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Basic Concepts
[[i * 256 / n for i in range(0, n)] for _ in range(0, n)]
)
image = ImageMobject(imageArray).scale(2)
image.background_rectangle = SurroundingRectangle(image, GREEN)
image.background_rectangle = SurroundingRectangle(image, color=GREEN)
self.add(image, image.background_rectangle)

.. manim:: BooleanOperations
Expand Down
1 change: 1 addition & 0 deletions docs/source/reference_index/utilities_misc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Module Index
:toctree: ../reference

~utils.bezier
cli
~utils.color
~utils.commands
~utils.config_ops
Expand Down
57 changes: 45 additions & 12 deletions manim/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,49 @@
import click
import cloup

from . import __version__, cli_ctx_settings, console
from .cli.cfg.group import cfg
from .cli.checkhealth.commands import checkhealth
from .cli.default_group import DefaultGroup
from .cli.init.commands import init
from .cli.plugins.commands import plugins
from .cli.render.commands import render
from .constants import EPILOG
from manim import __version__
from manim._config import cli_ctx_settings, console
from manim.cli.cfg.group import cfg
from manim.cli.checkhealth.commands import checkhealth
from manim.cli.default_group import DefaultGroup
from manim.cli.init.commands import init
from manim.cli.plugins.commands import plugins
from manim.cli.render.commands import render
from manim.constants import EPILOG


def show_splash(ctx, param, value):
def show_splash(ctx: click.Context, param: click.Option, value: str | None) -> None:
"""When giving a value by console, show an initial message with the Manim
version before executing any other command: ``Manim Community vA.B.C``.
Parameters
----------
ctx
The Click context.
param
A Click option.
value
A string value given by console, or None.
"""
if value:
console.print(f"Manim Community [green]v{__version__}[/green]\n")


def print_version_and_exit(ctx, param, value):
def print_version_and_exit(
ctx: click.Context, param: click.Option, value: str | None
) -> None:
"""Same as :func:`show_splash`, but also exit when giving a value by
console.
Parameters
----------
ctx
The Click context.
param
A Click option.
value
A string value given by console, or None.
"""
show_splash(ctx, param, value)
if value:
ctx.exit()
Expand Down Expand Up @@ -53,8 +80,14 @@ def print_version_and_exit(ctx, param, value):
expose_value=False,
)
@cloup.pass_context
def main(ctx):
"""The entry point for manim."""
def main(ctx: click.Context) -> None:
"""The entry point for Manim.
Parameters
----------
ctx
The Click context.
"""
pass


Expand Down
3 changes: 2 additions & 1 deletion manim/_config/cli_colors.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from __future__ import annotations

import configparser
from typing import Any

from cloup import Context, HelpFormatter, HelpTheme, Style

__all__ = ["parse_cli_ctx"]


def parse_cli_ctx(parser: configparser.SectionProxy) -> Context:
def parse_cli_ctx(parser: configparser.SectionProxy) -> dict[str, Any]:
formatter_settings: dict[str, str | int] = {
"indent_increment": int(parser["indent_increment"]),
"width": int(parser["width"]),
Expand Down
1 change: 0 additions & 1 deletion manim/animation/composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ def begin(self) -> None:
f"Trying to play {self} without animations, this is not supported. "
"Please add at least one subanimation."
)

for anim in self.animations:
anim.begin()
self.process_subanimation_buffer(anim.buffer)
Expand Down
4 changes: 2 additions & 2 deletions manim/animation/indication.py
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,8 @@ def __init__(
if shape is Rectangle:
frame = SurroundingRectangle(
mobject,
color,
buff,
color=color,
buff=buff,
stroke_width=stroke_width,
)
elif shape is Circle:
Expand Down
17 changes: 17 additions & 0 deletions manim/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""The Manim CLI, and the available commands for ``manim``.
This page is a work in progress. Please run ``manim`` or ``manim --help`` in
your terminal to find more information on the following commands.
Available commands
------------------
.. autosummary::
:toctree: ../reference
cfg
checkhealth
init
plugins
render
"""
81 changes: 49 additions & 32 deletions manim/cli/cfg/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,23 @@
import contextlib
from ast import literal_eval
from pathlib import Path
from typing import Any, cast

import cloup
from rich.errors import StyleSyntaxError
from rich.style import Style

from ... import cli_ctx_settings, console
from ..._config.utils import config_file_paths, make_config_parser
from ...constants import EPILOG
from ...utils.file_ops import guarantee_existence, open_file
from manim._config import cli_ctx_settings, console
from manim._config.utils import config_file_paths, make_config_parser
from manim.constants import EPILOG
from manim.utils.file_ops import guarantee_existence, open_file

RICH_COLOUR_INSTRUCTIONS: str = """
[red]The default colour is used by the input statement.
If left empty, the default colour will be used.[/red]
[magenta] For a full list of styles, visit[/magenta] [green]https://rich.readthedocs.io/en/latest/style.html[/green]
"""
RICH_NON_STYLE_ENTRIES: str = ["log.width", "log.height", "log.timestamps"]
RICH_NON_STYLE_ENTRIES: list[str] = ["log.width", "log.height", "log.timestamps"]

__all__ = [
"value_from_string",
Expand All @@ -41,57 +42,69 @@


def value_from_string(value: str) -> str | int | bool:
"""Extracts the literal of proper datatype from a string.
"""Extract the literal of proper datatype from a ``value`` string.
Parameters
----------
value
The value to check get the literal from.
Returns
-------
Union[:class:`str`, :class:`int`, :class:`bool`]
Returns the literal of appropriate datatype.
:class:`str` | :class:`int` | :class:`bool`
The literal of appropriate datatype.
"""
with contextlib.suppress(SyntaxError, ValueError):
value = literal_eval(value)
return value


def _is_expected_datatype(value: str, expected: str, style: bool = False) -> bool:
"""Checks whether `value` is the same datatype as `expected`,
and checks if it is a valid `style` if `style` is true.
def _is_expected_datatype(
value: str, expected: str, validate_style: bool = False
) -> bool:
"""Check whether the literal from ``value`` is the same datatype as the
literal from ``expected``. If ``validate_style`` is ``True``, also check if
the style given by ``value`` is valid, according to ``rich``.
Parameters
----------
value
The string of the value to check (obtained from reading the user input).
The string of the value to check, obtained from reading the user input.
expected
The string of the literal datatype must be matched by `value`. Obtained from
reading the cfg file.
style
Whether or not to confirm if `value` is a style, by default False
The string of the literal datatype which must be matched by ``value``.
This is obtained from reading the ``cfg`` file.
validate_style
Whether or not to confirm if ``value`` is a valid style, according to
``rich``. Default is ``False``.
Returns
-------
:class:`bool`
Whether or not `value` matches the datatype of `expected`.
Whether or not the literal from ``value`` matches the datatype of the
literal from ``expected``.
"""
value = value_from_string(value)
expected = type(value_from_string(expected))
value_literal = value_from_string(value)
ExpectedLiteralType = type(value_from_string(expected))

return isinstance(value, expected) and (is_valid_style(value) if style else True)
return isinstance(value_literal, ExpectedLiteralType) and (
(isinstance(value_literal, str) and is_valid_style(value_literal))
if validate_style
else True
)


def is_valid_style(style: str) -> bool:
"""Checks whether the entered color is a valid color according to rich
"""Checks whether the entered color style is valid, according to ``rich``.
Parameters
----------
style
The style to check whether it is valid.
Returns
-------
Boolean
Returns whether it is valid style or not according to rich.
:class:`bool`
Whether the color style is valid or not, according to ``rich``.
"""
try:
Style.parse(style)
Expand All @@ -100,16 +113,20 @@ def is_valid_style(style: str) -> bool:
return False


def replace_keys(default: dict) -> dict:
"""Replaces _ to . and vice versa in a dictionary for rich
def replace_keys(default: dict[str, Any]) -> dict[str, Any]:
"""Replace ``_`` with ``.`` and vice versa in a dictionary's keys for
``rich``.
Parameters
----------
default
The dictionary to check and replace
The dictionary whose keys will be checked and replaced.
Returns
-------
:class:`dict`
The dictionary which is modified by replacing _ with . and vice versa
The dictionary whose keys are modified by replacing ``_`` with ``.``
and vice versa.
"""
for key in default:
if "_" in key:
Expand All @@ -133,7 +150,7 @@ def replace_keys(default: dict) -> dict:
help="Manages Manim configuration files.",
)
@cloup.pass_context
def cfg(ctx):
def cfg(ctx: cloup.Context) -> None:
"""Responsible for the cfg subcommand."""
pass

Expand All @@ -147,7 +164,7 @@ def cfg(ctx):
help="Specify if this config is for user or the working directory.",
)
@cloup.option("-o", "--open", "openfile", is_flag=True)
def write(level: str = None, openfile: bool = False) -> None:
def write(level: str | None = None, openfile: bool = False) -> None:
config_paths = config_file_paths()
console.print(
"[yellow bold]Manim Configuration File Writer[/yellow bold]",
Expand All @@ -166,7 +183,7 @@ def write(level: str = None, openfile: bool = False) -> None:
action = "save this as"
for category in parser:
console.print(f"{category}", style="bold green underline")
default = parser[category]
default = cast(dict[str, Any], parser[category])
if category == "logger":
console.print(RICH_COLOUR_INSTRUCTIONS)
default = replace_keys(default)
Expand Down Expand Up @@ -249,7 +266,7 @@ def write(level: str = None, openfile: bool = False) -> None:


@cfg.command(context_settings=cli_ctx_settings)
def show():
def show() -> None:
parser = make_config_parser()
rich_non_style_entries = [a.replace(".", "_") for a in RICH_NON_STYLE_ENTRIES]
for category in parser:
Expand All @@ -269,7 +286,7 @@ def show():
@cfg.command(context_settings=cli_ctx_settings)
@cloup.option("-d", "--directory", default=Path.cwd())
@cloup.pass_context
def export(ctx, directory):
def export(ctx: cloup.Context, directory: str) -> None:
directory_path = Path(directory)
if directory_path.absolute == Path.cwd().absolute:
console.print(
Expand Down
Loading

0 comments on commit c0d842a

Please sign in to comment.