mirror of
https://github.com/jeertmans/manim-slides.git
synced 2025-08-24 21:17:36 +08:00
chore(dev): move to Rye instead of PDM (#420)
* test: re-add opencv-python * chore(dev): move to Rye instead of PDM * try fix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: build backend * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: string quotes? * small fixes * upgrade typing * fix(ci): rye install on Windows * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix(ci): typos * fix * fix(ci): actually use right python version * fix(deps): manimgl * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix docs * another fix * cleanup * make sure to use trusted publisher * chore(docs): remove PDM --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
19
.github/workflows/publish.yml
vendored
19
.github/workflows/publish.yml
vendored
@ -18,15 +18,22 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install PDM
|
||||
uses: pdm-project/setup-pdm@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
cache: true
|
||||
- name: Setup Rye
|
||||
env:
|
||||
RYE_INSTALL_OPTION: --yes
|
||||
run: |
|
||||
curl -sSf https://rye-up.com/get | bash
|
||||
echo "$HOME/.rye/shims" >> $GITHUB_PATH
|
||||
|
||||
- name: Configure Rye
|
||||
run: rye config --set-bool behavior.use-uv=true
|
||||
|
||||
- name: Build package
|
||||
run: rye build
|
||||
|
||||
- name: Publish to PyPI
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
|
||||
run: pdm publish
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
|
||||
publish-docker:
|
||||
name: Publish Docker image
|
||||
|
47
.github/workflows/tests.yml
vendored
47
.github/workflows/tests.yml
vendored
@ -25,28 +25,30 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install PDM
|
||||
uses: pdm-project/setup-pdm@v4
|
||||
with:
|
||||
python-version: ${{ matrix.pyversion }}
|
||||
cache: true
|
||||
|
||||
# Path related stuff
|
||||
- name: Append to Path on MacOS
|
||||
if: matrix.os == 'macos-latest'
|
||||
- name: Setup Rye
|
||||
if: matrix.os != 'windows-latest'
|
||||
env:
|
||||
RYE_TOOLCHAIN_VERSION: ${{ matrix.pyversion}}
|
||||
RYE_INSTALL_OPTION: --yes
|
||||
run: |
|
||||
echo "${HOME}/.local/bin" >> $GITHUB_PATH
|
||||
echo "/Users/runner/Library/Python/${{ matrix.pyversion }}/bin" >> $GITHUB_PATH
|
||||
curl -sSf https://rye-up.com/get | bash
|
||||
echo "$HOME/.rye/shims" >> $GITHUB_PATH
|
||||
|
||||
- name: Append to Path on Ubuntu
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: echo "${HOME}/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Append to Path on Windows
|
||||
# Stolen from https://github.com/bluss/pyproject-local-kernel/blob/2b641290694adc998fb6bceea58d3737523a68b7/.github/workflows/ci.yaml
|
||||
- name: Install Rye (Windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: echo "${HOME}/.local/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
shell: bash
|
||||
run: |
|
||||
C:/msys64/usr/bin/wget.exe -q 'https://github.com/astral-sh/rye/releases/latest/download/rye-x86_64-windows.exe' -O rye-x86_64-windows.exe
|
||||
./rye-x86_64-windows.exe self install --toolchain-version ${{ matrix.pyversion }} --modify-path -y
|
||||
echo "$HOME\\.rye\\shims" >> $GITHUB_PATH
|
||||
|
||||
- name: Configure Rye
|
||||
shell: bash
|
||||
run: |
|
||||
rye config --set-bool behavior.use-uv=true
|
||||
rye pin ${{ matrix.pyversion }}
|
||||
|
||||
# OS dependencies
|
||||
- name: Install manim dependencies on MacOS
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: brew install ffmpeg py3cairo
|
||||
@ -68,16 +70,17 @@ jobs:
|
||||
uses: ssciwr/setup-mesa-dist-win@v2
|
||||
|
||||
- name: Install Manim Slides
|
||||
run: |
|
||||
pdm sync -Ggithub-action -Gtest
|
||||
shell: bash
|
||||
run: rye sync
|
||||
|
||||
- name: Run pytest
|
||||
shell: bash
|
||||
if: matrix.os != 'ubuntu-latest' || matrix.pyversion != '3.11'
|
||||
run: pdm run pytest
|
||||
run: rye run pytest
|
||||
|
||||
- name: Run pytest and coverage
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.pyversion == '3.11'
|
||||
run: pdm run pytest --cov-report xml --cov=manim_slides tests/
|
||||
run: rye run pytest --cov-report xml --cov=manim_slides tests/
|
||||
|
||||
- name: Upload to codecov.io
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.pyversion == '3.11'
|
||||
|
1
.python-version
Normal file
1
.python-version
Normal file
@ -0,0 +1 @@
|
||||
3.11.8
|
@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
[#417](https://github.com/jeertmans/manim-slides/pull/417)
|
||||
- Create FAQ page and clear FAQ from README.md.
|
||||
[#418](https://github.com/jeertmans/manim-slides/pull/418)
|
||||
- Used Rye instead of PDM for faster development.
|
||||
[#420](https://github.com/jeertmans/manim-slides/pull/420)
|
||||
|
||||
(unreleased-fixed)=
|
||||
### Fixed
|
||||
|
@ -24,61 +24,25 @@ the repository, and clone it locally.
|
||||
|
||||
As for every Python project, using virtual environment is recommended to avoid
|
||||
conflicts between modules.
|
||||
For this project, we use [PDM](https://pdm-project.org/) to easily manage project
|
||||
For this project, we use [Rye](https://rye-up.com/) to easily manage project
|
||||
and development dependencies. If not already, please install this tool.
|
||||
|
||||
## Installing Python modules
|
||||
|
||||
With PDM, installation becomes straightforward:
|
||||
With Rye, installation becomes straightforward:
|
||||
|
||||
```bash
|
||||
pdm install
|
||||
rye sync --all-features
|
||||
```
|
||||
|
||||
This, however, only installs the minimal set of dependencies to run the package.
|
||||
|
||||
If you would like to install Manim or ManimGL,
|
||||
as documented in the [quickstart](/quickstart),
|
||||
you can use the `-G|--group` option:
|
||||
|
||||
```bash
|
||||
pdm install -Gmanim # For Manim
|
||||
# or
|
||||
pdm install -Gmanimgl # For ManimGL
|
||||
```
|
||||
|
||||
Additionally, Manim Slides comes with groups of dependencies for development purposes:
|
||||
|
||||
```bash
|
||||
pdm install -Gdev # For linters and formatters
|
||||
# or
|
||||
pdm install -Gdocs # To build the documentation locally
|
||||
# or
|
||||
pdm install -Gtest # To run tests
|
||||
```
|
||||
|
||||
:::{note}
|
||||
You can combine any number of groups or extras when installing the package locally.
|
||||
|
||||
You can also install everything with `pdm install -G:all`.
|
||||
:::
|
||||
|
||||
## Running commands
|
||||
|
||||
Because modules are installed in a new Python environment,
|
||||
you cannot use them directly in the shell.
|
||||
Instead, you either need to prepend `pdm run` to any command, e.g.:
|
||||
Instead, you either need to prepend `rye run` to any command, e.g.:
|
||||
|
||||
```bash
|
||||
pdm run manim-slides wizard
|
||||
```
|
||||
|
||||
or [enter a new shell](https://pdm-project.org/latest/usage/venv/#activate-a-virtualenv)
|
||||
that uses this new Python environment:
|
||||
|
||||
```bash
|
||||
eval $(pdm venv activate) # Click on the link above to see shell-specific command
|
||||
manim-slides wizard
|
||||
rye run manim-slides wizard
|
||||
```
|
||||
|
||||
## Testing your code
|
||||
@ -87,7 +51,7 @@ Most of the tests are done with GitHub actions, thus not on your computer.
|
||||
The only command you should run locally is:
|
||||
|
||||
```bash
|
||||
pdm run pre-commit run --all-files
|
||||
rye run pre-commit run --all-files
|
||||
```
|
||||
|
||||
This runs a few linter and formatter to make sure the code quality and style stay
|
||||
@ -97,7 +61,7 @@ If a warning or an error is displayed, please fix it before going to next step.
|
||||
For testing your code, simply run:
|
||||
|
||||
```bash
|
||||
pdm run pytest
|
||||
rye run pytest
|
||||
```
|
||||
|
||||
## Building the documentation
|
||||
@ -109,7 +73,7 @@ To generate the documentation, run the following:
|
||||
|
||||
```bash
|
||||
cd docs
|
||||
pdm run make html
|
||||
rye run make html
|
||||
```
|
||||
|
||||
Then, the output index file is located at `docs/build/html/index.html` and
|
||||
|
@ -106,7 +106,9 @@ Along with the optional dependencies for Manim and ManimGL,
|
||||
Manim Slides offers additional *extras*, that can be activated
|
||||
using optional dependencies:
|
||||
|
||||
- `full`, to include `magic`, `manim`, `manimgl`, and
|
||||
- `full`, to include `magic`, `manim`, and
|
||||
`sphinx-directive` extras (see below);
|
||||
- `full-gl`, to include `magic`, `manimgl`, and
|
||||
`sphinx-directive` extras (see below);
|
||||
- `magic`, to include a Jupyter magic to render
|
||||
animations inside notebooks. This automatically installs `manim`,
|
||||
|
@ -15,7 +15,6 @@ the slides.
|
||||
If both modules are present in {py:data}`sys.modules`, then Manim Slides will
|
||||
prefer using `manim`.
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
The simplest way to use Manim Slides with the correct Manim API is to:
|
||||
|
@ -18,6 +18,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from manim import *\n",
|
||||
"\n",
|
||||
"from manim_slides import *"
|
||||
]
|
||||
},
|
||||
|
@ -29,7 +29,7 @@ class Module(ModuleType):
|
||||
|
||||
return ModuleType.__getattribute__(self, name)
|
||||
|
||||
def __dir__(self) -> List[str]:
|
||||
def __dir__(self) -> list[str]:
|
||||
result = list(new_module.__all__)
|
||||
result.extend(
|
||||
(
|
||||
|
@ -4,7 +4,7 @@ from functools import wraps
|
||||
from inspect import Parameter, signature
|
||||
from pathlib import Path
|
||||
from textwrap import dedent
|
||||
from typing import Any, Callable, Dict, List, Optional, Set, Tuple
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
import rtoml
|
||||
from pydantic import (
|
||||
@ -24,7 +24,7 @@ Receiver = Callable[..., Any]
|
||||
|
||||
|
||||
class Signal(BaseModel): # type: ignore[misc]
|
||||
__receivers: List[Receiver] = PrivateAttr(default_factory=list)
|
||||
__receivers: list[Receiver] = PrivateAttr(default_factory=list)
|
||||
|
||||
def connect(self, receiver: Receiver) -> None:
|
||||
self.__receivers.append(receiver)
|
||||
@ -47,14 +47,14 @@ def key_id(name: str) -> PositiveInt:
|
||||
class Key(BaseModel): # type: ignore[misc]
|
||||
"""Represents a list of key codes, with optionally a name."""
|
||||
|
||||
ids: List[PositiveInt] = Field(unique=True)
|
||||
ids: list[PositiveInt] = Field(unique=True)
|
||||
name: Optional[str] = None
|
||||
|
||||
__signal: Signal = PrivateAttr(default_factory=Signal)
|
||||
|
||||
@field_validator("ids")
|
||||
@classmethod
|
||||
def ids_is_non_empty_set(cls, ids: Set[Any]) -> Set[Any]:
|
||||
def ids_is_non_empty_set(cls, ids: set[Any]) -> set[Any]:
|
||||
if len(ids) <= 0:
|
||||
raise ValueError("Key's ids must be a non-empty set")
|
||||
return ids
|
||||
@ -98,8 +98,8 @@ class Keys(BaseModel): # type: ignore[misc]
|
||||
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def ids_are_unique_across_keys(cls, values: Dict[str, Key]) -> Dict[str, Key]:
|
||||
ids: Set[int] = set()
|
||||
def ids_are_unique_across_keys(cls, values: dict[str, Key]) -> dict[str, Key]:
|
||||
ids: set[int] = set()
|
||||
|
||||
for key in values.values():
|
||||
if len(ids.intersection(key["ids"])) != 0:
|
||||
@ -296,8 +296,8 @@ class SlideConfig(BaseSlideConfig):
|
||||
|
||||
|
||||
class PresentationConfig(BaseModel): # type: ignore[misc]
|
||||
slides: List[SlideConfig] = Field(min_length=1)
|
||||
resolution: Tuple[PositiveInt, PositiveInt] = (1920, 1080)
|
||||
slides: list[SlideConfig] = Field(min_length=1)
|
||||
resolution: tuple[PositiveInt, PositiveInt] = (1920, 1080)
|
||||
background_color: Color = "black"
|
||||
|
||||
@classmethod
|
||||
|
@ -2,7 +2,6 @@ import mimetypes
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import webbrowser
|
||||
from base64 import b64encode
|
||||
@ -10,7 +9,7 @@ from collections import deque
|
||||
from enum import Enum
|
||||
from importlib import resources
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Dict, List, Optional, Type, Union
|
||||
from typing import Any, Callable, Optional, Union
|
||||
|
||||
import av
|
||||
import click
|
||||
@ -53,7 +52,7 @@ def open_with_default(file: Path) -> None:
|
||||
|
||||
def validate_config_option(
|
||||
ctx: Context, param: Parameter, value: Any
|
||||
) -> Dict[str, str]:
|
||||
) -> dict[str, str]:
|
||||
config = {}
|
||||
|
||||
for c_option in value:
|
||||
@ -121,7 +120,7 @@ class Converter(BaseModel): # type: ignore
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, s: str) -> Type["Converter"]:
|
||||
def from_string(cls, s: str) -> type["Converter"]:
|
||||
"""Return the appropriate converter from a string name."""
|
||||
return {
|
||||
"html": RevealJS,
|
||||
@ -329,7 +328,7 @@ class RevealJS(Converter):
|
||||
auto_animate_easing: AutoAnimateEasing = AutoAnimateEasing.ease
|
||||
auto_animate_duration: float = 1.0
|
||||
auto_animate_unmatched: JsBool = JsBool.true
|
||||
auto_animate_styles: List[str] = Field(
|
||||
auto_animate_styles: list[str] = Field(
|
||||
default_factory=lambda: [
|
||||
"opacity",
|
||||
"color",
|
||||
@ -379,9 +378,6 @@ class RevealJS(Converter):
|
||||
if isinstance(self.template, Path):
|
||||
return self.template.read_text()
|
||||
|
||||
if sys.version_info < (3, 9):
|
||||
return resources.read_text(templates, "revealjs.html")
|
||||
|
||||
return resources.files(templates).joinpath("revealjs.html").read_text()
|
||||
|
||||
def open(self, file: Path) -> bool:
|
||||
@ -658,13 +654,13 @@ def show_template_option(function: Callable[..., Any]) -> Callable[..., Any]:
|
||||
@show_config_options
|
||||
@verbosity_option
|
||||
def convert(
|
||||
scenes: List[str],
|
||||
scenes: list[str],
|
||||
folder: Path,
|
||||
dest: Path,
|
||||
to: str,
|
||||
open_result: bool,
|
||||
force: bool,
|
||||
config_options: Dict[str, str],
|
||||
config_options: dict[str, str],
|
||||
template: Optional[Path],
|
||||
) -> None:
|
||||
"""Convert SCENE(s) into a given format and writes the result in DEST."""
|
||||
|
@ -39,7 +39,7 @@ def list_scenes(folder: Path) -> None:
|
||||
click.secho(f"{i}: {scene}", fg="green")
|
||||
|
||||
|
||||
def _list_scenes(folder: Path) -> List[str]:
|
||||
def _list_scenes(folder: Path) -> list[str]:
|
||||
"""List available scenes in given directory."""
|
||||
scenes = []
|
||||
|
||||
@ -59,7 +59,7 @@ def _list_scenes(folder: Path) -> List[str]:
|
||||
return scenes
|
||||
|
||||
|
||||
def prompt_for_scenes(folder: Path) -> List[str]:
|
||||
def prompt_for_scenes(folder: Path) -> list[str]:
|
||||
"""Prompt the user to select scenes within a given folder."""
|
||||
scene_choices = dict(enumerate(_list_scenes(folder), start=1))
|
||||
|
||||
@ -71,7 +71,7 @@ def prompt_for_scenes(folder: Path) -> List[str]:
|
||||
click.echo("Choose number corresponding to desired scene/arguments.")
|
||||
click.echo("(Use comma separated list for multiple entries)")
|
||||
|
||||
def value_proc(value: Optional[str]) -> List[str]:
|
||||
def value_proc(value: Optional[str]) -> list[str]:
|
||||
indices = list(map(int, (value or "").strip().replace(" ", "").split(",")))
|
||||
|
||||
if not all(0 < i <= len(scene_choices) for i in indices):
|
||||
@ -93,8 +93,8 @@ def prompt_for_scenes(folder: Path) -> List[str]:
|
||||
|
||||
|
||||
def get_scenes_presentation_config(
|
||||
scenes: List[str], folder: Path
|
||||
) -> List[PresentationConfig]:
|
||||
scenes: list[str], folder: Path
|
||||
) -> list[PresentationConfig]:
|
||||
"""Return a list of presentation configurations based on the user input."""
|
||||
if len(scenes) == 0:
|
||||
scenes = prompt_for_scenes(folder)
|
||||
@ -116,7 +116,7 @@ def get_scenes_presentation_config(
|
||||
|
||||
def start_at_callback(
|
||||
ctx: Context, param: Parameter, values: str
|
||||
) -> Tuple[Optional[int], ...]:
|
||||
) -> tuple[Optional[int], ...]:
|
||||
if values == "(None, None)":
|
||||
return (None, None)
|
||||
|
||||
@ -253,7 +253,7 @@ def start_at_callback(
|
||||
@click.help_option("-h", "--help")
|
||||
@verbosity_option
|
||||
def present(
|
||||
scenes: List[str],
|
||||
scenes: list[str],
|
||||
config_path: Path,
|
||||
folder: Path,
|
||||
start_paused: bool,
|
||||
@ -262,7 +262,7 @@ def present(
|
||||
exit_after_last_slide: bool,
|
||||
hide_mouse: bool,
|
||||
aspect_ratio: str,
|
||||
start_at: Tuple[Optional[int], Optional[int], Optional[int]],
|
||||
start_at: tuple[Optional[int], Optional[int], Optional[int]],
|
||||
start_at_scene_number: int,
|
||||
start_at_slide_number: int,
|
||||
screen_number: Optional[int],
|
||||
|
@ -1,6 +1,6 @@
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
|
||||
from qtpy.QtCore import Qt, QTimer, QUrl, Signal, Slot
|
||||
from qtpy.QtGui import QCloseEvent, QIcon, QKeyEvent, QScreen
|
||||
@ -169,7 +169,7 @@ class Player(QMainWindow): # type: ignore[misc]
|
||||
def __init__(
|
||||
self,
|
||||
config: Config,
|
||||
presentation_configs: List[PresentationConfig],
|
||||
presentation_configs: list[PresentationConfig],
|
||||
*,
|
||||
start_paused: bool = False,
|
||||
full_screen: bool = False,
|
||||
|
@ -12,7 +12,6 @@ This is especially useful for two reasons:
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Tuple
|
||||
|
||||
import click
|
||||
|
||||
@ -39,7 +38,7 @@ import click
|
||||
help="If set, use ManimGL renderer.",
|
||||
)
|
||||
@click.argument("args", metavar="[RENDERER_ARGS]...", nargs=-1, type=click.UNPROCESSED)
|
||||
def render(ce: bool, gl: bool, args: Tuple[str, ...]) -> None:
|
||||
def render(ce: bool, gl: bool, args: tuple[str, ...]) -> None:
|
||||
"""
|
||||
Render SCENE(s) from the input FILE, using the specified renderer.
|
||||
|
||||
|
@ -11,7 +11,8 @@ that directly calls ``self.play(Animation(...))``, see
|
||||
|
||||
__all__ = ["Wipe", "Zoom"]
|
||||
|
||||
from typing import Any, Mapping, Optional, Sequence
|
||||
from collections.abc import Mapping, Sequence
|
||||
from typing import Any, Optional
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
@ -4,13 +4,11 @@ __all__ = ["BaseSlide"]
|
||||
|
||||
import platform
|
||||
from abc import abstractmethod
|
||||
from collections.abc import MutableMapping, Sequence, ValuesView
|
||||
from pathlib import Path
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
MutableMapping,
|
||||
Sequence,
|
||||
ValuesView,
|
||||
)
|
||||
|
||||
import numpy as np
|
||||
|
@ -1,5 +1,5 @@
|
||||
from pathlib import Path
|
||||
from typing import Any, List, Optional, Tuple
|
||||
from typing import Any, Optional
|
||||
|
||||
from manim import Scene, ThreeDScene, config
|
||||
|
||||
@ -30,11 +30,11 @@ class Slide(BaseSlide, Scene): # type: ignore[misc]
|
||||
return color.to_hex() # type: ignore
|
||||
|
||||
@property
|
||||
def _resolution(self) -> Tuple[int, int]:
|
||||
def _resolution(self) -> tuple[int, int]:
|
||||
return config["pixel_width"], config["pixel_height"]
|
||||
|
||||
@property
|
||||
def _partial_movie_files(self) -> List[Path]:
|
||||
def _partial_movie_files(self) -> list[Path]:
|
||||
# When rendering with -na,b (manim only)
|
||||
# the animations not in [a,b] will be skipped,
|
||||
# but animation before a will have a None source file.
|
||||
|
@ -1,5 +1,5 @@
|
||||
from pathlib import Path
|
||||
from typing import Any, ClassVar, Dict, List, Optional, Tuple
|
||||
from typing import Any, ClassVar, Optional
|
||||
|
||||
from manimlib import Scene, ThreeDCamera
|
||||
from manimlib.utils.file_ops import get_sorted_integer_files
|
||||
@ -31,11 +31,11 @@ class Slide(BaseSlide, Scene): # type: ignore[misc]
|
||||
return self.camera_config["background_color"].hex # type: ignore
|
||||
|
||||
@property
|
||||
def _resolution(self) -> Tuple[int, int]:
|
||||
def _resolution(self) -> tuple[int, int]:
|
||||
return self.camera_config["pixel_width"], self.camera_config["pixel_height"]
|
||||
|
||||
@property
|
||||
def _partial_movie_files(self) -> List[Path]:
|
||||
def _partial_movie_files(self) -> list[Path]:
|
||||
kwargs = {
|
||||
"remove_non_integer_files": True,
|
||||
"extension": self.file_writer.movie_file_extension,
|
||||
@ -66,7 +66,7 @@ class Slide(BaseSlide, Scene): # type: ignore[misc]
|
||||
|
||||
|
||||
class ThreeDSlide(Slide):
|
||||
CONFIG: ClassVar[Dict[str, Any]] = {
|
||||
CONFIG: ClassVar[dict[str, Any]] = {
|
||||
"camera_class": ThreeDCamera,
|
||||
}
|
||||
pass
|
||||
|
@ -1,18 +1,18 @@
|
||||
import hashlib
|
||||
import os
|
||||
import tempfile
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
from typing import Iterator, List
|
||||
|
||||
import av
|
||||
|
||||
from .logger import logger
|
||||
|
||||
|
||||
def concatenate_video_files(files: List[Path], dest: Path) -> None:
|
||||
def concatenate_video_files(files: list[Path], dest: Path) -> None:
|
||||
"""Concatenate multiple video files into one."""
|
||||
|
||||
def _filter(files: List[Path]) -> Iterator[Path]:
|
||||
def _filter(files: list[Path]) -> Iterator[Path]:
|
||||
"""Patch possibly empty video files."""
|
||||
for file in files:
|
||||
with av.open(str(file)) as container:
|
||||
@ -30,9 +30,10 @@ def concatenate_video_files(files: List[Path], dest: Path) -> None:
|
||||
f.writelines(f"file '{file}'\n" for file in _filter(files))
|
||||
tmp_file = f.name
|
||||
|
||||
with av.open(
|
||||
tmp_file, format="concat", options={"safe": "0"}
|
||||
) as input_container, av.open(str(dest), mode="w") as output_container:
|
||||
with (
|
||||
av.open(tmp_file, format="concat", options={"safe": "0"}) as input_container,
|
||||
av.open(str(dest), mode="w") as output_container,
|
||||
):
|
||||
input_video_stream = input_container.streams.video[0]
|
||||
output_video_stream = output_container.add_stream(
|
||||
template=input_video_stream,
|
||||
@ -61,7 +62,7 @@ def concatenate_video_files(files: List[Path], dest: Path) -> None:
|
||||
os.unlink(tmp_file) # https://stackoverflow.com/a/54768241
|
||||
|
||||
|
||||
def merge_basenames(files: List[Path]) -> Path:
|
||||
def merge_basenames(files: list[Path]) -> Path:
|
||||
"""Merge multiple filenames by concatenating basenames."""
|
||||
if len(files) == 0:
|
||||
raise ValueError("Cannot merge an empty list of files!")
|
||||
@ -90,9 +91,10 @@ def link_nodes(*nodes: av.filter.context.FilterContext) -> None:
|
||||
|
||||
def reverse_video_file(src: Path, dest: Path) -> None:
|
||||
"""Reverses a video file, writing the result to `dest`."""
|
||||
with av.open(str(src)) as input_container, av.open(
|
||||
str(dest), mode="w"
|
||||
) as output_container:
|
||||
with (
|
||||
av.open(str(src)) as input_container,
|
||||
av.open(str(dest), mode="w") as output_container,
|
||||
):
|
||||
input_stream = input_container.streams.video[0]
|
||||
output_stream = output_container.add_stream(
|
||||
codec_name="libx264", rate=input_stream.base_rate
|
||||
|
@ -1,6 +1,6 @@
|
||||
[build-system]
|
||||
build-backend = "pdm.backend"
|
||||
requires = ["pdm-backend", "setuptools"]
|
||||
build-backend = "hatchling.build"
|
||||
requires = ["hatchling"]
|
||||
|
||||
[project]
|
||||
authors = [{name = "Jérome Eertmans", email = "jeertmans@icloud.com"}]
|
||||
@ -39,7 +39,7 @@ keywords = ["manim", "slides", "plugin", "manimgl"]
|
||||
license = {text = "MIT"}
|
||||
name = "manim-slides"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9,<3.13"
|
||||
requires-python = ">=3.9"
|
||||
|
||||
[project.optional-dependencies]
|
||||
docs = [
|
||||
@ -55,11 +55,14 @@ docs = [
|
||||
"sphinxext-opengraph>=0.7.5",
|
||||
]
|
||||
full = [
|
||||
"manim-slides[magic,manim,manimgl,sphinx-directive]",
|
||||
"manim-slides[magic,manim,sphinx-directive]",
|
||||
]
|
||||
full-gl = [
|
||||
"manim-slides[magic,manimgl,sphinx-directive]",
|
||||
]
|
||||
magic = ["manim-slides[manim]", "ipython>=8.12.2"]
|
||||
manim = ["manim>=0.17.3"]
|
||||
manimgl = ["manimgl>=1.6.1"]
|
||||
manimgl = ["manimgl>=1.6.1;python_version<'3.12'"]
|
||||
pyqt6 = ["pyqt6>=6.6.1"]
|
||||
pyqt6-full = ["manim-slides[full,pyqt6]"]
|
||||
pyside6 = ["pyside6>=6.5.1,<6.5.3;python_version<'3.12'"]
|
||||
@ -80,7 +83,7 @@ Repository = "https://github.com/jeertmans/manim-slides"
|
||||
builtin = "clear,rare,informal,usage,names,en-GB_to_en-US"
|
||||
check-hidden = true
|
||||
ignore-words-list = "master"
|
||||
skip = "pdm.lock"
|
||||
skip = "requirements.lock,requirements-dev.lock"
|
||||
|
||||
[tool.coverage.report]
|
||||
exclude_lines = [
|
||||
@ -91,35 +94,15 @@ exclude_lines = [
|
||||
]
|
||||
precision = 2
|
||||
|
||||
[tool.hatch.version]
|
||||
path = "manim_slides/__version__.py"
|
||||
|
||||
[tool.mypy]
|
||||
disallow_untyped_decorators = false
|
||||
install_types = true
|
||||
python_version = "3.8"
|
||||
python_version = "3.9"
|
||||
strict = true
|
||||
|
||||
[tool.pdm.dev-dependencies]
|
||||
dev = [
|
||||
"bump2version>=1.0.1",
|
||||
"pre-commit>=3.5.0",
|
||||
]
|
||||
github-action = ["setuptools"]
|
||||
test = [
|
||||
"manim-slides[manim,manimgl,pyqt6]",
|
||||
"pytest>=7.4.0",
|
||||
"pytest-cov>=4.1.0",
|
||||
"pytest-env>=0.8.2",
|
||||
"pytest-qt>=4.2.0",
|
||||
"pytest-xdist>=3.3.1",
|
||||
]
|
||||
|
||||
[tool.pdm.resolution.overrides]
|
||||
manimpango = "<1.0.0,>=0.5.0" # This conflicts with ManimGL, hopefully not an issue
|
||||
skia-pathops = "0.8.0.post1" # From manim 0.18.0 (Python 3.12 support)
|
||||
|
||||
[tool.pdm.version]
|
||||
path = "manim_slides/__version__.py"
|
||||
source = "file"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
env = [
|
||||
"QT_QPA_PLATFORM=offscreen",
|
||||
@ -133,7 +116,7 @@ filterwarnings = [
|
||||
extend-exclude = ["manim_slides/resources.py"]
|
||||
extend-include = ["*.ipynb"]
|
||||
line-length = 88
|
||||
target-version = "py38"
|
||||
target-version = "py39"
|
||||
|
||||
[tool.ruff.lint]
|
||||
extend-ignore = [
|
||||
@ -152,3 +135,16 @@ extend-ignore = [
|
||||
]
|
||||
extend-select = ["B", "C90", "D", "I", "N", "RUF", "UP", "T"]
|
||||
isort = {known-first-party = ["manim_slides", "tests"]}
|
||||
|
||||
[tool.rye]
|
||||
dev-dependencies = [
|
||||
"bump2version>=1.0.1",
|
||||
"manim-slides[manim,manimgl,pyqt6]",
|
||||
"pre-commit>=3.5.0",
|
||||
"pytest>=7.4.0",
|
||||
"pytest-cov>=4.1.0",
|
||||
"pytest-env>=0.8.2",
|
||||
"pytest-qt>=4.2.0",
|
||||
"pytest-xdist>=3.3.1",
|
||||
]
|
||||
managed = true
|
||||
|
419
requirements-dev.lock
Normal file
419
requirements-dev.lock
Normal file
@ -0,0 +1,419 @@
|
||||
# generated by rye
|
||||
# use `rye lock` or `rye sync` to update this lockfile
|
||||
#
|
||||
# last locked with the following flags:
|
||||
# pre: false
|
||||
# features: []
|
||||
# all-features: true
|
||||
# with-sources: false
|
||||
|
||||
-e file:.
|
||||
alabaster==0.7.16
|
||||
# via sphinx
|
||||
annotated-types==0.6.0
|
||||
# via pydantic
|
||||
asttokens==2.4.1
|
||||
# via stack-data
|
||||
attrs==23.2.0
|
||||
# via jsonschema
|
||||
# via referencing
|
||||
av==12.0.0
|
||||
# via manim-slides
|
||||
babel==2.14.0
|
||||
# via sphinx
|
||||
beautifulsoup4==4.12.3
|
||||
# via furo
|
||||
# via nbconvert
|
||||
bleach==6.1.0
|
||||
# via nbconvert
|
||||
bump2version==1.0.1
|
||||
certifi==2024.2.2
|
||||
# via requests
|
||||
cfgv==3.4.0
|
||||
# via pre-commit
|
||||
charset-normalizer==3.3.2
|
||||
# via requests
|
||||
click==8.1.7
|
||||
# via click-default-group
|
||||
# via cloup
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via sphinx-click
|
||||
click-default-group==1.2.4
|
||||
# via manim
|
||||
# via manim-slides
|
||||
cloup==0.13.1
|
||||
# via manim
|
||||
colour==0.1.5
|
||||
# via manim
|
||||
# via manimgl
|
||||
comm==0.2.2
|
||||
# via ipykernel
|
||||
contourpy==1.2.1
|
||||
# via matplotlib
|
||||
coverage==7.4.4
|
||||
# via pytest-cov
|
||||
cycler==0.12.1
|
||||
# via matplotlib
|
||||
debugpy==1.8.1
|
||||
# via ipykernel
|
||||
decorator==5.1.1
|
||||
# via ipython
|
||||
# via manim
|
||||
defusedxml==0.7.1
|
||||
# via nbconvert
|
||||
distlib==0.3.8
|
||||
# via virtualenv
|
||||
docutils==0.20.1
|
||||
# via manim-slides
|
||||
# via myst-parser
|
||||
# via nbsphinx
|
||||
# via sphinx
|
||||
# via sphinx-click
|
||||
execnet==2.1.1
|
||||
# via pytest-xdist
|
||||
executing==2.0.1
|
||||
# via stack-data
|
||||
fastjsonschema==2.19.1
|
||||
# via nbformat
|
||||
filelock==3.13.4
|
||||
# via virtualenv
|
||||
fonttools==4.51.0
|
||||
# via matplotlib
|
||||
furo==2024.1.29
|
||||
# via manim-slides
|
||||
glcontext==2.5.0
|
||||
# via moderngl
|
||||
identify==2.5.35
|
||||
# via pre-commit
|
||||
idna==3.7
|
||||
# via requests
|
||||
imagesize==1.4.1
|
||||
# via sphinx
|
||||
iniconfig==2.0.0
|
||||
# via pytest
|
||||
ipykernel==6.29.4
|
||||
# via manim-slides
|
||||
ipython==8.18.1
|
||||
# via ipykernel
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
isosurfaces==0.1.0
|
||||
# via manim
|
||||
# via manimgl
|
||||
jedi==0.19.1
|
||||
# via ipython
|
||||
jinja2==3.1.3
|
||||
# via manim-slides
|
||||
# via myst-parser
|
||||
# via nbconvert
|
||||
# via nbsphinx
|
||||
# via sphinx
|
||||
jsonschema==4.21.1
|
||||
# via nbformat
|
||||
jsonschema-specifications==2023.12.1
|
||||
# via jsonschema
|
||||
jupyter-client==8.6.1
|
||||
# via ipykernel
|
||||
# via nbclient
|
||||
jupyter-core==5.7.2
|
||||
# via ipykernel
|
||||
# via jupyter-client
|
||||
# via nbclient
|
||||
# via nbconvert
|
||||
# via nbformat
|
||||
jupyterlab-pygments==0.3.0
|
||||
# via nbconvert
|
||||
kiwisolver==1.4.5
|
||||
# via matplotlib
|
||||
lxml==5.2.1
|
||||
# via manim-slides
|
||||
# via python-pptx
|
||||
manim==0.17.3
|
||||
# via manim-slides
|
||||
manimgl==1.6.1
|
||||
# via manim-slides
|
||||
manimpango==0.4.4
|
||||
# via manim
|
||||
# via manimgl
|
||||
mapbox-earcut==1.0.1
|
||||
# via manim
|
||||
# via manimgl
|
||||
markdown-it-py==3.0.0
|
||||
# via mdit-py-plugins
|
||||
# via myst-parser
|
||||
# via rich
|
||||
markupsafe==2.1.5
|
||||
# via jinja2
|
||||
# via nbconvert
|
||||
matplotlib==3.8.4
|
||||
# via manimgl
|
||||
matplotlib-inline==0.1.7
|
||||
# via ipykernel
|
||||
# via ipython
|
||||
mdit-py-plugins==0.4.0
|
||||
# via myst-parser
|
||||
mdurl==0.1.2
|
||||
# via markdown-it-py
|
||||
mistune==3.0.2
|
||||
# via nbconvert
|
||||
moderngl==5.10.0
|
||||
# via manim
|
||||
# via manimgl
|
||||
# via moderngl-window
|
||||
moderngl-window==2.4.4
|
||||
# via manim
|
||||
# via manimgl
|
||||
mpmath==1.3.0
|
||||
# via sympy
|
||||
multipledispatch==1.0.0
|
||||
# via pyrr
|
||||
myst-parser==2.0.0
|
||||
# via manim-slides
|
||||
nbclient==0.10.0
|
||||
# via nbconvert
|
||||
nbconvert==7.16.3
|
||||
# via nbsphinx
|
||||
nbformat==5.10.4
|
||||
# via nbclient
|
||||
# via nbconvert
|
||||
# via nbsphinx
|
||||
nbsphinx==0.9.3
|
||||
# via manim-slides
|
||||
nest-asyncio==1.6.0
|
||||
# via ipykernel
|
||||
networkx==2.8.8
|
||||
# via manim
|
||||
nodeenv==1.8.0
|
||||
# via pre-commit
|
||||
numpy==1.26.4
|
||||
# via contourpy
|
||||
# via isosurfaces
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
# via mapbox-earcut
|
||||
# via matplotlib
|
||||
# via moderngl-window
|
||||
# via pyrr
|
||||
# via scipy
|
||||
packaging==24.0
|
||||
# via ipykernel
|
||||
# via matplotlib
|
||||
# via nbconvert
|
||||
# via pytest
|
||||
# via qtpy
|
||||
# via sphinx
|
||||
pandoc==2.3
|
||||
# via manim-slides
|
||||
pandocfilters==1.5.1
|
||||
# via nbconvert
|
||||
parso==0.8.4
|
||||
# via jedi
|
||||
pexpect==4.9.0
|
||||
# via ipython
|
||||
pillow==9.5.0
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
# via matplotlib
|
||||
# via moderngl-window
|
||||
# via python-pptx
|
||||
platformdirs==4.2.0
|
||||
# via jupyter-core
|
||||
# via virtualenv
|
||||
pluggy==1.4.0
|
||||
# via pytest
|
||||
# via pytest-qt
|
||||
plumbum==1.8.2
|
||||
# via pandoc
|
||||
ply==3.11
|
||||
# via pandoc
|
||||
pre-commit==3.7.0
|
||||
prompt-toolkit==3.0.43
|
||||
# via ipython
|
||||
psutil==5.9.8
|
||||
# via ipykernel
|
||||
ptyprocess==0.7.0
|
||||
# via pexpect
|
||||
pure-eval==0.2.2
|
||||
# via stack-data
|
||||
pycairo==1.26.0
|
||||
# via manim
|
||||
pydantic==2.7.0
|
||||
# via manim-slides
|
||||
# via pydantic-extra-types
|
||||
pydantic-core==2.18.1
|
||||
# via pydantic
|
||||
pydantic-extra-types==2.6.0
|
||||
# via manim-slides
|
||||
pydub==0.25.1
|
||||
# via manim
|
||||
# via manimgl
|
||||
pyglet==2.0.15
|
||||
# via moderngl-window
|
||||
pygments==2.17.2
|
||||
# via furo
|
||||
# via ipython
|
||||
# via manim
|
||||
# via manimgl
|
||||
# via nbconvert
|
||||
# via rich
|
||||
# via sphinx
|
||||
pyopengl==3.1.7
|
||||
# via manimgl
|
||||
pyparsing==3.1.2
|
||||
# via matplotlib
|
||||
pyqt6==6.6.1
|
||||
# via manim-slides
|
||||
pyqt6-qt6==6.6.3
|
||||
# via pyqt6
|
||||
pyqt6-sip==13.6.0
|
||||
# via pyqt6
|
||||
pyrr==0.10.3
|
||||
# via moderngl-window
|
||||
pyside6==6.5.2
|
||||
# via manim-slides
|
||||
pyside6-addons==6.5.2
|
||||
# via pyside6
|
||||
pyside6-essentials==6.5.2
|
||||
# via pyside6
|
||||
# via pyside6-addons
|
||||
pytest==8.1.1
|
||||
# via pytest-cov
|
||||
# via pytest-env
|
||||
# via pytest-qt
|
||||
# via pytest-xdist
|
||||
pytest-cov==5.0.0
|
||||
pytest-env==1.1.3
|
||||
pytest-qt==4.4.0
|
||||
pytest-xdist==3.5.0
|
||||
python-dateutil==2.9.0.post0
|
||||
# via jupyter-client
|
||||
# via matplotlib
|
||||
python-pptx==0.6.23
|
||||
# via manim-slides
|
||||
pyyaml==6.0.1
|
||||
# via manimgl
|
||||
# via myst-parser
|
||||
# via pre-commit
|
||||
pyzmq==26.0.0
|
||||
# via ipykernel
|
||||
# via jupyter-client
|
||||
qtpy==2.4.1
|
||||
# via manim-slides
|
||||
referencing==0.34.0
|
||||
# via jsonschema
|
||||
# via jsonschema-specifications
|
||||
requests==2.31.0
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via sphinx
|
||||
rich==13.7.1
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
rpds-py==0.18.0
|
||||
# via jsonschema
|
||||
# via referencing
|
||||
rtoml==0.10.0
|
||||
# via manim-slides
|
||||
scipy==1.13.0
|
||||
# via manim
|
||||
# via manimgl
|
||||
screeninfo==0.8.1
|
||||
# via manim
|
||||
# via manimgl
|
||||
setuptools==69.5.1
|
||||
# via nodeenv
|
||||
shiboken6==6.5.2
|
||||
# via pyside6
|
||||
# via pyside6-addons
|
||||
# via pyside6-essentials
|
||||
six==1.16.0
|
||||
# via asttokens
|
||||
# via bleach
|
||||
# via python-dateutil
|
||||
skia-pathops==0.7.4
|
||||
# via manim
|
||||
# via manimgl
|
||||
snowballstemmer==2.2.0
|
||||
# via sphinx
|
||||
soupsieve==2.5
|
||||
# via beautifulsoup4
|
||||
sphinx==7.3.6
|
||||
# via furo
|
||||
# via manim-slides
|
||||
# via myst-parser
|
||||
# via nbsphinx
|
||||
# via sphinx-basic-ng
|
||||
# via sphinx-click
|
||||
# via sphinx-copybutton
|
||||
# via sphinxext-opengraph
|
||||
sphinx-basic-ng==1.0.0b2
|
||||
# via furo
|
||||
sphinx-click==5.1.0
|
||||
# via manim-slides
|
||||
sphinx-copybutton==0.5.2
|
||||
# via manim-slides
|
||||
sphinxcontrib-applehelp==1.0.8
|
||||
# via sphinx
|
||||
sphinxcontrib-devhelp==1.0.6
|
||||
# via sphinx
|
||||
sphinxcontrib-htmlhelp==2.0.5
|
||||
# via sphinx
|
||||
sphinxcontrib-jsmath==1.0.1
|
||||
# via sphinx
|
||||
sphinxcontrib-qthelp==1.0.7
|
||||
# via sphinx
|
||||
sphinxcontrib-serializinghtml==1.1.10
|
||||
# via sphinx
|
||||
sphinxext-opengraph==0.9.1
|
||||
# via manim-slides
|
||||
srt==3.5.3
|
||||
# via manim
|
||||
stack-data==0.6.3
|
||||
# via ipython
|
||||
svgelements==1.9.6
|
||||
# via manim
|
||||
# via manimgl
|
||||
sympy==1.12
|
||||
# via manimgl
|
||||
tinycss2==1.2.1
|
||||
# via nbconvert
|
||||
tornado==6.4
|
||||
# via ipykernel
|
||||
# via jupyter-client
|
||||
tqdm==4.66.2
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
traitlets==5.14.2
|
||||
# via comm
|
||||
# via ipykernel
|
||||
# via ipython
|
||||
# via jupyter-client
|
||||
# via jupyter-core
|
||||
# via matplotlib-inline
|
||||
# via nbclient
|
||||
# via nbconvert
|
||||
# via nbformat
|
||||
# via nbsphinx
|
||||
typing-extensions==4.11.0
|
||||
# via pydantic
|
||||
# via pydantic-core
|
||||
urllib3==2.2.1
|
||||
# via requests
|
||||
validators==0.28.0
|
||||
# via manimgl
|
||||
virtualenv==20.25.3
|
||||
# via pre-commit
|
||||
watchdog==2.3.1
|
||||
# via manim
|
||||
wcwidth==0.2.13
|
||||
# via prompt-toolkit
|
||||
webencodings==0.5.1
|
||||
# via bleach
|
||||
# via tinycss2
|
||||
xlsxwriter==3.2.0
|
||||
# via python-pptx
|
382
requirements.lock
Normal file
382
requirements.lock
Normal file
@ -0,0 +1,382 @@
|
||||
# generated by rye
|
||||
# use `rye lock` or `rye sync` to update this lockfile
|
||||
#
|
||||
# last locked with the following flags:
|
||||
# pre: false
|
||||
# features: []
|
||||
# all-features: true
|
||||
# with-sources: false
|
||||
|
||||
-e file:.
|
||||
alabaster==0.7.16
|
||||
# via sphinx
|
||||
annotated-types==0.6.0
|
||||
# via pydantic
|
||||
asttokens==2.4.1
|
||||
# via stack-data
|
||||
attrs==23.2.0
|
||||
# via jsonschema
|
||||
# via referencing
|
||||
av==12.0.0
|
||||
# via manim-slides
|
||||
babel==2.14.0
|
||||
# via sphinx
|
||||
beautifulsoup4==4.12.3
|
||||
# via furo
|
||||
# via nbconvert
|
||||
bleach==6.1.0
|
||||
# via nbconvert
|
||||
certifi==2024.2.2
|
||||
# via requests
|
||||
charset-normalizer==3.3.2
|
||||
# via requests
|
||||
click==8.1.7
|
||||
# via click-default-group
|
||||
# via cloup
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via sphinx-click
|
||||
click-default-group==1.2.4
|
||||
# via manim
|
||||
# via manim-slides
|
||||
cloup==0.13.1
|
||||
# via manim
|
||||
colour==0.1.5
|
||||
# via manim
|
||||
# via manimgl
|
||||
comm==0.2.2
|
||||
# via ipykernel
|
||||
contourpy==1.2.1
|
||||
# via matplotlib
|
||||
cycler==0.12.1
|
||||
# via matplotlib
|
||||
debugpy==1.8.1
|
||||
# via ipykernel
|
||||
decorator==5.1.1
|
||||
# via ipython
|
||||
# via manim
|
||||
defusedxml==0.7.1
|
||||
# via nbconvert
|
||||
docutils==0.20.1
|
||||
# via manim-slides
|
||||
# via myst-parser
|
||||
# via nbsphinx
|
||||
# via sphinx
|
||||
# via sphinx-click
|
||||
executing==2.0.1
|
||||
# via stack-data
|
||||
fastjsonschema==2.19.1
|
||||
# via nbformat
|
||||
fonttools==4.51.0
|
||||
# via matplotlib
|
||||
furo==2024.1.29
|
||||
# via manim-slides
|
||||
glcontext==2.5.0
|
||||
# via moderngl
|
||||
idna==3.7
|
||||
# via requests
|
||||
imagesize==1.4.1
|
||||
# via sphinx
|
||||
ipykernel==6.29.4
|
||||
# via manim-slides
|
||||
ipython==8.18.1
|
||||
# via ipykernel
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
isosurfaces==0.1.0
|
||||
# via manim
|
||||
# via manimgl
|
||||
jedi==0.19.1
|
||||
# via ipython
|
||||
jinja2==3.1.3
|
||||
# via manim-slides
|
||||
# via myst-parser
|
||||
# via nbconvert
|
||||
# via nbsphinx
|
||||
# via sphinx
|
||||
jsonschema==4.21.1
|
||||
# via nbformat
|
||||
jsonschema-specifications==2023.12.1
|
||||
# via jsonschema
|
||||
jupyter-client==8.6.1
|
||||
# via ipykernel
|
||||
# via nbclient
|
||||
jupyter-core==5.7.2
|
||||
# via ipykernel
|
||||
# via jupyter-client
|
||||
# via nbclient
|
||||
# via nbconvert
|
||||
# via nbformat
|
||||
jupyterlab-pygments==0.3.0
|
||||
# via nbconvert
|
||||
kiwisolver==1.4.5
|
||||
# via matplotlib
|
||||
lxml==5.2.1
|
||||
# via manim-slides
|
||||
# via python-pptx
|
||||
manim==0.17.3
|
||||
# via manim-slides
|
||||
manimgl==1.6.1
|
||||
# via manim-slides
|
||||
manimpango==0.4.4
|
||||
# via manim
|
||||
# via manimgl
|
||||
mapbox-earcut==1.0.1
|
||||
# via manim
|
||||
# via manimgl
|
||||
markdown-it-py==3.0.0
|
||||
# via mdit-py-plugins
|
||||
# via myst-parser
|
||||
# via rich
|
||||
markupsafe==2.1.5
|
||||
# via jinja2
|
||||
# via nbconvert
|
||||
matplotlib==3.8.4
|
||||
# via manimgl
|
||||
matplotlib-inline==0.1.7
|
||||
# via ipykernel
|
||||
# via ipython
|
||||
mdit-py-plugins==0.4.0
|
||||
# via myst-parser
|
||||
mdurl==0.1.2
|
||||
# via markdown-it-py
|
||||
mistune==3.0.2
|
||||
# via nbconvert
|
||||
moderngl==5.10.0
|
||||
# via manim
|
||||
# via manimgl
|
||||
# via moderngl-window
|
||||
moderngl-window==2.4.4
|
||||
# via manim
|
||||
# via manimgl
|
||||
mpmath==1.3.0
|
||||
# via sympy
|
||||
multipledispatch==1.0.0
|
||||
# via pyrr
|
||||
myst-parser==2.0.0
|
||||
# via manim-slides
|
||||
nbclient==0.10.0
|
||||
# via nbconvert
|
||||
nbconvert==7.16.3
|
||||
# via nbsphinx
|
||||
nbformat==5.10.4
|
||||
# via nbclient
|
||||
# via nbconvert
|
||||
# via nbsphinx
|
||||
nbsphinx==0.9.3
|
||||
# via manim-slides
|
||||
nest-asyncio==1.6.0
|
||||
# via ipykernel
|
||||
networkx==2.8.8
|
||||
# via manim
|
||||
numpy==1.26.4
|
||||
# via contourpy
|
||||
# via isosurfaces
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
# via mapbox-earcut
|
||||
# via matplotlib
|
||||
# via moderngl-window
|
||||
# via pyrr
|
||||
# via scipy
|
||||
packaging==24.0
|
||||
# via ipykernel
|
||||
# via matplotlib
|
||||
# via nbconvert
|
||||
# via qtpy
|
||||
# via sphinx
|
||||
pandoc==2.3
|
||||
# via manim-slides
|
||||
pandocfilters==1.5.1
|
||||
# via nbconvert
|
||||
parso==0.8.4
|
||||
# via jedi
|
||||
pexpect==4.9.0
|
||||
# via ipython
|
||||
pillow==9.5.0
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
# via matplotlib
|
||||
# via moderngl-window
|
||||
# via python-pptx
|
||||
platformdirs==4.2.0
|
||||
# via jupyter-core
|
||||
plumbum==1.8.2
|
||||
# via pandoc
|
||||
ply==3.11
|
||||
# via pandoc
|
||||
prompt-toolkit==3.0.43
|
||||
# via ipython
|
||||
psutil==5.9.8
|
||||
# via ipykernel
|
||||
ptyprocess==0.7.0
|
||||
# via pexpect
|
||||
pure-eval==0.2.2
|
||||
# via stack-data
|
||||
pycairo==1.26.0
|
||||
# via manim
|
||||
pydantic==2.7.0
|
||||
# via manim-slides
|
||||
# via pydantic-extra-types
|
||||
pydantic-core==2.18.1
|
||||
# via pydantic
|
||||
pydantic-extra-types==2.6.0
|
||||
# via manim-slides
|
||||
pydub==0.25.1
|
||||
# via manim
|
||||
# via manimgl
|
||||
pyglet==2.0.15
|
||||
# via moderngl-window
|
||||
pygments==2.17.2
|
||||
# via furo
|
||||
# via ipython
|
||||
# via manim
|
||||
# via manimgl
|
||||
# via nbconvert
|
||||
# via rich
|
||||
# via sphinx
|
||||
pyopengl==3.1.7
|
||||
# via manimgl
|
||||
pyparsing==3.1.2
|
||||
# via matplotlib
|
||||
pyqt6==6.6.1
|
||||
# via manim-slides
|
||||
pyqt6-qt6==6.6.3
|
||||
# via pyqt6
|
||||
pyqt6-sip==13.6.0
|
||||
# via pyqt6
|
||||
pyrr==0.10.3
|
||||
# via moderngl-window
|
||||
pyside6==6.5.2
|
||||
# via manim-slides
|
||||
pyside6-addons==6.5.2
|
||||
# via pyside6
|
||||
pyside6-essentials==6.5.2
|
||||
# via pyside6
|
||||
# via pyside6-addons
|
||||
python-dateutil==2.9.0.post0
|
||||
# via jupyter-client
|
||||
# via matplotlib
|
||||
python-pptx==0.6.23
|
||||
# via manim-slides
|
||||
pyyaml==6.0.1
|
||||
# via manimgl
|
||||
# via myst-parser
|
||||
pyzmq==26.0.0
|
||||
# via ipykernel
|
||||
# via jupyter-client
|
||||
qtpy==2.4.1
|
||||
# via manim-slides
|
||||
referencing==0.34.0
|
||||
# via jsonschema
|
||||
# via jsonschema-specifications
|
||||
requests==2.31.0
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via sphinx
|
||||
rich==13.7.1
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
rpds-py==0.18.0
|
||||
# via jsonschema
|
||||
# via referencing
|
||||
rtoml==0.10.0
|
||||
# via manim-slides
|
||||
scipy==1.13.0
|
||||
# via manim
|
||||
# via manimgl
|
||||
screeninfo==0.8.1
|
||||
# via manim
|
||||
# via manimgl
|
||||
shiboken6==6.5.2
|
||||
# via pyside6
|
||||
# via pyside6-addons
|
||||
# via pyside6-essentials
|
||||
six==1.16.0
|
||||
# via asttokens
|
||||
# via bleach
|
||||
# via python-dateutil
|
||||
skia-pathops==0.7.4
|
||||
# via manim
|
||||
# via manimgl
|
||||
snowballstemmer==2.2.0
|
||||
# via sphinx
|
||||
soupsieve==2.5
|
||||
# via beautifulsoup4
|
||||
sphinx==7.3.6
|
||||
# via furo
|
||||
# via manim-slides
|
||||
# via myst-parser
|
||||
# via nbsphinx
|
||||
# via sphinx-basic-ng
|
||||
# via sphinx-click
|
||||
# via sphinx-copybutton
|
||||
# via sphinxext-opengraph
|
||||
sphinx-basic-ng==1.0.0b2
|
||||
# via furo
|
||||
sphinx-click==5.1.0
|
||||
# via manim-slides
|
||||
sphinx-copybutton==0.5.2
|
||||
# via manim-slides
|
||||
sphinxcontrib-applehelp==1.0.8
|
||||
# via sphinx
|
||||
sphinxcontrib-devhelp==1.0.6
|
||||
# via sphinx
|
||||
sphinxcontrib-htmlhelp==2.0.5
|
||||
# via sphinx
|
||||
sphinxcontrib-jsmath==1.0.1
|
||||
# via sphinx
|
||||
sphinxcontrib-qthelp==1.0.7
|
||||
# via sphinx
|
||||
sphinxcontrib-serializinghtml==1.1.10
|
||||
# via sphinx
|
||||
sphinxext-opengraph==0.9.1
|
||||
# via manim-slides
|
||||
srt==3.5.3
|
||||
# via manim
|
||||
stack-data==0.6.3
|
||||
# via ipython
|
||||
svgelements==1.9.6
|
||||
# via manim
|
||||
# via manimgl
|
||||
sympy==1.12
|
||||
# via manimgl
|
||||
tinycss2==1.2.1
|
||||
# via nbconvert
|
||||
tornado==6.4
|
||||
# via ipykernel
|
||||
# via jupyter-client
|
||||
tqdm==4.66.2
|
||||
# via manim
|
||||
# via manim-slides
|
||||
# via manimgl
|
||||
traitlets==5.14.2
|
||||
# via comm
|
||||
# via ipykernel
|
||||
# via ipython
|
||||
# via jupyter-client
|
||||
# via jupyter-core
|
||||
# via matplotlib-inline
|
||||
# via nbclient
|
||||
# via nbconvert
|
||||
# via nbformat
|
||||
# via nbsphinx
|
||||
typing-extensions==4.11.0
|
||||
# via pydantic
|
||||
# via pydantic-core
|
||||
urllib3==2.2.1
|
||||
# via requests
|
||||
validators==0.28.0
|
||||
# via manimgl
|
||||
watchdog==2.3.1
|
||||
# via manim
|
||||
wcwidth==0.2.13
|
||||
# via prompt-toolkit
|
||||
webencodings==0.5.1
|
||||
# via bleach
|
||||
# via tinycss2
|
||||
xlsxwriter==3.2.0
|
||||
# via python-pptx
|
@ -1,5 +1,5 @@
|
||||
#! /bin/bash
|
||||
|
||||
pdm run manim-slides render -t -qk -s --format png --resolution 64,64 static/logo.py ManimSlidesFavicon && mv media/images/logo/*.png static/favicon.png
|
||||
rye run manim-slides render -t -qk -s --format png --resolution 64,64 static/logo.py ManimSlidesFavicon && mv media/images/logo/*.png static/favicon.png
|
||||
|
||||
ln -f -r -s static/favicon.png docs/source/_static/favicon.png
|
||||
|
@ -1,21 +1,21 @@
|
||||
#! /bin/bash
|
||||
|
||||
MANIM_SLIDES_THEME=light pdm run manim-slides render -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo.png
|
||||
MANIM_SLIDES_THEME=light rye run manim-slides render -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo.png
|
||||
|
||||
ln -f -r -s static/logo.png docs/source/_static/logo.png
|
||||
|
||||
MANIM_SLIDES_THEME=dark_docs pdm run manim-slides render -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo_dark_docs.png
|
||||
MANIM_SLIDES_THEME=dark_docs rye run manim-slides render -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo_dark_docs.png
|
||||
|
||||
ln -f -r -s static/logo_dark_docs.png docs/source/_static/logo_dark_docs.png
|
||||
|
||||
MANIM_SLIDES_THEME=dark_github pdm run manim-slides render -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo_dark_github.png
|
||||
MANIM_SLIDES_THEME=dark_github rye run manim-slides render -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo_dark_github.png
|
||||
|
||||
ln -f -r -s static/logo_dark_github.png docs/source/_static/logo_dark_github.png
|
||||
|
||||
MANIM_SLIDES_THEME=light pdm run manim-slides render -t -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo_light_transparent.png
|
||||
MANIM_SLIDES_THEME=light rye run manim-slides render -t -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo_light_transparent.png
|
||||
|
||||
ln -f -r -s static/logo_light_transparent.png docs/source/_static/logo_light_transparent.png
|
||||
|
||||
MANIM_SLIDES_THEME=dark_docs pdm run manim-slides render -t -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo_dark_transparent.png
|
||||
MANIM_SLIDES_THEME=dark_docs rye run manim-slides render -t -qk -s --format png --resolution 2560,1280 static/logo.py ManimSlidesLogo && mv media/images/logo/*.png static/logo_dark_transparent.png
|
||||
|
||||
ln -f -r -s static/logo_dark_transparent.png docs/source/_static/logo_dark_transparent.png
|
||||
|
@ -1,7 +1,7 @@
|
||||
import random
|
||||
import string
|
||||
from collections.abc import Generator, Iterator
|
||||
from pathlib import Path
|
||||
from typing import Generator, Iterator, List
|
||||
|
||||
import pytest
|
||||
|
||||
@ -65,7 +65,7 @@ def random_path(
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def paths() -> Generator[List[Path], None, None]:
|
||||
def paths() -> Generator[list[Path], None, None]:
|
||||
random.seed(1234)
|
||||
|
||||
yield [random_path() for _ in range(20)]
|
||||
|
@ -1,4 +1,4 @@
|
||||
from typing import MutableMapping
|
||||
from collections.abc import MutableMapping
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -21,6 +21,7 @@ def assert_import(
|
||||
|
||||
|
||||
def test_force_api() -> None:
|
||||
pytest.importorskip("manimlib")
|
||||
import manim # noqa: F401
|
||||
|
||||
if "manimlib" in sys.modules:
|
||||
@ -54,6 +55,7 @@ def test_invalid_api() -> None:
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:assert_import")
|
||||
def test_manim_and_manimgl_imported() -> None:
|
||||
pytest.importorskip("manimlib")
|
||||
import manim # noqa: F401
|
||||
import manimlib # noqa: F401
|
||||
|
||||
@ -78,6 +80,7 @@ def test_manim_imported() -> None:
|
||||
|
||||
|
||||
def test_manimgl_imported() -> None:
|
||||
pytest.importorskip("manimlib")
|
||||
import manimlib # noqa: F401
|
||||
|
||||
if "manim" in sys.modules:
|
||||
|
@ -1,5 +1,5 @@
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
from typing import Iterator, Tuple
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
@ -20,11 +20,11 @@ def auto_shutdown_qapp() -> Iterator[None]:
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def args(slides_folder: Path) -> Iterator[Tuple[str, ...]]:
|
||||
def args(slides_folder: Path) -> Iterator[tuple[str, ...]]:
|
||||
yield ("--folder", str(slides_folder), "--skip-all", "--playback-rate", "25")
|
||||
|
||||
|
||||
def test_present(args: Tuple[str, ...]) -> None:
|
||||
def test_present(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -34,7 +34,7 @@ def test_present(args: Tuple[str, ...]) -> None:
|
||||
assert results.stdout == ""
|
||||
|
||||
|
||||
def test_present_unexisting_slide(args: Tuple[str, ...]) -> None:
|
||||
def test_present_unexisting_slide(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -44,7 +44,7 @@ def test_present_unexisting_slide(args: Tuple[str, ...]) -> None:
|
||||
assert "UnexistingSlide.json does not exist" in results.stdout
|
||||
|
||||
|
||||
def test_present_full_screen(args: Tuple[str, ...]) -> None:
|
||||
def test_present_full_screen(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -54,7 +54,7 @@ def test_present_full_screen(args: Tuple[str, ...]) -> None:
|
||||
assert results.stdout == ""
|
||||
|
||||
|
||||
def test_present_hide_mouse(args: Tuple[str, ...]) -> None:
|
||||
def test_present_hide_mouse(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -64,7 +64,7 @@ def test_present_hide_mouse(args: Tuple[str, ...]) -> None:
|
||||
assert results.stdout == ""
|
||||
|
||||
|
||||
def test_present_ignore_aspect_ratio(args: Tuple[str, ...]) -> None:
|
||||
def test_present_ignore_aspect_ratio(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -76,7 +76,7 @@ def test_present_ignore_aspect_ratio(args: Tuple[str, ...]) -> None:
|
||||
assert results.stdout == ""
|
||||
|
||||
|
||||
def test_present_start_at(args: Tuple[str, ...]) -> None:
|
||||
def test_present_start_at(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -86,7 +86,7 @@ def test_present_start_at(args: Tuple[str, ...]) -> None:
|
||||
assert results.stdout == ""
|
||||
|
||||
|
||||
def test_present_start_at_invalid(args: Tuple[str, ...]) -> None:
|
||||
def test_present_start_at_invalid(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -96,7 +96,7 @@ def test_present_start_at_invalid(args: Tuple[str, ...]) -> None:
|
||||
assert "Could not set presentation index to 1234"
|
||||
|
||||
|
||||
def test_present_start_at_scene_number(args: Tuple[str, ...]) -> None:
|
||||
def test_present_start_at_scene_number(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -108,7 +108,7 @@ def test_present_start_at_scene_number(args: Tuple[str, ...]) -> None:
|
||||
assert results.stdout == ""
|
||||
|
||||
|
||||
def test_present_start_at_slide_number(args: Tuple[str, ...]) -> None:
|
||||
def test_present_start_at_slide_number(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -120,7 +120,7 @@ def test_present_start_at_slide_number(args: Tuple[str, ...]) -> None:
|
||||
assert results.stdout == ""
|
||||
|
||||
|
||||
def test_present_set_screen(args: Tuple[str, ...]) -> None:
|
||||
def test_present_set_screen(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
@ -131,7 +131,7 @@ def test_present_set_screen(args: Tuple[str, ...]) -> None:
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="Fails when running the whole test suite.")
|
||||
def test_present_set_invalid_screen(args: Tuple[str, ...]) -> None:
|
||||
def test_present_set_invalid_screen(args: tuple[str, ...]) -> None:
|
||||
runner = CliRunner()
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
|
@ -1,7 +1,9 @@
|
||||
import random
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import manim
|
||||
import numpy as np
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
@ -35,8 +37,9 @@ from manim_slides.slide.manim import Slide
|
||||
pytest.param(
|
||||
"--GL",
|
||||
marks=pytest.mark.skipif(
|
||||
version.parse(np.__version__) >= version.parse("1.25"),
|
||||
reason="ManimGL requires numpy<1.25, which is outdate",
|
||||
version.parse(np.__version__) >= version.parse("1.25")
|
||||
or sys.version_info >= (3, 12),
|
||||
reason="ManimGL requires numpy<1.25, which is outdated and Python < 3.12",
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -109,6 +112,10 @@ class TestSlide:
|
||||
assert len(self._canvas) == 0
|
||||
assert self._wait_time_between_slides == 0.0
|
||||
|
||||
@pytest.mark.skipif(
|
||||
version.parse(manim.__version__) < version.parse("0.18"),
|
||||
reason="Manim change how color are represented in 0.18",
|
||||
)
|
||||
@assert_constructs
|
||||
class TestBackgroundColor(Slide):
|
||||
def construct(self) -> None:
|
||||
|
@ -1,17 +1,16 @@
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from manim_slides.utils import merge_basenames
|
||||
|
||||
|
||||
def test_merge_basenames(paths: List[Path]) -> None:
|
||||
def test_merge_basenames(paths: list[Path]) -> None:
|
||||
path = merge_basenames(paths)
|
||||
assert path.suffix == paths[0].suffix
|
||||
assert path.parent == paths[0].parent
|
||||
|
||||
|
||||
def test_merge_basenames_same_with_different_parent_directories(
|
||||
paths: List[Path],
|
||||
paths: list[Path],
|
||||
) -> None:
|
||||
d1 = Path("a/b/c")
|
||||
d2 = Path("d/e/f")
|
||||
|
Reference in New Issue
Block a user