feat(cli): manim-slides checkhealth (#458)

* feat(cli): `manim-slides checkhealth`

Closes #457

* chore(fmt): auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* chore(tests): implement some basic tests

* chore(docs): document changes

---------

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-08-27 12:23:24 +02:00
committed by GitHub
parent 5b6f5eb1e4
commit c047da67b1
8 changed files with 139 additions and 24 deletions

View File

@ -73,22 +73,22 @@ body:
description: | description: |
Please copy and paste the output of `python --version`. Please copy and paste the output of `python --version`.
Make sure to activate your virtual environment first (if any). Make sure to activate your virtual environment first (if any).
This will be automatically formatted into code, so no need for backticks.
placeholder: Python 3.11.8 placeholder: Python 3.11.8
validations: validations:
required: false required: true
- type: textarea - type: textarea
id: venv id: venv
attributes: attributes:
label: Python environment label: Python environment
description: | description: |
Please copy and paste the output of `pip freeze`. Please copy and paste the output of `manim-slides checkhealth`.
Make sure to activate your virtual environment first (if any). Make sure to activate your virtual environment first (if any).
This will be automatically formatted into code, so no need for backticks. This will be automatically formatted into code, so no need for backticks.
If Manim Slides installation failed, enter 'N/A' instead.
render: shell render: shell
validations: validations:
required: false required: true
- type: dropdown - type: dropdown
id: platform id: platform

View File

@ -10,6 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
(unreleased)= (unreleased)=
## [Unreleased](https://github.com/jeertmans/manim-slides/compare/v5.1.7...HEAD) ## [Unreleased](https://github.com/jeertmans/manim-slides/compare/v5.1.7...HEAD)
(unreleased-added)=
### Added
- Added `manim-slides checkhealth` command to easily obtain important information
for debug purposes.
[#458](https://github.com/jeertmans/manim-slides/pull/458)
(unreleased-chore)= (unreleased-chore)=
### Chore ### Chore

View File

@ -5,6 +5,7 @@ import requests
from click_default_group import DefaultGroup from click_default_group import DefaultGroup
from .__version__ import __version__ from .__version__ import __version__
from .checkhealth import checkhealth
from .convert import convert from .convert import convert
from .logger import logger from .logger import logger
from .present import list_scenes, present from .present import list_scenes, present
@ -63,6 +64,7 @@ def cli(notify_outdated_version: bool) -> None:
cli.add_command(convert) cli.add_command(convert)
cli.add_command(checkhealth)
cli.add_command(init) cli.add_command(init)
cli.add_command(list_scenes) cli.add_command(list_scenes)
cli.add_command(present) cli.add_command(present)

View File

@ -0,0 +1,39 @@
import sys
import click
from .__version__ import __version__
@click.command()
def checkhealth() -> None:
"""Check Manim Slides' installation."""
click.echo(f"Manim Slides version: {__version__}")
click.echo(f"Python executable: {sys.executable}")
click.echo("Manim bindings:")
click.echo(f"Modules: {sys.modules.keys()}")
try:
from manim import __version__ as manimce_version
click.echo(f"\tmanim (version: {manimce_version})")
except ImportError:
click.secho("\tmanim not found", bold=True)
try:
from manimlib import __version__ as manimlib_version
click.echo(f"\tmanimgl (version: {manimlib_version})")
except ImportError:
click.secho("\tmanimgl not found", bold=True)
try:
from qtpy import API, QT_VERSION
click.echo(f"Qt API: {API} (version: {QT_VERSION})")
except ImportError:
click.secho(
"No Qt API found, some Manim Slides commands will not be available",
bold=True,
)

View File

@ -33,6 +33,7 @@ dependencies = [
"rtoml==0.9.0;sys_platform=='win32' and python_version<'3.13'", "rtoml==0.9.0;sys_platform=='win32' and python_version<'3.13'",
"rtoml>=0.9.0;sys_platform!='win32' or python_version>='3.13'", "rtoml>=0.9.0;sys_platform!='win32' or python_version>='3.13'",
"tqdm>=4.64.1", "tqdm>=4.64.1",
"pytest-missing-modules>=0.1.0",
] ]
description = "Tool for live presentations using manim" description = "Tool for live presentations using manim"
dynamic = ["readme", "version"] dynamic = ["readme", "version"]
@ -217,6 +218,7 @@ isort = {known-first-party = ["manim_slides", "tests"]}
dev-dependencies = [ dev-dependencies = [
"bump-my-version>=0.20.3", "bump-my-version>=0.20.3",
"pre-commit>=3.5.0", "pre-commit>=3.5.0",
"setuptools>=73.0.1",
] ]
managed = true managed = true

View File

@ -7,7 +7,6 @@
# all-features: true # all-features: true
# with-sources: false # with-sources: false
# generate-hashes: false # generate-hashes: false
# universal: false
-e file:. -e file:.
alabaster==1.0.0 alabaster==1.0.0
@ -49,12 +48,6 @@ click-default-group==1.2.4
# via manim-slides # via manim-slides
cloup==3.0.5 cloup==3.0.5
# via manim # via manim
colorama==0.4.6
# via click
# via ipython
# via pytest
# via sphinx
# via tqdm
colour==0.1.5 colour==0.1.5
# via manimgl # via manimgl
comm==0.2.2 comm==0.2.2
@ -198,6 +191,7 @@ nodeenv==1.9.1
numpy==1.24.0 numpy==1.24.0
# via --override (workspace) # via --override (workspace)
# via contourpy # via contourpy
# via ipython
# via isosurfaces # via isosurfaces
# via manim # via manim
# via manim-slides # via manim-slides
@ -205,6 +199,7 @@ numpy==1.24.0
# via mapbox-earcut # via mapbox-earcut
# via matplotlib # via matplotlib
# via moderngl-window # via moderngl-window
# via networkx
# via pyrr # via pyrr
# via scipy # via scipy
packaging==24.1 packaging==24.1
@ -220,6 +215,8 @@ pandocfilters==1.5.1
# via nbconvert # via nbconvert
parso==0.8.4 parso==0.8.4
# via jedi # via jedi
pexpect==4.9.0
# via ipython
pillow==10.4.0 pillow==10.4.0
# via manim # via manim
# via manim-slides # via manim-slides
@ -243,6 +240,8 @@ prompt-toolkit==3.0.47
# via questionary # via questionary
psutil==6.0.0 psutil==6.0.0
# via ipykernel # via ipykernel
ptyprocess==0.7.0
# via pexpect
pure-eval==0.2.3 pure-eval==0.2.3
# via stack-data # via stack-data
pycairo==1.26.1 pycairo==1.26.1
@ -294,11 +293,14 @@ pytest==8.3.2
# via manim-slides # via manim-slides
# via pytest-cov # via pytest-cov
# via pytest-env # via pytest-env
# via pytest-missing-modules
# via pytest-qt # via pytest-qt
pytest-cov==5.0.0 pytest-cov==5.0.0
# via manim-slides # via manim-slides
pytest-env==1.1.3 pytest-env==1.1.3
# via manim-slides # via manim-slides
pytest-missing-modules==0.1.0
# via manim-slides
pytest-qt==4.4.0 pytest-qt==4.4.0
# via manim-slides # via manim-slides
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
@ -308,9 +310,6 @@ python-dotenv==1.0.1
# via pydantic-settings # via pydantic-settings
python-pptx==1.0.2 python-pptx==1.0.2
# via manim-slides # via manim-slides
pywin32==306
# via jupyter-core
# via plumbum
pyyaml==6.0.2 pyyaml==6.0.2
# via manimgl # via manimgl
# via myst-parser # via myst-parser
@ -347,6 +346,7 @@ scipy==1.14.1
screeninfo==0.8.1 screeninfo==0.8.1
# via manim # via manim
# via manimgl # via manimgl
setuptools==73.0.1
shiboken6==6.7.2 shiboken6==6.7.2
# via pyside6 # via pyside6
# via pyside6-addons # via pyside6-addons

View File

@ -7,7 +7,6 @@
# all-features: true # all-features: true
# with-sources: false # with-sources: false
# generate-hashes: false # generate-hashes: false
# universal: false
-e file:. -e file:.
alabaster==1.0.0 alabaster==1.0.0
@ -42,12 +41,6 @@ click-default-group==1.2.4
# via manim-slides # via manim-slides
cloup==3.0.5 cloup==3.0.5
# via manim # via manim
colorama==0.4.6
# via click
# via ipython
# via pytest
# via sphinx
# via tqdm
colour==0.1.5 colour==0.1.5
# via manimgl # via manimgl
comm==0.2.2 comm==0.2.2
@ -183,6 +176,7 @@ networkx==3.3
numpy==1.24.0 numpy==1.24.0
# via --override (workspace) # via --override (workspace)
# via contourpy # via contourpy
# via ipython
# via isosurfaces # via isosurfaces
# via manim # via manim
# via manim-slides # via manim-slides
@ -190,6 +184,7 @@ numpy==1.24.0
# via mapbox-earcut # via mapbox-earcut
# via matplotlib # via matplotlib
# via moderngl-window # via moderngl-window
# via networkx
# via pyrr # via pyrr
# via scipy # via scipy
packaging==24.1 packaging==24.1
@ -205,6 +200,8 @@ pandocfilters==1.5.1
# via nbconvert # via nbconvert
parso==0.8.4 parso==0.8.4
# via jedi # via jedi
pexpect==4.9.0
# via ipython
pillow==10.4.0 pillow==10.4.0
# via manim # via manim
# via manim-slides # via manim-slides
@ -225,6 +222,8 @@ prompt-toolkit==3.0.47
# via ipython # via ipython
psutil==6.0.0 psutil==6.0.0
# via ipykernel # via ipykernel
ptyprocess==0.7.0
# via pexpect
pure-eval==0.2.3 pure-eval==0.2.3
# via stack-data # via stack-data
pycairo==1.26.1 pycairo==1.26.1
@ -272,11 +271,14 @@ pytest==8.3.2
# via manim-slides # via manim-slides
# via pytest-cov # via pytest-cov
# via pytest-env # via pytest-env
# via pytest-missing-modules
# via pytest-qt # via pytest-qt
pytest-cov==5.0.0 pytest-cov==5.0.0
# via manim-slides # via manim-slides
pytest-env==1.1.3 pytest-env==1.1.3
# via manim-slides # via manim-slides
pytest-missing-modules==0.1.0
# via manim-slides
pytest-qt==4.4.0 pytest-qt==4.4.0
# via manim-slides # via manim-slides
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
@ -284,9 +286,6 @@ python-dateutil==2.9.0.post0
# via matplotlib # via matplotlib
python-pptx==1.0.2 python-pptx==1.0.2
# via manim-slides # via manim-slides
pywin32==306
# via jupyter-core
# via plumbum
pyyaml==6.0.2 pyyaml==6.0.2
# via manimgl # via manimgl
# via myst-parser # via myst-parser

66
tests/test_checkhealth.py Normal file
View File

@ -0,0 +1,66 @@
import importlib.util
import sys
from itertools import chain, combinations
import pytest
from click.testing import CliRunner
from pytest_missing_modules.plugin import MissingModulesContextGenerator
from manim_slides.__version__ import __version__
from manim_slides.checkhealth import checkhealth
MANIM_NOT_INSTALLED = importlib.util.find_spec("manim") is None
MANIMGL_NOT_INSTALLED = importlib.util.find_spec("manimlib") is None
PYQT6_NOT_INSTALLED = importlib.util.find_spec("PyQt6") is None
PYSIDE6_NOT_INSTALLED = importlib.util.find_spec("PySide6") is None
@pytest.mark.filterwarnings("ignore:Selected binding 'pyqt6' could not be found")
@pytest.mark.parametrize(
"names",
list(
chain.from_iterable(
combinations(("manim", "manimlib", "PyQt6", "PySide6"), r=r)
for r in range(0, 5)
)
),
)
def test_checkhealth(
names: tuple[str, ...], missing_modules: MissingModulesContextGenerator
) -> None:
runner = CliRunner()
manim_missing = "manim" in names or MANIM_NOT_INSTALLED
manimlib_missing = "manimlib" in names or MANIMGL_NOT_INSTALLED
pyqt6_missing = "PyQt6" in names or PYQT6_NOT_INSTALLED
pyside6_missing = "PySide6" in names or PYSIDE6_NOT_INSTALLED
if "qtpy" in sys.modules:
del sys.modules["qtpy"] # Avoid using cached module
with missing_modules(*names):
result = runner.invoke(
checkhealth,
env={"QT_API": "pyqt6", "FORCE_QT_API": "1"},
)
assert result.exit_code == 0
assert f"Manim Slides version: {__version__}" in result.output
assert sys.executable in result.output
if manim_missing:
assert "manim not found" in result.output
else:
assert "manim (version:" in result.output
if manimlib_missing:
assert "manimgl not found" in result.output
else:
assert "manimgl (version:" in result.output
if pyqt6_missing and pyside6_missing:
assert "No Qt API found" in result.output
elif pyqt6_missing:
assert "Qt API: pyside6 (version:" in result.output
else:
assert "Qt API: pyqt6 (version:" in result.output