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:
Jérome Eertmans
2024-04-18 22:12:45 +02:00
committed by GitHub
parent bd04dae2bf
commit d5d1513d94
31 changed files with 965 additions and 3677 deletions

View File

@ -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

View File

@ -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
View File

@ -0,0 +1 @@
3.11.8

View File

@ -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

View File

@ -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

View File

@ -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`,

View File

@ -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:

View File

@ -18,6 +18,7 @@
"outputs": [],
"source": [
"from manim import *\n",
"\n",
"from manim_slides import *"
]
},

View File

@ -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(
(

View File

@ -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

View File

@ -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."""

View File

@ -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],

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.

View 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

View File

@ -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

3493
pdm.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -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
View 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
View 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

View File

@ -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

View File

@ -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

View File

@ -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)]

View File

@ -1,4 +1,4 @@
from typing import MutableMapping
from collections.abc import MutableMapping
import pytest

View File

@ -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:

View File

@ -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():

View File

@ -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:

View File

@ -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")