Merge with main (#3815)

* fix a typo in deep_dive.rst (#3377)

* Several GitHub actions updates (#3397)

* Bump docker/login-action from 2 to 3

Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump docker/setup-buildx-action from 2 to 3

Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump docker/build-push-action from 4 to 5

Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4 to 5.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump docker/setup-qemu-action from 2 to 3

Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump actions/checkout from 3 to 4

Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* rtd: enable htmlzip build (#3355)

also, bump python to 3.11
fixes https://github.com/ManimCommunity/manim/issues/3342

* fix(docs): Remove extra curly bracket in LaTeX math expression to fix issue #3330 (#3389)

* Bug fix: Use np.isclose for float equality in number line elongated ticks (#3392)

* use np.isclose for float equality in number line elongated ticks

* use offsets relative to x_min to tell if we need to elongate a tick

* forgot to subtract to create list of offsets

* add test for elongated ticks float equality

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Remove unused import

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Updated several dependencies (#3399)

* updated lockfile

* ran poetry update again

* pyproject.toml: update manimpango version (#3405)

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Added docs for functions in `mobject_update_utils` (#3325)

* Added docs for functions in mobject_update_utils

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Updated docstring of always_shift

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Added period to sentence.

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Updated parameter description in always_redraw

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Update always_rotate description

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Finished parameters in always_redraw

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Changed comment in always_shift

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* update always_shift description

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* used normalize from manim.utils.space_ops

* fixed indentation in always_redraw

* added type-hints

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Fix tests to run on Cairo 1.18.0 (#3416)

* Add a script to build and install cairo

* Update gui tests for cairo 1.18.0

* update script to set env vars

* Make the script run with plain python

* Prefer the recently built one in pkg-config

* Skip the built if it's windows

* CI: build and install latest cairo

* CI: only run when cache is missed

* Disable compiling tests while building cairo

* update poetry lock file

* Display the cairo version when running pytest

* fixup

* tests: skip graphical test when cairo is old

* fix the path to find the pkgconfig files on linux

* set the LD_LIBRARY_PATH too

only then it'll work on linux

* fixup

* small fixup

* Move the script inside `.github/scripts` folder

* Make the minimum cairo version a constant

* Seperate setting env vars to a sperate step

this seem to have broken when cache is hit

* Fix: Fixed a bug in regards to empty inputs in AddTextLetterByLetter class.  (#3404)

* Misc: Just a class to test out some functions

* Fix: Fixed a bug in AddTextLetterByLetter class

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fix: Adjusted changes according to Ben's comments

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fix: Removed imports

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Feat: Adjusted changes to AddTextLetterByLetter

* Feat: Added test_creation

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Introduce new workflow creating a downloadable version of the documentation (#3417)

* Revert "rtd: enable htmlzip build (#3355)"

This reverts commit 571f79be2c.

* use python3.11 to build docs

* upgrade python version used in release publish workflow

* new workflow for building downloadable docs

* change event trigger for testing

* sudo apt

* rename release job; build html in poetry env

* set GITHUB_PATH instead of PATH

* introduce additional step

* use correct binary path

* forgot microtype

* fonts-roboto + actually compress files correctly

* fix asset path

* Update .github/workflows/release-publish-documentation.yml

Co-authored-by: Naveen M K <naveen521kk@gmail.com>

* pull_request -> workflow_dispatch

* Update .github/workflows/release-publish-documentation.yml

---------

Co-authored-by: Naveen M K <naveen521kk@gmail.com>

* Fix incorrect submobject count of multi-part Tex/MathTex mobjects by stopping them from adding empty submobjects (#3423)

* do not add a VectorizedPoint as a submobject if SingleStringMathTex renders to empty SVG

* test new behavior

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Update tests/module/mobject/text/test_texmobject.py

* Update tests/module/mobject/text/test_texmobject.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* CI: fix caching of cairo (#3419)

I forgot to change the path after moving around the file.

* Fix CSV reader adding empty lists in rendering summary (#3430)

* Fix CSV reader adding empty files

Fixes issue #3311

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Fix None check order in _tree_layout (#3421)

* Fix None check order in _tree_layout

* add tests to test_graph.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Bump teatimeguest/setup-texlive-action from 2 to 3 (#3431)

Bumps [teatimeguest/setup-texlive-action](https://github.com/teatimeguest/setup-texlive-action) from 2 to 3.
- [Release notes](https://github.com/teatimeguest/setup-texlive-action/releases)
- [Commits](https://github.com/teatimeguest/setup-texlive-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: teatimeguest/setup-texlive-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* bump dependencies -- see #3241 (#3433)

* Fix Typing (#3086)

* first draft of color class + starting library conversion

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* changed everything to Manim color todo: figure out circular dependency in utils

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* first working draft of new color version

* resolving conflicts

* resolving conflicts

* resolving conflicts

* resolving conflicts

* resolving conflicts

* changed default internal value of ManimColor to np.ndarray[float]

* starting to fix tests

* fixed more tests and changed precision of manim color

* removed premature color conversion

* fixed some more tests

* final test changes

* fix doctests

* fix for 3.8

* fixing ManimColor string representation

* removing some unneccesary conversions

* moved community constants to manim_colors.py and added more color standards

* Added typing.py and typed bezier.py, core.py, constants.py  fully

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fixed codeql complaints

* add type ignore for np.allclose

* fixed import in three_dimensions

* added ignore for F401 back again in flake

* added typings to coordinate_systems.py

* Few improvements to `graphing/coordinate_systems.py`

* added some typings to mobject/geometry/line.py

* updated typings for mobject/geometry/line.py

* Add missing imports to `line.py`

* added typings to three_dimensions.py

* Use `FunctionOverride` for animation overrides

Fix type signature of `set_color_by_gradient`

* Remove `TYPE_CHECKING` check

Doc is failing

* Revert "Remove `TYPE_CHECKING` check"

Fails due to circular import

* Use `Self` in `coordinate_systems.py`

* Typehinted mobject.py and updated manim.typing.py

* Typed VMobject

* Type-hinted manim.mobject.geometry

* math.cos->np.cos, etc & fixed incorrect typehints

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fix missing annotations import

* TypeAlias fix in typing.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Add ignore errors again to mypy because commits are not possible like this

* Fix last typing issues

* Update docs

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Only type check manim

* Try fixing pre-commit

* fix merge

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fix compat

* Fix compat again

* Fix imports compat

* Use union syntax

* Use union syntax

* Fix reduce_across_dimension

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Various test and merge fixes

* Doc fixes

* Last doc fix

* Revert usage of np over math

* Bump numpy version

* Remove obsolete duplicate example

* Fixed Incorrect Typehint in manim.constants

* Fix docstring typo

* More fixes

Use mypy.ini instead of .mypy.ini
Fix more docstrings
Improve types in utils and constants

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* docs fixes

* Add internal aliases

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fix compat

* line lengths in .rst file, formatting, typos

* add docstring for space_ops:cross2d

* add some more arrow tip typings (in a non-circular import causing way)

* yes, this can be deleted

* fix formatting of example

* added docstring to bezier::inverse_interpolation

* added docstring + test for bezier::match_interpolate

* some improvements in coordinate_systems

* Vector -> Vector3

* replaced np.ndarray with more appropriate type hints

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Apply feedback

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* revert to previous (new) version

* fix doctest

* fix ReST errors

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Alex Lembcke <alex.lembcke@gmail.com>
Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>
Co-authored-by: JasonGrace2282 <aarush.deshpande@gmail.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* fix: issue with ImageMobject bounding box (#3340)

* fix: fix an issue with ImageMobject bounding box

A missing point resulted in smaller bounding box causing issues it to be
smaller when the object is rotated. Added the missing fourth point to
ImageMobject points and altered call from camera. Filled in docstring
that used to propagate from superclass, saying that ImageMobject has no
points.

* add a test to check that rotating an image to and from doesn't change it

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: Václav Blažej <vaclav.blazej@warwick.ac.uk>
Co-authored-by: Naveen M K <naveen521kk@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* chore(deps): add Python 3.12 support (#3395)

* chore(deps): add Python 3.11 and 3.12 support


chore(deps): update lock file


chore(deps): remove colour


fix(deps): force NumPy version


fix(deps): relax constraints


chore(deps): update lock file

* fix(deps): make poetry happy

* fix(ci): skia pathops on 3.12

* fix(test): doctest skip

* disable python 3.8 pipeline

* removed get_parameters, replaced by direct call to inspect

* black

---------

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Added ability to remove non-svg LaTeX files (#3322)

* Added ability to remove latex junk (default True)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fixed tests (hopefully), and whitelisted .tex

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* reverted weird changes from merge

* See previous commit message

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fixed logs-too-long test

* Fixed log output

* Fixed typo ;)

* deleted unused variable

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* moved latex deletion to tex_file_writing.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* removed changes in scene files

* Added caching based on LaTeX expression .svg

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Deleted unused function in delete_old_tex

* make if condition more readable

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* cleaned up svg file check

* changed blacklist -> whitelist for file endings

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Reverted docstring change

* Updated delete_non_svg files docstring

* Changed list to a set

* Update manim/_config/utils.py

* Update manim/cli/render/global_options.py

* added one test for the no_latex_cleanup config option

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>
Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>

* feat: DecimalNumber() - added spacing between values and unit (#3366)

* feat: DecimalNumber() - added spacing between values and unit

* Update manim/mobject/text/numbers.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Update manim/mobject/text/numbers.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Update manim/mobject/text/numbers.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Update manim/mobject/text/numbers.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Update manim/mobject/text/numbers.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Update manim/mobject/text/numbers.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Update manim/mobject/text/numbers.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

---------

Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Add option to run examples directly with binder (#3427)

* Add option to run examples directly with binder

The minified JS is from
https://github.com/naveen521kk/manim-binder

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* slight style changes

* update the js file to fix on chrome

Signed-off-by: Naveen M K <naveen521kk@gmail.com>

* show the run button as an cursor

* make the video to be 100% of the width

* Update manim/utils/docbuild/manim_directive.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Add a "Make interactive" button instead of "Run" button

Clicking on the "Make interactive" button show the code-editor and "run" button

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* update margin for run interactive button

---------

Signed-off-by: Naveen M K <naveen521kk@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Prepare v0.18.0 (#3439)

* generated changelog and bumped version

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* changed some PR descriptions in the changelog

* fix some docbuild warnings

* fixed a reference that became ambiguous

* copyedit pass of changelog

* some more changelog polishing

* bump release date

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* updated release date

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Fixed wrong path in action building downloadable docs (#3450)

* fixed wrong path in action building downloadable docs

* fix second occurrence of wrong path

* Allow accessing ghost vectors in :class:`.LinearTransformationScene` (#3435)

* Fix CSV reader adding empty files

Fixes issue #3311

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Added LinearTransformationScene.ghost_vectors

* Added test and prevented empty VGroups as ghost vectors

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fixed typo in example

* Added ability to join together multiple renders

* Revert "Added ability to join together multiple renders" (wrong branch)

This reverts commit dee29c390f.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Add type hints to `_config` (#3440)

* Add type hints to `_config`

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fix call issues

* Fix wrong value being used

* Fix test

* Fix wrong value being set

* lint

* Few type fixes

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Fix Idicate docs typo (#3461)

* Update indication.py (#3477)

reading docs, im sure oppising isnt a word

* Optimized `get_unit_normal()` and replaced `np.cross()` with custom `cross()` in `manim.utils.space_ops` (#3494)

* Added cross and optimized get_unit_normal in manim.utils.space_ops

* Added missing border case to new get_unit_normal where one vector is nonzero

* Updated test_threed.py::test_Sphere test data

* Update dependency constraints, fix deprecation warnings (#3376)

* WIP: Update metadata

* Finish removing upper bounds

Drop requests dependency, use urllib instead
order depencencies

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fix issues on 3.12

* Order dev dependencies

* Update most dev deps, update lint config

* Add missing import

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* trigger CI

* More deprecation fixes

* Missing argument

* Deprecation fixes, again

* Use older xdist to fix test flakyness

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* fix 360° to 180° in quickstart tutorial (#3498)

* Update Docker base image to python3.12-slim (#3458) (#3459)

* Update Docker base image to python3.12-slim (#3458)

* Update docker/Dockerfile

---------

Co-authored-by: Melody Griesen <jvgriese@ncsu.edu>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* fix line_join to joint_type in example_scenes/basic.py (#3510)

* fix typo in docstring for DtUpdater example: line -> square (#3509)

* Implement caching of fonts list to improve runtime performance (#3316)

* Implement caching of fonts list to improve runtime performance

* Fix small use_svg_cache kwargs error

* replaced font list with LRU cache

* Removed deprecated new command (#3512)

Co-authored-by: Naveen M K <naveen521kk@gmail.com>

* Added `cap_style` feature to `VMobject` (#3516)

* Added cap_style feature to VMobject

* Added an example to `set_cap_style` method

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Unsplitted line 2501

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Added graphical test for cap_style

* Added vmobject_cap_styles.npz for testing cap_styles

* Removed # noqa comments from vectorized_mobject.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* feat(cli): optionally hide version splash (#3329)

* feat(cli): optionally hide version splash

As discussed in #3326, this PR proposes a new optional flag to hide the version splash when manim command in launched. Additionally, the splash print is now inly executed when the CLI is executed, not on module import.

After looking at the current documentation, it does not seem to change anything. I only saw that you documented a version splash for when the CLI is used, but not when the module is imported. So removing it should not break the api docs.

In the future, users can still have version information with `import manim; print(manim.__version__)`.

Closes #3326

* chore(tests): make tests pass

---------

Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>

* Reformatting the `--save_sections` output to have the format `<Scene>_<SecNum>_<SecName><extension>` (#3499)

* Worked on issue 3471, fixing rendered file names to inherit section name

* Modified file name to include section number and name

* Modified tests for file names to include number and name, in order to pass

---------

Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>

* Explain ``.Transform`` vs ``.ReplacementTransform`` in quickstart examples (#3500)

* Explained ReplacementTransform vs Transform

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Added section explaining Transform vs ReplacementTransform

* Added a->b->c example

* Clarified explanation

* Fixed Typo

* Fixed missing colon

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>

* Fix formatting building blocks (#3515)

* Fix formatting building blocks

* Fix formatting building blocks

---------

Co-authored-by: Jason Grace <110117391+JasonGrace2282@users.noreply.github.com>

* Bump jupyter-server from 2.9.1 to 2.11.2 (#3497)

Bumps [jupyter-server](https://github.com/jupyter-server/jupyter_server) from 2.9.1 to 2.11.2.
- [Release notes](https://github.com/jupyter-server/jupyter_server/releases)
- [Changelog](https://github.com/jupyter-server/jupyter_server/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter-server/jupyter_server/compare/v2.9.1...v2.11.2)

---
updated-dependencies:
- dependency-name: jupyter-server
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Account for dtype in the pixel array so the maximum value stays correct in the invert function (#3493)

* fix(lib): fix

This fixes an issue where the `invert` argument would only work for `uint8` dtypes. Now the `max` value is updated according to the pixel array dtype.

Maybe we should add unit tests for that, but haven't found an obvious place to put unit tests.

* chore(ci): add basic test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fix(ci): wrong attr name

* Update tests/module/mobject/test_image.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Added `grid_lines` attribute to `Rectangle` to add individual styling to the grid lines (#3428)

* Added 'grid_line_stroke_width' parameter in Rectangle

* Added 'grid_lines' (VGroup) attribute to 'Rectangle' class

---------

Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>

* Fix rectangle grid properties (#3082) (#3513)

* Import  for both vertical and horizontal gridlines in

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Fix animations with zero runtime length to give a useful error instead of a broken pipe (#3491)

* Fix animation group not erroring when instantiated with an empty list

* Move error messages into Animation.begin()

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Added tests

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Update manim/animation/animation.py

* Update manim/animation/composition.py

* Update manim/animation/animation.py

Co-authored-by: Jason Grace <110117391+JasonGrace2282@users.noreply.github.com>

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Jason Grace <110117391+JasonGrace2282@users.noreply.github.com>

* fixed the stroke width issue with single color in streamlines (#3436)

* fixed the stroke width issue with single color in streamlines

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Added test for streamlines

* Added test for streamlines

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: MrDiver <mrdiverlp@gmail.com>

* Add Documentation to `.to_edge` and `to_corner` (#3408)

* Added docstrings and example renders to Mobject.to_corner() and Mobject.to_edge

* Added docstrings and example renders to Mobject.to_corner() and Mobject.to_edge

* Update manim/mobject/mobject.py

* Update manim/mobject/mobject.py

* Update manim/mobject/mobject.py

* Update manim/mobject/mobject.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Update manim/mobject/mobject.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Adding the ability to pass lists and generators to .play() (#3365)

* adding the ability to pass lists and generators to .play()

* fix for _AnimationBuilder

* Changed handling of generators to accept lists of generators and normal arguments at the same time

* Animation group handles generators

* Refactored into own function for reusability

* Fix typing

* Fix typing

---------

Co-authored-by: Jason Grace <110117391+JasonGrace2282@users.noreply.github.com>

* follow-up to #3491, made errors more consistent. fixes #3527

* chore(docs): add some words about Cairo 1.18 (#3530)

* chore(docs): add some words about Cairo 1.18

Closes #3521

* fix(docs): typo

* Update testing.rst

* Update testing.rst

* Fix formatting of ``MoveAlongPath`` docs (#3541)

* Remove wag method from Mobject

* Fixed MoveAlongPath

* Revert remove wag

Created a new branch with the wrong base, sorry ;)

* Fixed Animate Type-hint (#3543)

* Remove wag method from Mobject (#3539)

Co-authored-by: Francisco Manríquez Novoa <49853152+chopan050@users.noreply.github.com>

* Fix typo of `get_y_axis_label` docstring (#3547)

* Finish TODO's in ``contributing/typings.rst`` (#3545)

* Updated typing docs

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Added link for protocols

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Added object vs Any

* Fix Typo

* Rephrase TypeVar

Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

* Compare between tuple vs list

Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

* typing -> collections.abc

Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

* typing -> collections.abc

Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

* change method to attr

Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

* clarify object typehint

Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

* Fix code typo

Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

* Added if TYPE_CHECKING section

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fix reST for inline code

* Elaborate on if TYPE_CHECKING

Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

* functions -> collections

Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>

* Fix use of `Mobject`'s deprecated `get_*()` and `set_*()` methods in Cairo tests (#3549)

* Fix Deprecation warnings in cairo tests

* Fix animation/specialized.py

* add note in docstring of ManimColor about class constructors (#3554)

* Added support for Manim type aliases in Sphinx docs + Added new TypeAliases (#3484)

* Updated manim.typing and included TypeAliases in docs.source.conf

* Added Vector2 and reorganized manim_type_aliases

* Fixed __all__ exports for __all__ of manim

* Update manim/cli/render/global_options.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Draft of new typing docs and new autotyping directive

* Changed vertical bars to Unions

* Updated poetry.lock

* Created custom file parser for manim.typing

* Got reST parser going

* Updated autotyping and parsing

* Update parsing

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Added code_block toggle

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Added typings to directives

* Renamed Tuple to tuple in manim.typings

* Added missing docs for type aliases

* Fixed exponent typo in ManimInt

* Hyperlinks to types work - removed Module Attributes section

* Removed Unused Import

Remove ``import re``

* Added freeglut-devel to workflows for Linux

Hopefully (?) fix the GLU import error

* Fix package name

* Add support for Type Aliases section in every module - Renaming of Vector types

* Add/fix docs for directive, parser and others

* Fixed alias typo in module_parsing

* Fix decode/import bugs, fix minor details in docs

* Added missing docs for utils.docbuild and utils.testing

* Sort alphabetically entries in utilities_misc.rst

* Address review comments, add notes about Vector and hyperlinks inside definition blocks

---------

Co-authored-by: MrDiver <mrdiverlp@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: JasonGrace2282 <aarush.deshpande@gmail.com>

* Improve documentation section about contributing to docs (#3555)

* Improve section in docs about contributing to docs

* Add note about doc build command depending on the OS

* Improve section in docs about contributing to docs

* Add note about doc build command depending on the OS

* Fix wrong toctree path in docs/source/contributing/docs.rst

* Add helpful hints to `VGroup.add()` error message (#3561)

* Improve VGroup creation error message

* Use .__name__ for the type

Co-authored-by: Jason Grace <110117391+JasonGrace2282@users.noreply.github.com>

---------

Co-authored-by: Jason Grace <110117391+JasonGrace2282@users.noreply.github.com>

* exception add if new_rings is none (#3574)

* exception add if new_rings is none

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Fix typing of `Animation` (#3568)

* Add 'to be used in the future' TODOs to ManimFrame (#3553)

* Refactor `TexTemplate` (#3520)

* Refactor `TexTemplate`

* Add tests, refactor some things

* Fixed Some tests

* Move typing imports

* Fix remaining tests

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: JasonGrace2282 <aarush.deshpande@gmail.com>
Co-authored-by: Jason Grace <110117391+JasonGrace2282@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Bump github/codeql-action from 2 to 3 (#3567)

Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump actions/upload-artifact from 3 to 4 (#3566)

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump actions/setup-python from 4 to 5 (#3565)

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* updated several packages (pillow, jupyterlab, notebook, jupyterlab-lsp, jinja2, gitpython) (#3593)

* Removed -s / --save_last_frame flag from CLI arguments (#3528)

* Remove -s flag

* Make help text more verbose

* fix write_subcaption_file error when using opengl renderer (#3546)

* fix write_subcaption_file error when using opengl renderer

* Update manim/scene/scene_file_writer.py

---------

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Update docker.rst to use bash from the PATH (#3582)

* fix typo in value_tracker.py (#3594)

* fix `get_arc_center()` returning reference of point (#3599)

* Add ref_class (#3598)

* Fix typehint (#3592)

* Update ci.yml (#3611)

* fix type hint of indication.py (#3613)

* Revert vector type aliases to NumPy ndarrays (#3595)

* Improve handling of specified font name (#3429)

Co-authored-by: Jason Grace <110117391+JasonGrace2282@users.noreply.github.com>
Co-authored-by: JasonGrace2282 <aarush.deshpande@gmail.com>

The proposed fix does two things :

* If the specified font is 'sans-serif' : change it to 'sans' as this is the name used in the list of fonts
* if the font name is not in the list of fonts, automatically check if the capitalized version of the font exists in the list of fonts. If not, print a warning to the user.

* Remove support for dynamic plugin imports (#3524)

* Remove call to deprecated `pkg_resources`

* Remove support for dynamic plugin imports, update plugin utilities

* fix affected tests

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* more fixes

* Last fix

* Fix import

* Update docs

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Jason Villanueva <a@jsonvillanueva.com>

* Run poetry lock --no-update (#3621)

* Update jupyter.rst (#3630)

Pinpoint IPython==8.21.0 for Google Colab, because more recent versions are incompatible with their runtime.

* Fix Vector3 -> Vector3D in contributing docs (#3639)

* Bump black from 23.12.1 to 24.3.0 (#3649)

Bumps [black](https://github.com/psf/black) from 23.12.1 to 24.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.12.1...24.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump cryptography from 42.0.0 to 42.0.4 (#3629)

Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.0 to 42.0.4.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.0...42.0.4)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Code Cleanup: removing unused imports and global variables (#3620)

* Remove unused import

* More security fixes

* Remove unused global variable

* More fixes

* Revert change (actual fix would require some rewrite)

* Add exception for edge case to satisfy warning

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Stuff

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Fixing the behavior of `.become` to not modify target mobject via side effects fix color linking (#3508)

* Copied ndarray for rgbas when interpolating

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* changing .become to copy the target mobject

* change tests and test data to reflect .become new behavior

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Update tests/test_graphical_units/test_mobjects.py

* removed unused copy_submobject kwarg

* added doctests and improved documentation

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Added some examples for `Mobject`/`VMobject` methods (#3641)

* Add examples to mobject+vmobject methods

* Add missing import

* Separate whitespace to point_from_proportion

* Fixes!

* Changed example of Mobject.get_color

* Remove unneccessary import

* Add in import

* Fix typehint of `Vector` direction parameter (#3640)

* Fix typehint of Vector

* Change from Vector to Point in typehint

In `TipableVMobject._pointify` it converts a 3D
list of the form [x, y, z] to a Vector3D. Therefore
the direction parameter can take lists, not just numpy arrays.

* Fix bug in :class:`.VMobjectFromSVGPath` (#3677)

* Fixes #3676

* Update manim/mobject/svg/svg_mobject.py

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* Fixed problem and added test

---------

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* Flake8 rule C901 is about McCabe code complexity (#3673)

* Flake8 rule C901 is about McCabe code complexity

It is not about flake8-comprehensions.

* max-complexity = 29

* Fix broken link to Poetry's installation guide in the first time contributors page (#3692)

* Fix minor grammatical errors found in the index page of the documentation (#3690)

* Fix some minor grammatical errors in the index page of the docs

* Fix grammar

* Undo uneccessary change in phrasing

* fix(LICENSE): update year (#3689)

* Remove deprecated parameters and animations (#3688)

* Remove deprecated parameters/animations

* Remove test

* Remove test data

* Attempted fix for windows cp1252 encoding failure (#3687)

* Attempt to fix windows test

* Revert "Attempt to fix windows test"

This reverts commit e31c2077cd.

* try a different fix

* maybe both fixes together?

* try adding in CI

* Update ci.yml

* Update logger_utils.py

* maybe needs a dash?

* try utf8 again

* Remove legacy_windows

* try changing test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Try decoding after capturing bytes output

* Nicer fix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Fix typo (#3696)

* Docs: fix out-dated CLI option in Manim's Output Settings (#3674)

* Docs: fix out-dated CLI option in Manim's Output Settings

* Docs: more fluent English

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* Docs: break lines

* Docs: more fluent English

* Docs: remove a space

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

---------

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* only do actions if try succeeded (#3694)

* Mention pixi in installation guide (#3678)

* Mention pixi in installation guide

* Update docs/source/installation/conda.rst

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Add note

---------

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Fix successive calls of :meth:`.LinearTransformationScene.apply_matrix` (#3675)

* docs: improve installation FAQ's

* I have potentially resolved the issue when in LinearTransformationScene between two animations of transforming space we invoke the self.wait()

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* added another solutions in comments, added tests and removed wrong files from git

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* yeah , i forgot to save the file xd

* fixed the test, removed the comments my in changed file

* fix test and speed up test time for test_apply_matrix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fixed the test, removed the comments my in changed file

* fixed the test

* Revert "docs: improve installation FAQ's"

This reverts commit e53a1c8d6f.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: JasonGrace2282 <aarush.deshpande@gmail.com>
Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* Bump actions/cache from 3 to 4 (#3607)

Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* Bump FedericoCarboni/setup-ffmpeg from 2 to 3 (#3608)

Bumps [FedericoCarboni/setup-ffmpeg](https://github.com/federicocarboni/setup-ffmpeg) from 2 to 3.
- [Release notes](https://github.com/federicocarboni/setup-ffmpeg/releases)
- [Commits](https://github.com/federicocarboni/setup-ffmpeg/compare/v2...v3)

---
updated-dependencies:
- dependency-name: FedericoCarboni/setup-ffmpeg
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump ssciwr/setup-mesa-dist-win from 1 to 2 (#3609)

Bumps [ssciwr/setup-mesa-dist-win](https://github.com/ssciwr/setup-mesa-dist-win) from 1 to 2.
- [Release notes](https://github.com/ssciwr/setup-mesa-dist-win/releases)
- [Commits](https://github.com/ssciwr/setup-mesa-dist-win/compare/v1...v2)

---
updated-dependencies:
- dependency-name: ssciwr/setup-mesa-dist-win
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: update typing guidelines (#3704)

* Update typing guidelines

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fix formatting

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Update documentation and typings for `ParametricFunction` (#3703)

* Update documentation and typings for ParametricFunction

* Use manim tyings

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* fix typings

* a few doc fixes

* Update manim/mobject/graphing/functions.py

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* update typings

* remove extraneous line

* update example code

* add line back for comptibility

* import TYPE_CHECKING

---------

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* fix(copyright): automate copyright updating for docs (#3708)

* Fix some typehints in mobject.py (#3668)

* refactor(mobject): fix some typehints

* Move typing_extensions import under `if TYPE_CHECKING`
* Change from using `def animate(self: T ,...) -> T` to `def
  animate(self, ...) -> Self` as stated in PEP 673
* Fix incorrect usage of `T` in a method

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* move updaters type alias into TYPE_CHECKING

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Bump idna from 3.6 to 3.7 (#3693)

Bumps [idna](https://github.com/kjd/idna) from 3.6 to 3.7.
- [Release notes](https://github.com/kjd/idna/releases)
- [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.rst)
- [Commits](https://github.com/kjd/idna/compare/v3.6...v3.7)

---
updated-dependencies:
- dependency-name: idna
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump pillow from 10.2.0 to 10.3.0 (#3672)

Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.2.0 to 10.3.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.2.0...10.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Fix typo (#3721)

* Fixed `Mobject.put_start_and_end_on` with same start and end point (#3718)

* fix put_start_and_end_on() at the same point

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* [pre-commit.ci] pre-commit autoupdate (#3332)

* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/pre-commit/pre-commit-hooks: v4.4.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.4.0...v4.6.0)
- [github.com/pycqa/isort: 5.12.0 → 5.13.2](https://github.com/pycqa/isort/compare/5.12.0...5.13.2)
- [github.com/asottile/pyupgrade: v3.10.1 → v3.15.2](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.15.2)
- [github.com/psf/black: 23.7.0 → 24.4.0](https://github.com/psf/black/compare/23.7.0...24.4.0)
- [github.com/asottile/blacken-docs: 1.15.0 → 1.16.0](https://github.com/asottile/blacken-docs/compare/1.15.0...1.16.0)
- [github.com/PyCQA/flake8: 6.1.0 → 7.0.0](https://github.com/PyCQA/flake8/compare/6.1.0...7.0.0)
- [github.com/pre-commit/mirrors-mypy: v1.5.1 → v1.9.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.5.1...v1.9.0)
- [github.com/codespell-project/codespell: v2.2.5 → v2.2.6](https://github.com/codespell-project/codespell/compare/v2.2.5...v2.2.6)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* make smoothererstep readable again, avoid overlong line

* zoom_value more readable

* fix blacken-docs touching .github

* fix codespell setup, remove unnecessary file, fix some typos

* flake8: ignore E704, triggered by overload

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Update docs/source/tutorials/quickstart.rst

* more flake fixes

* try to make blacken-docs happy

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* fix(autoaliasattr): search for type aliases under if TYPE_CHECKING (#3671)

* build(deps): read-the-docs sphinx (#3720)

* Fix issue where SpiralIn doesn't show elements. (#3589)

* Set SpiralIn to use fill_opacity 1 if not set

* Create SpiralIn control data

* Create test for SpiralIn

* Fix spiralin to separate fill and stroke opacity

* resolve opacity issue

* fix test data

---------

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Clean Graph layouts and increase flexibility (#3434)

* allow user-defined layout functions for Graph
+ fixup type annotations

* only pass relevant args

* write tests

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* change_layout forward root_vertex and partitions
- deduplicated layout code in __init__ and change_layout
- fixed change_layout backwards compatibility

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* add test for change_layout

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fix copy/paste error

* fix

* fixup types for CodeQL

* static type the Layout Names

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fix dynamic union type for Python 3.9

* add example scenes to LayoutFunction protocol documentation

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Replace references to np.ndarray with standard Manim types

* Label NxGraph as a TypeAlias

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Follow-up to graph layout cleanup: improvements for tests and typing (#3728)

* suggestions from review on #3434

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Update coordinate_systems.py (#3730)

small change

* build(ci): change from macos-latest to macos-13 (#3729)

* Add ``--preview_command`` cli flag (#3615)

* Add preview_command cli flag

* Edit help for --preview_command

* Change back from subprocess.run

* Remove old comment

* Bug with timg stopped happening with sp.run

* Fix docstring

* Revert "Fix docstring"

This reverts commit d2c00fc24dc46586f994237f1d2758528b78d6a3.

* Actually fix docstring

* Change help for option

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

---------

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* AnimationGroup: optimized interpolate() and fixed alpha bug on finish() (#3542)

* Optimized AnimationGroup computation of start-end times with lag ratio

* Added extra comment for init_run_time

* Added full path to imports in composition.py

* Optimized AnimationGroup.interpolate

* Fixed final bugs

* Removed accidental print

* Final fix to AnimationGroup.interpolate

* Fixed animations being skipped unintentionally

* Addressed requested changes

---------

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Fixed ```get_anchors()``` Return Type Inconsistency (#3214)

* changed return type of get_anchors()

* Ensured consistency with OpenGLVMobject

* Fixed CodeQl, updated docstring

* Update manim/mobject/types/vectorized_mobject.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Update manim/mobject/opengl/opengl_vectorized_mobject.py

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* fixed typo, t -> e

* fixed doctest

---------

Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>
Co-authored-by: Francisco Manríquez Novoa <49853152+chopan050@users.noreply.github.com>

* fixed [""] being set as loaded plugins (#3734)

* Prepare new release: v0.18.1 (#3719)

* add note about changelog in changelog.rst

* bump version

* Update CITATION.cff

* feat: Add three animations that together simulate a typing animation (#3612)

* feat: Add animations that together simulate typing

AddTextLetterByLetterWithCursor

RemoveTextLetterByLetterWithCursor

Blink

* Revert "feat: Add animations that together simulate typing"

This reverts commit 5fe256880d.

* Revert "Revert "feat: Add animations that together simulate typing""

This reverts commit 6a8244a157.

* Add new animations to __all__

* Temporarily remove docs example

* Modify "Blink" and add docstring examples back in

To avoid 0-second animations, which fail docstring test

* Address requested changes

Fix imports
Remove redundant constructor arguments
Improve names

* Shorten names

* Fix release documentation building (#3737)

* [pre-commit.ci] pre-commit autoupdate (#3739)

updates:
- [github.com/psf/black: 24.4.0 → 24.4.2](https://github.com/psf/black/compare/24.4.0...24.4.2)
- [github.com/pre-commit/mirrors-mypy: v1.9.0 → v1.10.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.9.0...v1.10.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Fixes #3744 (#3745)

Co-authored-by: Andrzej Nagórko <>

* Bump tqdm from 4.66.1 to 4.66.3 (#3746)

Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.66.1 to 4.66.3.
- [Release notes](https://github.com/tqdm/tqdm/releases)
- [Commits](https://github.com/tqdm/tqdm/compare/v4.66.1...v4.66.3)

---
updated-dependencies:
- dependency-name: tqdm
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump jinja2 from 3.1.3 to 3.1.4 (#3750)

Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.3...3.1.4)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add typehints to `manim.utils.iterables` (#3751)

* typehint iterables

* organize typing hints

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* remove any

* Add overloads for tuplify

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Remove example

* feedback

* Make TypeVars accessible at runtime

* Add hints for zip

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

* typing -> collections.abc

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

* try to make mypy happy

* zip[tuple[T, ...]] instead of zip[T]

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

* Let `SceneFileWriter` access `ffmpeg` via `av` instead of via external process (#3501)

* added av as a dependency

* make partial movie files use av instead of piping to external ffmpeg

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* opengl rendering: use av for movie files

* no need to check for ffmpeg executable

* refactor: *_movie_pipe -> *_partial_movie_stream

* improve (oneline) documentation

* pass more options to partial movie file rendering

* move ffmpeg verbosity settings to config; renamed option dict

* replaced call to ffmpeg in combine_files by using av

Co-authored-by: Jérome Eertmans <jeertmans@icloud.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* there was one examples saved as a gif?

* chore(deps): re-order av

* chore(lib): simplify `write_frame` method

Reduces the overall code complexity

* chore(lib): add audio

* fix(lib): same issue for conversion

* fix(lib): webm export

* fix(lib): transparent export

Though the output video is weird

* try(lib): fix gif + TODOs

* chore(deps): lower dep crit

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* feat(lib): add support for GIF

* fix(ci): rewrite tests

* fix

* chore(ci): prevent calling concat on empty list

* add missing dot

* fix(ci): update frame comparison ?

* fix(log): add handler to libav logger

* chore: add TODO

* fix(lib): concat issue

* Revert "fix(ci): update frame comparison ?"

This reverts commit 904cfb46ae.

* fix(ci): make it pass tests

* chore(lib/docs/ci): remove FFMPEG entirely

This removes any reference to FFMPEG, except in translation files

* added av as a dependency

* make partial movie files use av instead of piping to external ffmpeg

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* opengl rendering: use av for movie files

* no need to check for ffmpeg executable

* refactor: *_movie_pipe -> *_partial_movie_stream

* improve (oneline) documentation

* pass more options to partial movie file rendering

* move ffmpeg verbosity settings to config; renamed option dict

* replaced call to ffmpeg in combine_files by using av

Co-authored-by: Jérome Eertmans <jeertmans@icloud.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* there was one examples saved as a gif?

* chore(deps): re-order av

* chore(lib): simplify `write_frame` method

Reduces the overall code complexity

* chore(lib): add audio

* fix(lib): same issue for conversion

* fix(lib): webm export

* fix(lib): transparent export

Though the output video is weird

* try(lib): fix gif + TODOs

* chore(deps): lower dep crit

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* feat(lib): add support for GIF

* fix(ci): rewrite tests

* fix

* chore(ci): prevent calling concat on empty list

* add missing dot

* fix(ci): update frame comparison ?

* fix(log): add handler to libav logger

* chore: add TODO

* fix(lib): concat issue

* Revert "fix(ci): update frame comparison ?"

This reverts commit 904cfb46ae.

* fix(ci): make it pass tests

* chore(lib/docs/ci): remove FFMPEG entirely

This removes any reference to FFMPEG, except in translation files

* chore(deps): update lockfile

* chore(lib): rewrite ffprobe

* fix typo

* slightly more aggressive removal of ffmpeg in docs; minor language changes

* fix gif output stream dimensions

* minor style change

* fix encoding of (transparent) mov files

* fixed metadata / comment

* set frame rate for --format=gif in output_stream

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* more video tests for different render settings, also test pix_fmt

* improve default bitrate setting via crf

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* parametrized format/transparency rendering test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* context managers for (some) av.open

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Update manim/utils/commands.py

Co-authored-by: Jérome Eertmans <jeertmans@icloud.com>

* fixed segfault

* update test data involving implicit functions (output improved!)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* explicity set pix_fmt for transparent webms

* special-special case extracting frame from vp9-encoded file with transparency

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fix transparent gifs, more special casing in parametrized video format test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* run tests on macos-latest again

* removed old control data

* Revert "run tests on macos-latest again"

This reverts commit f50efa4b88.

* added sound to codec test; fixed issue with sound track in gif (disabled) and webm (now via opus)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* manual wav -> ogg transcoding

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fixed f-string

* refactored codec test, split out gif

* check for non-zero audio samples

* more cleanup

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* remove ffmpeg from readthedocs apt_packages

* round up run_time if positive and shorter than current frame rate

* added more run_time tests

* black

* improve implementation of test

* removed some unused imports

* improve wording of logged warning

Co-authored-by: Jérome Eertmans <jeertmans@icloud.com>

* move run_time checks from Animation.begin to Scene.get_run_time

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* remove unused import

* flake: PT012

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Jérome Eertmans <jeertmans@icloud.com>

* Use --py39-plus in pre-commit (#3761)

* Use --py39-plus in pre-commit

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fix indication.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Optimized `manim.utils.bezier.is_closed()` (#3768)

* Optimized manim.utils.bezier.is_closed()

* oops, that shouldn't have been there

* Slightly optimized is_closed() even more

* Added doctest for is_closed()

* Created and optimized Bézier splitting functions such as `partial_bezier_points()` in `manim.utils.bezier` (#3766)

* Optimized manim.utils.partial_bezier_points()

* Added split_bezier, subdivide_bezier and bezier_remap, and tests

* Use bezier_remap() in VMobject and OpenGLVMobject()

* Note that partial_bezier_points is similar to calling split_bezier twice

* Bump requests to 2.32.0 (#3776)

updated-dependencies:
- dependency-name: requests
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Fix assertions and improve error messages when adding submobjects (#3756)

* Optimized AnimationGroup computation of start-end times with lag ratio

* Added extra comment for init_run_time

* Added full path to imports in composition.py

* Optimized AnimationGroup.interpolate

* Fixed final bugs

* Removed accidental print

* Final fix to AnimationGroup.interpolate

* Fixed animations being skipped unintentionally

* Fix and improve Mobject assertions when adding submobjects

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Update examples in Mobject.add() and OpenGLMobject.add() docstrings

* overriden -> overridden

* Joined string in OpenGLMobject error message

* Address requested changes

* OpenGLVMObjects -> OpenGLVMobjects

* Use tuplify in VGroup.__setitem__()

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Add pyproject for ruff formatting (#3777)

* Add pyproject for ruff

* add black config back

* Make only formatting

* rearrange isort to undo diff

* poetry lock

* Feedback

* style

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

---------

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

* pre-commit change to ruff (#3779)

* pre-commit change to ruff

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* fixes

* astral-sh ruff bump

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Ignore Ruff format in git blame (#3781)

* Fixed `there_and_back_with_pause()` rate function behaviour with different `pause_ratio` values (#3778)

Co-authored-by: Francisco Manríquez Novoa <49853152+chopan050@users.noreply.github.com>

* Optimize VMobject methods which append to points (#3765)

* Add `@` shorthand for `CoordinateSystem` methods `coords_to_point` (`c2p`) and `point_to_coords` (`p2c`) (#3754)

* Add shorthand for axes

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Add spacing

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

* Convert CoordinateSystem example, and add to NumberLine

* Add doctest for NumberLine

* Add test

* Fix typehint for c2p

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>
Co-authored-by: Francisco Manríquez Novoa <49853152+chopan050@users.noreply.github.com>

* [pre-commit.ci] pre-commit autoupdate (#3784)

* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.4.4 → v0.4.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.4...v0.4.5)
- [github.com/codespell-project/codespell: v2.2.6 → v2.3.0](https://github.com/codespell-project/codespell/compare/v2.2.6...v2.3.0)

* Fix typo

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: JasonGrace2282 <aarush.deshpande@gmail.com>

* [pre-commit.ci] pre-commit autoupdate (#3794)

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.4.5 → v0.4.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.5...v0.4.7)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Add Ruff Lint (#3780)

Adds Ruff Linting to CI, and replaces isort in the pre-commit config with Ruff's isort rules.

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

* Replace Pyupgrade with Ruff rule (#3795)

* Add config for pyupgrade

* Fix pyupgrade errors

* Unsafe-fixes

* Nicer way of formatting

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

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

* Revert "Nicer way of formatting"

This reverts commit 48013f4a30.

---------

Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Bump tornado from 6.4 to 6.4.1 (#3796)

Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.4 to 6.4.1.
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.4.0...v6.4.1)

---
updated-dependencies:
- dependency-name: tornado
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update opengl_vectorized_mobject.py (#3790)

The "insert_n_curves_to_point_list" function requires the "points" argument to be a numpy array, since it calls the "get_bezier_tuples_from_points" function, which requires "points" to be a numpy array because it has the "return points.reshape((-1, nppc, 3))" statement. Ordinary lists do not have a "reshape" method.

So we need to convert "sp1" and "sp2" to numpy arrays before calling the "insert_n_curves_to_point_list" function.

Co-authored-by: Francisco Manríquez Novoa <49853152+chopan050@users.noreply.github.com>

* [pre-commit.ci] pre-commit autoupdate (#3801)

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.4.7 → v0.4.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.7...v0.4.8)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Add typings to `OpenGLMobject` (#3803)

* Add typings to OpenGLMobject

* Import typing_extensions

* Add explicit returns to inner functions in .arrange_in_grid()

* Add quotes to parameters in ValueError

* Add some more typings

* Address requested changes

* Type apply_over_attr_arrays with TypeVar

* Fix use of TypeVar

* Add Vector3D typing in set_x, set_y and set_z

* fix: importing manim should not trigger pygments.styles.get_all_styles (#3797)

* fix: importing manim should not trigger pygments.styles.get_all_styles

Removed the Code.styles_list attribute.

Rewrote the documentation to say that a list of all styles can be generated by calling list(pygments.styles.get_all_styles()).

The example in the docstring of Code was rewritten to use an explicit code style name.

* fix: small change to documentation

* Added potential class method to get available code styles.

* Adding typehints to newly-added attributes.

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* Removing unnecessary lines.

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

---------

Co-authored-by: adeshpande <110117391+JasonGrace2282@users.noreply.github.com>

* [pre-commit.ci] pre-commit autoupdate (#3809)

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.4.8 → v0.4.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.8...v0.4.9)
- [github.com/PyCQA/flake8: 7.0.0 → 7.1.0](https://github.com/PyCQA/flake8/compare/7.0.0...7.1.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Bump urllib3 from 2.2.1 to 2.2.2 (#3810)

Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.2.1 to 2.2.2.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.2.1...2.2.2)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update macos packages (#3812)

* Fixed infinite loop in OpenGL `BackgroundRectangle.get_color()` (#3732)

Co-authored-by: Francisco Manríquez Novoa <49853152+chopan050@users.noreply.github.com>

* Some fixes for interpolation

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Naveen M K <naveen521kk@gmail.com>
Co-authored-by: Holly and Prosper <45610532+rongpenl@users.noreply.github.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Naveen M K <naveen521kk@gmail.com>
Co-authored-by: Anousheh Moonen <141789878+u7481690@users.noreply.github.com>
Co-authored-by: Narahari Rao <narahari387@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Immanuel-Alvaro-Bhirawa <127812163+Immanuel-Alvaro-Bhirawa@users.noreply.github.com>
Co-authored-by: Nikhil Iyer <iyer.h.nikhil@gmail.com>
Co-authored-by: Harald Schilly <harald.schilly@gmail.com>
Co-authored-by: Tristan Schulz <mrdiverlp@gmail.com>
Co-authored-by: Alex Lembcke <alex.lembcke@gmail.com>
Co-authored-by: Viicos <65306057+Viicos@users.noreply.github.com>
Co-authored-by: Václav Blažej <6208643+vaclavblazej@users.noreply.github.com>
Co-authored-by: Václav Blažej <vaclav.blazej@warwick.ac.uk>
Co-authored-by: Jérome Eertmans <jeertmans@icloud.com>
Co-authored-by: Uwe Zimmermann <uwe.zimmermann@sciencetronics.com>
Co-authored-by: Lawrence Qupty <80665382+Lawqup@users.noreply.github.com>
Co-authored-by: JosephD <46393716+jcep@users.noreply.github.com>
Co-authored-by: Francisco Manríquez Novoa <49853152+chopan050@users.noreply.github.com>
Co-authored-by: szchixy <szchixy@outlook.com>
Co-authored-by: Melody Griesen <pikablue107@gmail.com>
Co-authored-by: Melody Griesen <jvgriese@ncsu.edu>
Co-authored-by: yuan <yuan_xin_yu@hotmail.com>
Co-authored-by: Benjamín Ubilla <118409119+MathItYT@users.noreply.github.com>
Co-authored-by: Doaa Muhammad <126016494+doaamuham@users.noreply.github.com>
Co-authored-by: Robin Dimasin <robindimasin@gmail.com>
Co-authored-by: Paul Uhlenbruck <48606747+pauluhlenbruck@users.noreply.github.com>
Co-authored-by: Yash Mundada <F20210001@pilani.bits-pilani.ac.in>
Co-authored-by: TheMathematicFanatic <63360493+TheMathematicFanatic@users.noreply.github.com>
Co-authored-by: Václav Volhejn <8401624+vvolhejn@users.noreply.github.com>
Co-authored-by: Hydromel Victor Doledji <victorvaddely@gmail.com>
Co-authored-by: Dan Davison <dandavison7@gmail.com>
Co-authored-by: Greg Rupp <gmrupp@gmail.com>
Co-authored-by: NotWearingPants <26556598+NotWearingPants@users.noreply.github.com>
Co-authored-by: Sparsh Goenka <43041139+sparshg@users.noreply.github.com>
Co-authored-by: Said Taghadouini <84044788+staghado@users.noreply.github.com>
Co-authored-by: Jason Villanueva <a@jsonvillanueva.com>
Co-authored-by: Abulafia <44573666+abul4fia@users.noreply.github.com>
Co-authored-by: Christian Clauss <cclauss@me.com>
Co-authored-by: Chin Zhe Ning <108804868+biinnnggggg@users.noreply.github.com>
Co-authored-by: HairlessVillager <64526732+HairlessVillager@users.noreply.github.com>
Co-authored-by: Pavel Zwerschke <pavelzw@gmail.com>
Co-authored-by: Sir James Clark Maxwell <71722499+SirJamesClarkMaxwell@users.noreply.github.com>
Co-authored-by: Daniel Zhu <danielfangzhu@gmail.com>
Co-authored-by: Stefano Ottolenghi <stejey@gmail.com>
Co-authored-by: MontroyJosh <122334909+MontroyJosh@users.noreply.github.com>
Co-authored-by: Greg Rupp <greg.rupp@66degrees.com>
Co-authored-by: Amirreza A <45117218+amrear@users.noreply.github.com>
Co-authored-by: Jinchu Li <63861808+JinchuLi2002@users.noreply.github.com>
Co-authored-by: VPC <111203113+VinhPhmCng@users.noreply.github.com>
Co-authored-by: anagorko <3418166+anagorko@users.noreply.github.com>
Co-authored-by: jkjkil4 <52841865+jkjkil4@users.noreply.github.com>
Co-authored-by: yang-tsao <caoyang2005@outlook.com>
Co-authored-by: Eddie Ruiz <eduardo.j.ruiz@gmail.com>
Co-authored-by: Cameron Burdgick <156892808+camburd2@users.noreply.github.com>
This commit is contained in:
adeshpande 2024-06-25 14:51:37 -04:00 committed by GitHub
commit 08264dcf76
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
489 changed files with 12155 additions and 6699 deletions

View file

@ -1 +0,0 @@
<path id="nd" d="m 464.7,68.6 -1.1,2.8 .8,1.4 -.3,5.1 -.5,1.1 2.7,9.1 1.3,2.5 .7,14 1,2.7 -.4,5.8 2.9,7.4 .3,5.8 -.1,2.1 -29.5,-.4 -46,-2.1 -39.2,-2.9 5.2,-66.7 44.5,3.4 55.3,1.6 z">

5
.codespell_ignorewords Normal file
View file

@ -0,0 +1,5 @@
nam
sherif
falsy
medias
strager

View file

@ -1,4 +1,4 @@
[codespell]
exclude-file=.codespell_ignorelines
check-hidden=True
ignore-words-list = nam,sherif,falsy
check-hidden = True
skip = .git,*.js,*.js.map,*.css,*.css.map,*.html,*.po,*.pot,poetry.lock,*.log,*.svg
ignore-words = .codespell_ignorewords

15
.flake8
View file

@ -1,7 +1,8 @@
[flake8]
# Exclude the grpc generated code
exclude = ./manim/grpc/gen/*
max-complexity = 15
exclude = ./manim/grpc/gen/*, __pycache__,.git,
per-file-ignores = __init__.py:F401
max-complexity = 29
max-line-length = 88
statistics = True
# Prevents some flake8-rst-docstrings errors
@ -9,7 +10,7 @@ rst-roles = attr,class,func,meth,mod,obj,ref,doc,exc
rst-directives = manim, SEEALSO, seealso
docstring-convention=numpy
select = A,A00,B,B9,C4,C90,D,E,F,F,PT,RST,SIM,W
select = A,A00,B,B9,C4,C90,D,E,F,F,PT,RST,SIM,W,F401
# General Compatibility
extend-ignore = E203, W503, D202, D212, D213, D404
@ -17,6 +18,9 @@ extend-ignore = E203, W503, D202, D212, D213, D404
# Misc
F401, F403, F405, F841, E501, E731, E402, F811, F821,
# multiple statements on one line (overload)
E704,
# Plug-in: flake8-builtins
A001, A002, A003,
@ -26,9 +30,6 @@ extend-ignore = E203, W503, D202, D212, D213, D404
# Plug-in: flake8-simplify
SIM105, SIM106, SIM119,
# Plug-in: flake8-comprehensions
C901
# Plug-in: flake8-pytest-style
PT001, PT004, PT006, PT011, PT018, PT022, PT023,
@ -40,4 +41,4 @@ extend-ignore = E203, W503, D202, D212, D213, D404
# Plug-in: flake8-rst-docstrings
RST201, RST203, RST210, RST212, RST213, RST215,
RST301, RST303,
RST301, RST303, RST499

2
.git-blame-ignore-revs Normal file
View file

@ -0,0 +1,2 @@
# Switched to ruff format:
24025b60d57301b0a59754c38d77bccd8ed69feb

View file

@ -70,14 +70,5 @@ PASTE HERE
<!-- output of `tlmgr list --only-installed` for TeX Live or a screenshot of the Packages page for MikTeX -->
</details>
<details><summary>FFMPEG</summary>
Output of `ffmpeg -version`:
```
PASTE HERE
```
</details>
## Additional comments
<!-- Add further context that you think might be relevant for this issue here. -->

View file

@ -53,14 +53,5 @@ PASTE HERE
<!-- output of `tlmgr list --only-installed` for TeX Live or a screenshot of the Packages page for MikTeX -->
</details>
<details><summary>FFMPEG</summary>
Output of `ffmpeg -version`:
```
PASTE HERE
```
</details>
## Additional comments
<!-- Add further context that you think might be relevant for this issue here. -->

View file

@ -4,7 +4,10 @@
"standalone",
"preview",
"doublestroke",
"ms",
"count1to",
"multitoc",
"prelim2e",
"ragged2e",
"everysel",
"setspace",
"rsfs",
@ -29,7 +32,10 @@
"standalone",
"preview",
"doublestroke",
"ms",
"count1to",
"multitoc",
"prelim2e",
"ragged2e",
"everysel",
"setspace",
"rsfs",

209
.github/scripts/ci_build_cairo.py vendored Normal file
View file

@ -0,0 +1,209 @@
# Logic is as follows:
# 1. Download cairo source code: https://cairographics.org/releases/cairo-<version>.tar.xz
# 2. Verify the downloaded file using the sha256sums file: https://cairographics.org/releases/cairo-<version>.tar.xz.sha256sum
# 3. Extract the downloaded file.
# 4. Create a virtual environment and install meson and ninja.
# 5. Run meson build in the extracted directory. Also, set required prefix.
# 6. Run meson compile -C build.
# 7. Run meson install -C build.
import hashlib
import logging
import os
import subprocess
import sys
import tarfile
import tempfile
import typing
import urllib.request
from contextlib import contextmanager
from pathlib import Path
from sys import stdout
CAIRO_VERSION = "1.18.0"
CAIRO_URL = f"https://cairographics.org/releases/cairo-{CAIRO_VERSION}.tar.xz"
CAIRO_SHA256_URL = f"{CAIRO_URL}.sha256sum"
VENV_NAME = "meson-venv"
BUILD_DIR = "build"
INSTALL_PREFIX = Path(__file__).parent.parent.parent / "third_party" / "cairo"
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)
def is_ci():
return os.getenv("CI", None) is not None
def download_file(url, path):
logger.info(f"Downloading {url} to {path}")
block_size = 1024 * 1024
with urllib.request.urlopen(url) as response, open(path, "wb") as file:
while True:
data = response.read(block_size)
if not data:
break
file.write(data)
def verify_sha256sum(path, sha256sum):
with open(path, "rb") as file:
file_hash = hashlib.sha256(file.read()).hexdigest()
if file_hash != sha256sum:
raise Exception("SHA256SUM does not match")
def extract_tar_xz(path, directory):
with tarfile.open(path) as file:
file.extractall(directory)
def run_command(command, cwd=None, env=None):
process = subprocess.Popen(command, cwd=cwd, env=env)
process.communicate()
if process.returncode != 0:
raise Exception("Command failed")
@contextmanager
def gha_group(title: str) -> typing.Generator:
if not is_ci():
yield
return
print(f"\n::group::{title}")
stdout.flush()
try:
yield
finally:
print("::endgroup::")
stdout.flush()
def set_env_var_gha(name: str, value: str) -> None:
if not is_ci():
return
env_file = os.getenv("GITHUB_ENV", None)
if env_file is None:
return
with open(env_file, "a") as file:
file.write(f"{name}={value}\n")
stdout.flush()
def get_ld_library_path(prefix: Path) -> str:
# given a prefix, the ld library path can be found at
# <prefix>/lib/* or sometimes just <prefix>/lib
# this function returns the path to the ld library path
# first, check if the ld library path exists at <prefix>/lib/*
ld_library_paths = list(prefix.glob("lib/*"))
if len(ld_library_paths) == 1:
return ld_library_paths[0].absolute().as_posix()
# if the ld library path does not exist at <prefix>/lib/*,
# return <prefix>/lib
ld_library_path = prefix / "lib"
if ld_library_path.exists():
return ld_library_path.absolute().as_posix()
return ""
def main():
if sys.platform == "win32":
logger.info("Skipping build on windows")
return
with tempfile.TemporaryDirectory() as tmpdir:
with gha_group("Downloading and Extracting Cairo"):
logger.info(f"Downloading cairo version {CAIRO_VERSION}")
download_file(CAIRO_URL, os.path.join(tmpdir, "cairo.tar.xz"))
logger.info("Downloading cairo sha256sum")
download_file(CAIRO_SHA256_URL, os.path.join(tmpdir, "cairo.sha256sum"))
logger.info("Verifying cairo sha256sum")
with open(os.path.join(tmpdir, "cairo.sha256sum")) as file:
sha256sum = file.read().split()[0]
verify_sha256sum(os.path.join(tmpdir, "cairo.tar.xz"), sha256sum)
logger.info("Extracting cairo")
extract_tar_xz(os.path.join(tmpdir, "cairo.tar.xz"), tmpdir)
with gha_group("Installing meson and ninja"):
logger.info("Creating virtual environment")
run_command([sys.executable, "-m", "venv", os.path.join(tmpdir, VENV_NAME)])
logger.info("Installing meson and ninja")
run_command(
[
os.path.join(tmpdir, VENV_NAME, "bin", "pip"),
"install",
"meson",
"ninja",
]
)
env_vars = {
# add the venv bin directory to PATH so that meson can find ninja
"PATH": f"{os.path.join(tmpdir, VENV_NAME, 'bin')}{os.pathsep}{os.environ['PATH']}",
}
with gha_group("Building and Installing Cairo"):
logger.info("Running meson setup")
run_command(
[
os.path.join(tmpdir, VENV_NAME, "bin", "meson"),
"setup",
BUILD_DIR,
f"--prefix={INSTALL_PREFIX.absolute().as_posix()}",
"--buildtype=release",
"-Dtests=disabled",
],
cwd=os.path.join(tmpdir, f"cairo-{CAIRO_VERSION}"),
env=env_vars,
)
logger.info("Running meson compile")
run_command(
[
os.path.join(tmpdir, VENV_NAME, "bin", "meson"),
"compile",
"-C",
BUILD_DIR,
],
cwd=os.path.join(tmpdir, f"cairo-{CAIRO_VERSION}"),
env=env_vars,
)
logger.info("Running meson install")
run_command(
[
os.path.join(tmpdir, VENV_NAME, "bin", "meson"),
"install",
"-C",
BUILD_DIR,
],
cwd=os.path.join(tmpdir, f"cairo-{CAIRO_VERSION}"),
env=env_vars,
)
logger.info(f"Successfully built cairo and installed it to {INSTALL_PREFIX}")
if __name__ == "__main__":
if "--set-env-vars" in sys.argv:
with gha_group("Setting environment variables"):
# append the pkgconfig directory to PKG_CONFIG_PATH
set_env_var_gha(
"PKG_CONFIG_PATH",
f"{Path(get_ld_library_path(INSTALL_PREFIX), 'pkgconfig').as_posix()}{os.pathsep}"
f'{os.getenv("PKG_CONFIG_PATH", "")}',
)
set_env_var_gha(
"LD_LIBRARY_PATH",
f"{get_ld_library_path(INSTALL_PREFIX)}{os.pathsep}"
f'{os.getenv("LD_LIBRARY_PATH", "")}',
)
sys.exit(0)
main()

View file

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out a copy of the repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Check whether the citation metadata from CITATION.cff is valid
uses: citation-file-format/cffconvert-github-action@2.0.0

View file

@ -18,23 +18,24 @@ jobs:
env:
DISPLAY: :0
PYTEST_ADDOPTS: "--color=yes" # colors in pytest
PYTHONIOENCODING: "utf8"
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, macos-latest, windows-latest]
python: ["3.8", "3.9", "3.10", "3.11"]
os: [ubuntu-22.04, macos-13, windows-latest]
python: ["3.9", "3.10", "3.11", "3.12"]
steps:
- name: Checkout the repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install Poetry
run: |
pipx install "poetry==1.5.*"
pipx install "poetry==1.7.*"
poetry config virtualenvs.prefer-active-python true
- name: Setup Python ${{ matrix.python }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
cache: "poetry"
@ -50,22 +51,16 @@ jobs:
run: |
echo "date=$(/bin/date -u "+%m%w%Y")" >> $GITHUB_OUTPUT
- name: Install and cache ffmpeg (all OS)
uses: FedericoCarboni/setup-ffmpeg@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
id: setup-ffmpeg
- name: Install system dependencies (Linux)
if: runner.os == 'Linux'
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: python3-opengl libpango1.0-dev xvfb
packages: python3-opengl libpango1.0-dev xvfb freeglut3-dev
version: 1.0
- name: Install Texlive (Linux)
if: runner.os == 'Linux'
uses: teatimeguest/setup-texlive-action@v2
uses: teatimeguest/setup-texlive-action@v3
with:
cache: true
packages: scheme-basic fontspec inputenc fontenc tipa mathrsfs calligra xcolor standalone preview doublestroke ms everysel setspace rsfs relsize ragged2e fundus-calligra microtype wasysym physics dvisvgm jknapltx wasy cm-super babel-english gnu-freefont mathastext cbfonts-fd xetex
@ -76,8 +71,24 @@ jobs:
# start xvfb in background
sudo /usr/bin/Xvfb $DISPLAY -screen 0 1280x1024x24 &
- name: Setup Cairo Cache
uses: actions/cache@v4
id: cache-cairo
if: runner.os == 'Linux' || runner.os == 'macOS'
with:
path: ${{ github.workspace }}/third_party
key: ${{ runner.os }}-dependencies-cairo-${{ hashFiles('.github/scripts/ci_build_cairo.py') }}
- name: Build and install Cairo (Linux and macOS)
if: (runner.os == 'Linux' || runner.os == 'macOS') && steps.cache-cairo.outputs.cache-hit != 'true'
run: python .github/scripts/ci_build_cairo.py
- name: Set env vars for Cairo (Linux and macOS)
if: runner.os == 'Linux' || runner.os == 'macOS'
run: python .github/scripts/ci_build_cairo.py --set-env-vars
- name: Setup macOS cache
uses: actions/cache@v3
uses: actions/cache@v4
id: cache-macos
if: runner.os == 'macOS'
with:
@ -103,10 +114,6 @@ jobs:
export PATH="$oriPath"
echo "Completed TinyTeX"
- name: Install cairo (MacOS)
if: runner.os == 'macOS'
run: brew install cairo
- name: Add macOS dependencies to PATH
if: runner.os == 'macOS'
shell: bash
@ -118,12 +125,12 @@ jobs:
- name: Setup Windows cache
id: cache-windows
if: runner.os == 'Windows'
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ github.workspace }}\ManimCache
key: ${{ runner.os }}-dependencies-tinytex-${{ hashFiles('.github/manimdependency.json') }}-${{ steps.cache-vars.outputs.date }}-1
- uses: ssciwr/setup-mesa-dist-win@v1
- uses: ssciwr/setup-mesa-dist-win@v2
- name: Install system dependencies (Windows)
if: runner.os == 'Windows' && steps.cache-windows.outputs.cache-hit != 'true'
@ -131,7 +138,7 @@ jobs:
$tinyTexPackages = $(python -c "import json;print(' '.join(json.load(open('.github/manimdependency.json'))['windows']['tinytex']))") -Split ' '
$OriPath = $env:PATH
echo "Install Tinytex"
Invoke-WebRequest "https://github.com/yihui/tinytex-releases/releases/download/daily/TinyTeX-1.zip" -O "$($env:TMP)\TinyTex.zip"
Invoke-WebRequest "https://github.com/yihui/tinytex-releases/releases/download/daily/TinyTeX-1.zip" -OutFile "$($env:TMP)\TinyTex.zip"
Expand-Archive -LiteralPath "$($env:TMP)\TinyTex.zip" -DestinationPath "$($PWD)\ManimCache\LatexWindows"
$env:Path = "$($PWD)\ManimCache\LatexWindows\TinyTeX\bin\windows;$($env:PATH)"
tlmgr update --self

View file

@ -24,19 +24,19 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql.yml
queries: +security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"

View file

@ -13,19 +13,19 @@ jobs:
if: github.event_name != 'release'
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
platforms: linux/arm64,linux/amd64
push: true
@ -38,13 +38,13 @@ jobs:
if: github.event_name == 'release'
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@ -61,7 +61,7 @@ jobs:
print(f"tag_name={ref_tag}", file=f)
- name: Build and push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
platforms: linux/arm64,linux/amd64
push: true

View file

@ -8,12 +8,12 @@ jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: 3.9
python-version: 3.11
- name: Install dependencies
run: python -m pip install --upgrade poetry
@ -30,7 +30,7 @@ jobs:
poetry build
- name: Store artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
path: dist/*.tar.gz
name: manim.tar.gz

View file

@ -0,0 +1,85 @@
name: Publish downloadable documentation
on:
release:
types: [released]
workflow_dispatch:
jobs:
build-and-publish-htmldocs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: 3.11
- name: Install system dependencies
run: |
sudo apt update && sudo apt install -y \
pkg-config libcairo-dev libpango1.0-dev wget fonts-roboto
wget -qO- "https://yihui.org/tinytex/install-bin-unix.sh" | sh
echo ${HOME}/.TinyTeX/bin/x86_64-linux >> $GITHUB_PATH
- name: Install LaTeX and Python dependencies
run: |
tlmgr update --self
tlmgr install \
babel-english ctex doublestroke dvisvgm frcursive fundus-calligra jknapltx \
mathastext microtype physics preview ragged2e relsize rsfs setspace standalone \
wasy wasysym
python -m pip install --upgrade poetry
poetry install
- name: Build and package documentation
run: |
cd docs/
poetry run make html
cd build/html/
tar -czvf ../html-docs.tar.gz *
- name: Store artifacts
uses: actions/upload-artifact@v4
with:
path: ${{ github.workspace }}/docs/build/html-docs.tar.gz
name: html-docs.tar.gz
- name: Install Dependency
run: pip install requests
- name: Get Upload URL
if: github.event == 'release'
id: create_release
shell: python
env:
access_token: ${{ secrets.GITHUB_TOKEN }}
tag_act: ${{ github.ref }}
run: |
import requests
import os
ref_tag = os.getenv('tag_act').split('/')[-1]
access_token = os.getenv('access_token')
headers = {
"Accept":"application/vnd.github.v3+json",
"Authorization": f"token {access_token}"
}
url = f"https://api.github.com/repos/ManimCommunity/manim/releases/tags/{ref_tag}"
c = requests.get(url,headers=headers)
upload_url=c.json()['upload_url']
with open(os.getenv('GITHUB_OUTPUT'), 'w') as f:
print(f"upload_url={upload_url}", file=f)
print(f"tag_name={ref_tag[1:]}", file=f)
- name: Upload Release Asset
if: github.event == 'release'
id: upload-release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ github.workspace }}/docs/build/html-docs.tar.gz
asset_name: manim-htmldocs-${{ steps.create_release.outputs.tag_name }}.tar.gz
asset_content_type: application/gzip

3
.gitignore vendored
View file

@ -131,3 +131,6 @@ dist/
/media_dir.txt
# ^TODO: Remove the need for this with a proper config file
# Ignore the built dependencies
third_party/*

View file

@ -1,91 +0,0 @@
[mypy]
show_error_codes = True
# ignore most files; should be checked once proper types have been implemented
[mypy-manim.__main__]
ignore_errors = True
[mypy-manim.camera.*]
ignore_errors = True
[mypy-manim.scene.*]
ignore_errors = True
[mypy-manim.cli.cfg.*]
ignore_errors = True
[mypy-manim.mobject.*]
ignore_errors = True
[mypy-manim._config.*]
ignore_errors = True
[mypy-manim.utils.*]
ignore_errors = True
[mypy-manim.utils.color]
ignore_errors = False
[mypy-manim.animation.*]
ignore_errors = True
# ---------------- We can't properly type this ------------------------
[mypy-manim.grpc.*]
ignore_errors = True
# ---------------- Stubless imported Modules --------------------------
# We should be able to create stubs for this or type hint it
[mypy-manimpango]
ignore_missing_imports = True
# Has stubs in 3.8
[mypy-numpy]
ignore_missing_imports = True
# Has stubs in 3.8
[mypy-pydub]
ignore_missing_imports = True
[mypy-matplotlib]
ignore_missing_imports = True
[mypy-scipy.*]
ignore_missing_imports = True
[mypy-networkx]
ignore_missing_imports = True
[mypy-git]
ignore_missing_imports = True
[mypy-moderngl.*]
ignore_missing_imports = True
[mypy-moderngl_window.*]
ignore_missing_imports = True
[mypy-colour]
ignore_missing_imports = True
[mypy-dearpygui.*]
ignore_missing_imports = True
[mypy-screeninfo]
ignore_missing_imports = True
[mypy-IPython.*]
ignore_missing_imports = True
[mypy-watchdog.*]
ignore_missing_imports = True
[mypy-tqdm]
ignore_missing_imports = True
[mypy-mapbox_earcut]
ignore_missing_imports = True
[mypy-click_default_group]
ignore_missing_imports = True

View file

@ -3,7 +3,7 @@ fail_fast: false
exclude: ^(manim/grpc/gen/|docs/i18n/)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.6.0
hooks:
- id: check-ast
name: Validate Python
@ -12,39 +12,22 @@ repos:
- id: end-of-file-fixer
- id: check-toml
name: Validate Poetry
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
name: isort (python)
- id: isort
name: isort (cython)
types: [cython]
- id: isort
name: isort (pyi)
types: [pyi]
- repo: https://github.com/asottile/pyupgrade
rev: v3.10.1
hooks:
- id: pyupgrade
name: Update code to new python versions
args: [--py37-plus]
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
hooks:
- id: python-check-blanket-noqa
name: Precision flake ignores
- repo: https://github.com/psf/black
rev: 23.7.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.9
hooks:
- id: black
- repo: https://github.com/asottile/blacken-docs
rev: 1.15.0
hooks:
- id: blacken-docs
additional_dependencies: [black==22.3.0]
- id: ruff
name: ruff lint
types: [python]
args: [--exit-non-zero-on-fix]
- id: ruff-format
types: [python]
- repo: https://github.com/PyCQA/flake8
rev: 6.1.0
rev: 7.1.0
hooks:
- id: flake8
additional_dependencies:
@ -58,7 +41,7 @@ repos:
flake8-simplify==0.14.1,
]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.4.1
rev: v1.10.0
hooks:
- id: mypy
additional_dependencies:
@ -69,9 +52,10 @@ repos:
types-requests,
types-setuptools,
]
files: ^manim/
- repo: https://github.com/codespell-project/codespell
rev: v2.2.5
rev: v2.3.0
hooks:
- id: codespell
files: ^.*\.(py|md|rst)$

View file

@ -3,11 +3,10 @@ build:
os: ubuntu-22.04
tools:
python: "3.10"
python: "3.11"
apt_packages:
- libpango1.0-dev
- ffmpeg
- graphviz
python:

View file

@ -4,10 +4,10 @@ authors:
-
name: "The Manim Community Developers"
cff-version: "1.2.0"
date-released: 2023-04-06
date-released: 2024-04-28
license: MIT
message: "We acknowledge the importance of good software to support research, and we note that research becomes more valuable when it is communicated effectively. To demonstrate the value of Manim, we ask that you cite Manim in your work."
title: Manim Mathematical Animation Framework
url: "https://www.manim.community/"
version: "v0.17.3"
version: "v0.18.1"
...

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021, the Manim Community Developers
Copyright (c) 2024, the Manim Community Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -5,12 +5,7 @@
from __future__ import annotations
try:
# https://github.com/moderngl/moderngl/issues/517
import readline # required to prevent a segfault on Python 3.10
except ModuleNotFoundError: # windows
pass
import cairo
import moderngl
# If it is running Doctest the current directory
@ -39,6 +34,7 @@ def pytest_report_header(config):
info = ctx.info
ctx.release()
return (
f"\nCairo Version: {cairo.cairo_version()}",
"\nOpenGL information",
"------------------",
f"vendor: {info['GL_VENDOR'].strip()}",

View file

@ -1,8 +1,7 @@
FROM python:3.8-slim
FROM python:3.11-slim
RUN apt-get update -qq \
&& apt-get install --no-install-recommends -y \
ffmpeg \
build-essential \
gcc \
cmake \

View file

@ -202,7 +202,7 @@ msgid "This ``Scene`` illustrates the quirks of ``.animate``. When using ``.anim
msgstr ""
#: ../../source/tutorials/quickstart.rst:344
msgid "In ``DifferentRotations``, the difference between ``.animate``'s interpretation of rotation and the ``Rotate`` method is far more apparent. The starting and ending states of a ``Mobject`` rotated 360 degrees are the same, so ``.animate`` tries to interpolate two identical objects and the result is the left square. If you find that your own usage of ``.animate`` is causing similar unwanted behavior, consider using conventional animation methods like the right square, which uses ``Rotate``."
msgid "In ``DifferentRotations``, the difference between ``.animate``'s interpretation of rotation and the ``Rotate`` method is far more apparent. The starting and ending states of a ``Mobject`` rotated 180 degrees are the same, so ``.animate`` tries to interpolate two identical objects and the result is the left square. If you find that your own usage of ``.animate`` is causing similar unwanted behavior, consider using conventional animation methods like the right square, which uses ``Rotate``."
msgstr ""
#: ../../source/tutorials/quickstart.rst:353

View file

@ -1,5 +1,5 @@
furo
myst-parser
sphinx<5.1
sphinx>=7.3
sphinx-copybutton
sphinxext-opengraph

0
docs/skip-manim Normal file
View file

View file

@ -82,3 +82,22 @@ h4, h5, h6{
.sidebar-tree a.internal.reference {
display: table-cell;
}
.manim-binder-button {
text-transform: capitalize;
padding: 10px 20px;
margin: 10px 0;
}
.manim-binder-wrapper {
background-color: var(--color-code-background);
color: var(--color-code-foreground);
}
.manim-binder-title {
margin-top: 0;
}
.manim-binder-button-wrapper {
margin: 0px 10px;
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,6 @@
/*!
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
*
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*/

File diff suppressed because one or more lines are too long

View file

@ -4,16 +4,9 @@
.. automodule:: {{ fullname }}
{% block attributes %}
{% if attributes %}
.. rubric:: Module Attributes
.. autosummary::
{% for item in attributes %}
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}
{# SEE manim.utils.docbuild.autoaliasattr_directive #}
{# FOR INFORMATION ABOUT THE CUSTOM autoaliasattr DIRECTIVE! #}
.. autoaliasattr:: {{ fullname }}
{% block classes %}
{% if classes %}

View file

@ -2,9 +2,14 @@
Changelog
#########
This page contains a list of changes made between releases. Changes
from versions that are not listed below (in particular patch-level
releases since v0.18.0) are documented on our
`GitHub release page <https://github.com/ManimCommunity/manim/releases/>`__.
.. toctree::
changelog/0.18.0-changelog
changelog/0.17.3-changelog
changelog/0.17.2-changelog
changelog/0.17.1-changelog

View file

@ -0,0 +1,294 @@
*******
v0.18.0
*******
:Date: November 11, 2023
Contributors
============
A total of 41 people contributed to this
release. People with a '+' by their names authored a patch for the first
time.
* Abulafia +
* Adhyyan Sekhsaria +
* Adrien Ludwig +
* Alex Kempen +
* Andres Berejnoi +
* Anousheh Moonen +
* Benjamin Hackl
* Francisco Manríquez Novoa
* Harald Schilly +
* Immanuel-Alvaro-Bhirawa +
* Jason Grace +
* Jason Villanueva
* Jinchu Li
* John Lynch +
* Jérome Eertmans
* Matt Turner +
* Narahari Rao +
* Naveen M K
* Nikhil Iyer +
* Ron Li +
* Sujal Singh +
* Tristan Schulz
* Uwe Zimmermann +
* Václav Blažej +
* Zachary Winkeler +
The patches included in this release have been reviewed by
the following contributors.
* Alex Lembcke
* Andres Berejnoi
* Axel
* Benjamin Hackl
* Francisco Manríquez Novoa
* Immanuel-Alvaro-Bhirawa
* Jan-Hendrik Müller
* Jason Grace
* Jason Villanueva
* Jinchu Li
* John Lynch
* Jérome Eertmans
* Kevin Lubick
* Narahari Rao
* Naveen M K
* NotWearingPants
* SsNiPeR1
* TheMathematicFanatic
* Tristan Schulz
* Uwe Zimmermann
* Viicos
* icedcoffeeee
Pull requests merged
====================
A total of 59 pull requests were merged for this release.
Breaking changes
----------------
* :pr:`3020`: Rewrote Manim's color system
This change removed the ``colour`` library as a dependency
of Manim and replaced the internal handling of colors with
the newly added :class:`.ManimColor`. This also adds hundreds
of new predefined colors, see :mod:`.utils.color` for more
details.
This should only be a breaking change if you have interacted
directly with the ``colour`` module before. The general interface
has been kept stable.
Highlights
----------
* :pr:`3299`: Added new ``manim checkhealth`` CLI subcommand
This adds a new command line interface subcommand which can be used to check
whether a local installation of Manim has been configured correctly, and all
required (and optional) dependencies are available. To try it, run it via
``manim checkhealth`` or ``python -m manim checkhealth``.
* :pr:`3427`: New feature: rendered examples in documentation can now be run directly via binder
This adds a "Make interactive" button below the examples in our documentation
that establishes a connection to binder such that examples can be modified and
rerendered directly from your browser.
* :pr:`3086`: Introduced a new module :mod:`.typing` for type hints
This also adds various type hints to integral parts of the code base.
* :pr:`3322`: Implemented auto-removal of auxiliary LaTeX files, enabled by default
This automatically removes auxiliary files creating during the compilation of
LaTeX documents like ``.aux`` or ``.dvi`` files. This behavior can be controlled
via the newly introduced ``no_latex_cleanup`` config key (``False`` by default).
On the command line, the autoremoval can be disabled via the ``--no_latex_cleanup``
CLI flag.
* :pr:`3395`: Added support for Python 3.12
New features
------------
* :pr:`3361`: Added three new rate functions
This adds the rate functions :func:`.smoothstep`, :func:`.smootherstep`,
:func:`.smoothererstep` based on the SmoothStep sigmoid functions.
* :pr:`3264`: Added new mobjects :class:`.LabeledLine` and :class:`.LabeledArrow`
Enhancements
------------
* :pr:`3190`: Made :class:`.CurvesAsSubmobjects` mobjects compatible with :meth:`.input_to_graph_point`
* :pr:`3226`: Avoid using a mobject as a default argument of :class:`.ArcBrace`
* :pr:`3366`: Added spacing between values and unit in :class:`.DecimalNumber`
This adds the new keyword argument ``unit_buff_per_font_unit`` (default: 0, for
backwards compatibility). Setting it to some positive number creates additional
space between the numeric value and the displayed unit.
Fixed bugs
----------
* :pr:`3205`: Fixed type hint of ``angle`` in :class:`.Arc`
* :pr:`3210`: Fixed :class:`.DecimalNumber` with ``show_ellipsis=True`` with the OpenGL renderer
* :pr:`3211`: Fixed display issues with custom labels for :class:`.Axes` with the OpenGL renderer
* :pr:`3298`: Fixed expand animation for :class:`.ManimBanner`
* :pr:`3306`: Fixed IPython terminal history and embedded shell instantiation for scenes using :meth:`.Scene.interactive_embed`
* :pr:`3315`: Fixed issue with parameter types in :meth:`.Scene.add_subcaption`
* :pr:`3423`: Fixed incorrect submobject count of multi-part :class:`.Tex` mobjects
This resolves various issues where formulas were not displayed completely,
like it was the case with ``MathTex("1", "^{", "0")``.
* :pr:`3284`: Fixed ``LinearTransformationSceneExample`` in Jupyter notebooks
* :pr:`3302`: Fixed typo in comparison in :meth:`.OpenGLVMobject.interpolate`
* :pr:`3340`: Fixed incorrect computation of bounding box for rotated :class:`.ImageMobject`
* :pr:`3343`: Fixed return value of :meth:`.TexTemplate.add_to_preamble` and :meth:`.TexTemplate.add_to_document`
* :pr:`3282`: Ensure that :meth:`.ArrowVectorField.get_vector` does not modify the passed inputs
* :pr:`3392`: Fixed behavior of elongated tick lines for :class:`.NumberLine`
* :pr:`3430`: Fixed CSV reader adding empty lists in rendering summary during documentation build
* :pr:`3404`: Properly raise an exception on empty inputs to :class:`.AddTextLetterByLetter`
Documentation-related changes
-----------------------------
* :pr:`3219`: Enabled social cards for links to documentation
* :pr:`3274`: Replaced incorrect mentions of Python 3.7 as the minimally required version
* :pr:`3297`: Improved arrow tip sowcase example for :class:`.ArrowTip`
* :pr:`3312`: Added documentation for :func:`.always_redraw`
* :pr:`3218`: Improved grammar in the :doc:`deep dive guide </guides/deep_dive>`
* :pr:`3251`: Add LaTeX installation instructions for Fedora
* :pr:`3290`: Updated required dependencies for MacOS installations
* :pr:`3325`: Added documentation for functions in :mod:`.mobject_update_utils`
This adds docstrings and typehints to :func:`.always_rotate`,
:func:`.always_shift`, :func:`.turn_animation_into_updater`
* :pr:`3353`: Added documentation for :meth:`.Mobject.center`
* :pr:`3355`: Temporarily enabled ``htmlzip`` build on ReadTheDocs
* :pr:`3377`: Fixed a typo in the :doc:`deep dive guide </guides/deep_dive>`
* :pr:`3389`: Removed superfluous curly braces in a LaTeX expression
* :pr:`3417`: Replaced ``htmlzip`` ReadTheDocs build with workflow attaching downloadable documentation to GitHub releases
Changes concerning the testing system
-------------------------------------
* :pr:`3416`: Fixed tests to run on Cairo 1.18.0
* :pr:`3257`: Fix a configuration error concerning poetry
* :pr:`3419`: Fixed caching of Cairo builds on CI runners
Code quality improvements and similar refactors
-----------------------------------------------
* :pr:`3229`: Made docbuild errors easier to debug and fixed error from changed exception class
* :pr:`3231`: Fixed errors reported by ``flake8``
* :pr:`3232`: Upgrade ReadTheDocs build environment to use newer image
* :pr:`3286`: Optimized :meth:`.Axes.coords_to_point`
* :pr:`3224`: Replace final few occurrences of ``os.path`` by ``pathlib.Path``
* :pr:`3236`: Return self in :meth:`.AbstractImageMobject.set_resampling_algorithm`
* :pr:`3253`: Bump tornado from 6.3.1 to 6.3.2
* :pr:`3272`: Bump docker/build-push-action from 3 to 4
* :pr:`3287`: Bump cryptography from 41.0.1 to 41.0.2
* :pr:`3350`: Added missing dependency ``typing-extensions``
* :pr:`3431`: Bump teatimeguest/setup-texlive-action from 2 to 3
* :pr:`3433`: Bump dependencies
* :pr:`3399`: Updated several dependencies
* :pr:`3397`: Several GitHub actions updates
* :pr:`3405`: Updated manimpango version to fix error regarding type strictness
* :pr:`3421`: Improved order of input checks when creating a tree graph
New releases
------------
* :pr:`3439`: Prepared new release: v0.18.0

View file

@ -176,7 +176,7 @@ Fixed bugs
* :pr:`1782`: Fixed :class:`~.Tex` not working properly with the OpenGL renderer
* :pr:`1783`: Fixed :meth:`~.OpenGLMobject.shuffle` function and added :meth:`~.invert` to OpenGL
* :pr:`1783`: Fixed :meth:`~.OpenGLMobject.shuffle` function and added :meth:`~.Mobject.invert` to OpenGL
* :pr:`1786`: Fixed :class:`~.DecimalNumber` not working properly when the number of digits changes

View file

@ -8,9 +8,11 @@ from __future__ import annotations
import os
import sys
from datetime import datetime
from pathlib import Path
import manim
from manim.utils.docbuild.module_parsing import parse_module_attributes
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
@ -24,7 +26,7 @@ sys.path.insert(0, os.path.abspath("."))
# -- Project information -----------------------------------------------------
project = "Manim"
copyright = "2020-2022, The Manim Community Dev Team"
copyright = f"2020-{datetime.now().year}, The Manim Community Dev Team"
author = "The Manim Community Dev Team"
@ -44,6 +46,7 @@ extensions = [
"sphinxext.opengraph",
"manim.utils.docbuild.manim_directive",
"manim.utils.docbuild.autocolor_directive",
"manim.utils.docbuild.autoaliasattr_directive",
"sphinx.ext.graphviz",
"sphinx.ext.inheritance_diagram",
"sphinxcontrib.programoutput",
@ -54,7 +57,14 @@ extensions = [
autosummary_generate = True
# generate documentation from type hints
ALIAS_DOCS_DICT = parse_module_attributes()[0]
autodoc_typehints = "description"
autodoc_type_aliases = {
alias_name: f"~manim.{module}.{alias_name}"
for module, module_dict in ALIAS_DOCS_DICT.items()
for category_dict in module_dict.values()
for alias_name in category_dict.keys()
}
autoclass_content = "both"
# controls whether functions documented by the autofunction directive
@ -172,8 +182,6 @@ inheritance_edge_attrs = {
"penwidth": 1,
}
html_js_files = [
"responsiveSvg.js",
]
html_js_files = ["responsiveSvg.js"]
graphviz_output_format = "svg"

View file

@ -38,14 +38,10 @@ To get an overview of what our community is currently working on, check out
Contributing can be confusing, so here are a few guides:
.. toctree::
:maxdepth: 2
:maxdepth: 3
contributing/development
contributing/docstrings
contributing/references
contributing/examples
contributing/typings
contributing/admonitions
contributing/docs
contributing/testing
contributing/performance
contributing/internationalization

View file

@ -51,8 +51,8 @@ For first-time contributors
#. Install Manim:
- Follow the steps in our :doc:`installation instructions
<../installation>` to install **Manim's dependencies**,
primarily ``ffmpeg`` and ``LaTeX``.
<../installation>` to install **Manim's system dependencies**.
We also recommend installing a LaTeX distribution.
- We recommend using `Poetry <https://python-poetry.org>`__ to manage your
developer installation of Manim. Poetry is a tool for dependency
@ -62,7 +62,7 @@ For first-time contributors
managing virtual environments.
If you choose to use Poetry as well, follow `Poetry's installation
guidelines <https://python-poetry.org/docs/master/#installation>`__
guidelines <https://python-poetry.org/docs/master/#installing-with-pipx>`__
to install it on your system, then run ``poetry install`` from
your cloned repository. Poetry will then install Manim, as well
as create and enter a virtual environment. You can always re-enter
@ -147,7 +147,7 @@ Develop your contribution
Update the docstrings (the text in triple quotation marks) of any functions
or classes you change and include them with any new functions you add.
See the :doc:`documentation guide <docstrings>` for more information about how we
See the :doc:`documentation guide <docs/docstrings>` for more information about how we
prefer our code to be documented. The content of the docstrings will be
rendered in the :doc:`reference manual <../reference>`.
@ -159,6 +159,8 @@ Develop your contribution
As far as development on your local machine goes, these are the main steps you
should follow.
.. _polishing-changes-and-submitting-a-pull-request:
Polishing Changes and Submitting a Pull Request
-----------------------------------------------
@ -243,7 +245,8 @@ sticks to our coding conventions.
a look at the built HTML files to see whether the formatting of the documentation
you added looks as you intended. You can build the documentation locally
by running ``make html`` from the ``docs`` directory. Make sure you have `Graphviz <https://graphviz.org/>`_
installed locally in order to build the inheritance diagrams.
installed locally in order to build the inheritance diagrams. See :doc:`docs` for
more information.
Finally, if the pipeline passes and you are satisfied with your changes: wait for
feedback and iterate over any requested changes. You will likely be asked to

View file

@ -0,0 +1,83 @@
====================
Adding Documentation
====================
Building the documentation
--------------------------
When you clone the Manim repository from GitHub, you can access the
``docs/`` folder which contains the necessary files to build the
documentation.
To build the docs locally, open a CLI, enter the ``docs/`` folder with the
``cd`` command and execute the following depending on your OS:
- Windows: ``./make.bat html``
- macOS and Linux: ``make html``
The first time you build the docs, the process will take several
minutes because it needs to generate all the ``.rst`` (reST:
reStructured Text) files from scratch by reading and parsing all the
Manim content. The process becomes much shorter the next time, as it
rebuilds only the parts which have changed.
Sphinx library and extensions
-----------------------------
Manim uses `Sphinx <https://www.sphinx-doc.org>`_ for building the
docs. It also makes use of Sphinx extensions such as:
- `Autodoc: <https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html>`_
imports Manim's Python source code, extracts its docstrings and
generates documentation from them.
- `Autosummary: <https://www.sphinx-doc.org/en/master/usage/extensions/autosummary.html>`_
a complement to Autodoc which adds a special directive ``autosummary``,
used in Manim to automatically document classes, methods,
attributes, functions, module-level variables and exceptions.
Autosummary makes use of `Jinja templates <https://jinja.palletsprojects.com/templates/>`_,
which Manim defines for autosummarizing classes and modules
inside ``docs/source/_templates/``.
- `Graphviz extension for Sphinx: <https://www.sphinx-doc.org/en/master/usage/extensions/graphviz.html>`_
embeds graphs generated by the `Graphviz <https://graphviz.org/>`_
module, which must be installed in order to render the
inheritance diagrams in the :doc:`/reference`.
- `Napoleon: <https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html>`_
enables Sphinx to read Google style docstrings and, in
particular for Manim, `NumPy style docstrings <https://numpydoc.readthedocs.io/en/latest/format.html>`_
- see :doc:`docs/docstrings` for more information.
Sphinx theme
------------
The theme used for this website is `Furo <https://sphinx-themes.org/sample-sites/furo/>`_.
Custom Sphinx directives
------------------------
Manim implements **custom directives** for use with Autodoc and Autosummary, which
are defined in :mod:`~.docbuild`:
.. currentmodule:: manim.utils.docbuild
.. autosummary::
:toctree: ../reference
autoaliasattr_directive
autocolor_directive
manim_directive
Index
-----
.. toctree::
:maxdepth: 2
docs/admonitions
docs/docstrings
docs/examples
docs/references
docs/typings

View file

@ -77,8 +77,7 @@ Example:
The mobject linked to this instance.
"""
def __init__(name: str, id: int, singleton: MyClass, mobj: Mobject = None):
...
def __init__(name: str, id: int, singleton: MyClass, mobj: Mobject = None): ...
2. The usage of ``Parameters`` on functions to specify how
every parameter works and what it does. This should be excluded if

View file

@ -0,0 +1,148 @@
==============
Adding Typings
==============
.. warning::
This section is still a work in progress.
Adding type hints to functions and parameters
---------------------------------------------
Manim is currently in the process of adding type hints into the library. In this
section, you will find information about the standards used and some general
guidelines.
If you've never used type hints before, this is a good place to get started:
https://realpython.com/python-type-checking/#hello-types.
Typing standards
~~~~~~~~~~~~~~~~
Manim uses `mypy`_ to type check its codebase. You will find a list of configuration values in the ``mypy.ini`` configuration file.
To be able to use the newest typing features not available in the lowest
supported Python version, make use of `typing_extensions`_.
To be able to use the new Union syntax (``|``) and builtins subscripting, use
the ``from __future__ import annotations`` import.
.. _mypy: https://mypy-lang.org/
.. _typing_extensions: https://pypi.org/project/typing-extensions/
Typing guidelines
~~~~~~~~~~~~~~~~~
* Manim has a dedicated :mod:`~.typing` module where type aliases are provided.
Most of them may seem redundant, in particular the ones related to ``numpy``.
This is in anticipation of the support for shape type hinting
(`related issue <https://github.com/numpy/numpy/issues/16544>`_). Besides the
pending shape support, using the correct type aliases will help users understand
which shape should be used.
* For typings of generic collections, check out `this <https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes>`_
link.
* Always use a type hint of ``None`` for functions that does not return
a value (this also applies to ``__init__``), e.g.:
.. code:: py
def height(self, value) -> None:
self.scale_to_fit_height(value)
* For variables representing paths, use the ``StrPath`` or ``StrOrBytesPath``
type alias defined in the :mod:`~.typing` module.
* ``*args`` and ``**kwargs`` shouldn't be left untyped (in most cases you can
use ``Any``).
* Following `PEP 484 <https://peps.python.org/pep-0484/#the-numeric-tower>`_,
use ``float`` instead of ``int | float``.
* Use ``x | y`` instead of ``Union[x, y]``
* Mobjects have the typehint ``Mobject``, e.g.:
.. code:: py
def match_color(self, mobject: "Mobject"):
"""Match the color with the color of another :class:`~.Mobject`."""
return self.set_color(mobject.get_color())
* Always parametrize generics (``list[int]`` instead of ``list``,
``type[Any]`` instead of ``type``, etc.). This also applies to callables.
.. code:: py
rate_func: Callable[[float], float] = lambda t: smooth(1 - t)
* Use ``TypeVar`` when you want to "link" type hints as being the same type.
Consider ``Mobject.copy``, which returns a new instance of the same class.
It would be type-hinted as:
.. code:: py
T = TypeVar("T")
def copy(self: T) -> T: ...
* Use ``typing.Iterable`` whenever the function works with *any* iterable, not a specific type.
* Prefer ``numpy.typing.NDArray`` over ``numpy.ndarray``
.. code:: py
import numpy as np
if TYPE_CHECKING:
import numpy.typing as npt
def foo() -> npt.NDArray[float]:
return np.array([1, 0, 1])
* If a method returns ``self``, use ``typing_extensions.Self``.
.. code:: py
if TYPE_CHECKING:
from typing_extensions import Self
class CustomMobject:
def set_color(self, color: ManimColor) -> Self:
...
return self
* If the function returns a container of a specific length each time, consider using ``tuple`` instead of ``list``.
.. code:: py
def foo() -> tuple[float, float, float]:
return (0, 0, 0)
* If a function works with a parameter as long as said parameter has a ``__getitem__``, ``__iter___`` and ``__len__`` method,
the typehint of the parameter should be ``collections.abc.Mapping``. If it also supports ``__setitem__`` and/or ``__delitem__``, it
should be marked as ``collections.abc.MutableMapping``.
* Typehinting something as ``object`` means that only attributes available on every Python object should be accessed,
like ``__str__`` and so on. On the other hand, literally any attribute can be accessed on a variable with the ``Any`` typehint -
it's more freeing than the ``object`` typehint, and makes mypy stop typechecking the variable. Note that whenever possible,
try to keep typehints as specific as possible.
* If objects are imported purely for type hint purposes, keep it under an ``if typing.TYPE_CHECKING`` guard, to prevent them from
being imported at runtime (helps library performance). Do not forget to use the ``from __future__ import annotations`` import to avoid having runtime ``NameError`` exceptions.
.. code:: py
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from manim.typing import Vector3D
# type stuff with Vector3D
Missing Sections for typehints are:
-----------------------------------
* Mypy and numpy import errors: https://realpython.com/python-type-checking/#running-mypy
* Explain ``mypy.ini`` (see above link)

View file

@ -28,7 +28,7 @@ Contributing
That being said, improving the documentation and making it more accessible is still highly encouraged.
And even if your work gets outdated and requires change, you or someone else can simply adjust the translation.
Your efforts are not in vail!
Your efforts are not in vain!
Voting

View file

@ -5,6 +5,24 @@ If you are adding new features to manim, you should add appropriate tests for th
manim from breaking at each change by checking that no other
feature has been broken and/or been unintentionally modified.
.. warning::
The full tests suite requires Cairo 1.18 in order to run all tests.
However, Cairo 1.18 may not be available from your package manager,
like ``apt``, and it is very likely that you have an older version installed,
e.g., 1.16. If you run tests with a version prior to 1.18,
many tests will be skipped. Those tests are not skipped in the online CI.
If you want to run all tests locally, you need to install Cairo 1.18 or above.
You can do so by compiling Cairo from source:
1. download ``cairo-1.18.0.tar.xz`` from
`here <https://www.cairographics.org/releases/>`_.
and uncompress it;
2. open the INSTALL file and follow the instructions (you might need to install
``meson`` and ``ninja``);
3. run the tests suite and verify that the Cairo version is correct.
How Manim tests
---------------

View file

@ -1,103 +0,0 @@
==============
Adding Typings
==============
Adding type hints to functions and parameters
---------------------------------------------
.. warning::
This section is still a work in progress.
If you've never used type hints before, this is a good place to get started:
https://realpython.com/python-type-checking/#hello-types.
When adding type hints to manim, there are some guidelines that should be followed:
* Coordinates have the typehint ``Sequence[float]``, e.g.
.. code:: py
def set_points_as_corners(self, points: Sequence[float]) -> "VMobject":
"""Given an array of points, set them as corner of the Vmobject."""
* ``**kwargs`` has no typehint
* Mobjects have the typehint "Mobject", e.g.
.. code:: py
def match_color(self, mobject: "Mobject"):
"""Match the color with the color of another :class:`~.Mobject`."""
return self.set_color(mobject.get_color())
* Colors have the typehint ``Color``, e.g.
.. code:: py
def set_color(self, color: Color = YELLOW_C, family: bool = True):
"""Condition is function which takes in one arguments, (x, y, z)."""
* As ``float`` and ``Union[int, float]`` are the same, use only ``float``
* For numpy arrays use the typehint ``np.ndarray``
* Functions that does not return a value should get the type hint ``None``. (This annotations help catch the kinds of subtle bugs where you are trying to use a meaningless return value. )
.. code:: py
def height(self, value) -> None:
self.scale_to_fit_height(value)
* Parameters that are None by default should get the type hint ``Optional``
.. code:: py
def rotate(
self,
angle,
axis=OUT,
about_point: Optional[Sequence[float]] = None,
**kwargs,
):
pass
* The ``__init__()`` method always should have None as its return type.
* Functions and lambda functions should get the typehint ``Callable``
.. code:: py
rate_func: Callable[[float], float] = lambda t: smooth(1 - t)
* Assuming that typical path objects are either Paths or strs, one can use the typehint ``typing.Union[str, pathlib.Path]``
.. note::
As a helper for tool for typesets, you can use `typestring-parser
<https://github.com/Dominik1123/typestring-parser>`_
which can be accessed by first installing it via ``pip`` - ``pip install typestring-parser`` and
then using ``from typestring_parser import parse``.
.. doctest::
:options: +SKIP
>>> from typestring_parser import parse
>>> parse("int")
<class 'int'>
>>> parse("int or str")
typing.Union[int, str]
>>> parse("list of str or str")
typing.Union[typing.List[str], str]
>>> parse("list of (int, str)")
typing.List[typing.Tuple[int, str]]
Missing Sections for typehints are:
-----------------------------------
* Tools for typehinting
* Link to MyPy
* Mypy and numpy import errors: https://realpython.com/python-type-checking/#running-mypy
* Where to find the alias
* When to use Object and when to use "Object".
* The use of a TypeVar on the type hints for copy().
* The definition and use of Protocols (like Sized, or Sequence, or Iterable...)

View file

@ -94,7 +94,7 @@ Basic Concepts
self.add(image, image.background_rectangle)
.. manim:: BooleanOperations
:ref_classes: Union Intersection Exclusion
:ref_classes: Union Intersection Exclusion Difference
class BooleanOperations(Scene):
def construct(self):

View file

@ -38,6 +38,7 @@ and then record it during rendering:
from manim_voiceover import VoiceoverScene
from manim_voiceover.services.recorder import RecorderService
# Simply inherit from VoiceoverScene instead of Scene to get all the
# voiceover functionality.
class RecorderExample(VoiceoverScene):

View file

@ -211,7 +211,7 @@ is imported and Python has read and defined the ``ToyExample`` class (but,
read carefully: *no instance of this class has been created yet*).
At this point, the interpreter is about to enter the ``tempconfig`` context
manager. Even if you have not seen Manim's ``tempconfig`` before, it's name
manager. Even if you have not seen Manim's ``tempconfig`` before, its name
already suggests what it does: it creates a copy of the current state of the
configuration, applies the changes to the key-value pairs in the passed
dictionary, and upon leaving the context the original version of the
@ -266,7 +266,7 @@ The scene then asks its renderer to initialize the scene by calling
Inspecting both the default Cairo renderer and the OpenGL renderer shows that the ``init_scene``
method effectively makes the renderer instantiate a :class:`.SceneFileWriter` object, which
basically is Manim's interface to ``ffmpeg`` and actually writes the movie file. The Cairo
basically is Manim's interface to ``libav`` (FFMPEG) and actually writes the movie file. The Cairo
renderer (see the implementation `here <https://github.com/ManimCommunity/manim/blob/main/manim/renderer/cairo_renderer.py>`__) does not require any further initialization. The OpenGL renderer
does some additional setup to enable the realtime rendering preview window, which we do not go
into detail further here.
@ -310,8 +310,8 @@ the order they are called, these customizable methods are:
After these three methods are run, the animations have been fully rendered,
and Manim calls :meth:`.CairoRenderer.scene_finished` to gracefully
complete the rendering process. This checks whether any animations have been
played -- and if so, it tells the :class:`.SceneFileWriter` to close the pipe
to ``ffmpeg``. If not, Manim assumes that a static image should be output
played -- and if so, it tells the :class:`.SceneFileWriter` to close the output
file. If not, Manim assumes that a static image should be output
which it then renders using the same strategy by calling the render loop
(see below) once.
@ -762,10 +762,10 @@ to learn more, the :func:`.get_hash_from_play_call` function in the
mechanism.
In the event that the animation has to be rendered, the renderer asks
its :class:`.SceneFileWriter` to start a writing process. The process
is started by a call to ``ffmpeg`` and opens a pipe to which rendered
raw frames can be written. As long as the pipe is open, the process
can be accessed via the ``writing_process`` attribute of the file writer.
its :class:`.SceneFileWriter` to open an output container. The process
is started by a call to ``libav`` and opens a container to which rendered
raw frames can be written. As long as the output is open, the container
can be accessed via the ``output_container`` attribute of the file writer.
With the writing process in place, the renderer then asks the scene
to "begin" the animations.
@ -815,7 +815,7 @@ time is extracted (3 seconds long) and stored in
skip (it should not), then whether the animation is already
cached (it is not). The corresponding animation hash value is
determined and passed to the file writer, which then also calls
``ffmpeg`` to start the writing process which waits for rendered
``libav`` to start the writing process which waits for rendered
frames from the library.
The scene then ``begin``\ s the animation: for the
@ -1001,7 +1001,7 @@ and :meth:`.Animation.clean_up_from_scene` methods are called.
In the end, the time progression is closed (which completes the displayed progress bar)
in the terminal. With the closing of the time progression, the
:meth:`.Scene.play_internal` call is completed, and we return to the renderer,
which now orders the :class:`.SceneFileWriter` to close the movie pipe that has
which now orders the :class:`.SceneFileWriter` to close the output container that has
been opened for this animation: a partial movie file is written.
This pretty much concludes the walkthrough of a :class:`.Scene.play` call,

View file

@ -378,7 +378,7 @@ we have to add it manually.
myTemplate = TexTemplate()
myTemplate.add_to_preamble(r"\usepackage{mathrsfs}")
tex = Tex(
r"$\mathscr{H} \rightarrow \mathbb{H}$}",
r"$\mathscr{H} \rightarrow \mathbb{H}$",
tex_template=myTemplate,
font_size=144,
)

View file

@ -30,7 +30,7 @@ in the right place!
You can also find information on Manim's docker images and (online)
notebook environments there.
- Want to try the library before installing it? Take a look at our
interactive online playground at https://try.manim.community in form
interactive online playground at https://try.manim.community in the form
of a Jupyter notebook.
- In our :doc:`Tutorials <tutorials/index>` section you will find a
collection of resources that will teach you how to use Manim. In particular,
@ -71,7 +71,7 @@ Here are some short summaries for all of the sections in this documentation:
can be found in the :doc:`FAQ </faq/index>` section.
- The :doc:`Reference Manual </reference>` contains a comprehensive list of all of Manim's
(documented) modules, classes, and functions. If you are somewhat familiar with Manim's
module structure feel free to browse the manual directly. If you are searching for
module structure, feel free to browse the manual directly. If you are searching for
something specific, feel free to use the documentation's search feature in the sidebar.
Many classes and methods come with their own illustrated examples too!
- The :doc:`Plugins </plugins>` page documents how to install, write, and distribute

View file

@ -28,17 +28,25 @@ your system's Python, or via Docker).
.. _conda-installation:
Installing Manim in conda
*************************
Installing Manim via Conda and related environment managers
***********************************************************
Conda is a package manager for Python that allows creating environments
where all your dependencies are stored. Like this, you don't clutter up your PC with
unwanted libraries and you can just delete the environment when you don't need it anymore.
It is a good way to install manim since all dependencies like
``ffmpeg``, ``pycairo``, etc. come with it.
It is a good way to install manim since all dependencies like ``pycairo``, etc. come with it.
Also, the installation steps are the same, no matter if you are
on Windows, Linux, Intel Macs or on Apple Silicon.
.. NOTE::
There are various popular alternatives to Conda like
`mamba <https://mamba.readthedocs.io/en/latest/>`__ /
`micromamba <https://mamba.readthedocs.io/en/latest/user_guide/micromamba.html>`__,
or `pixi <https://pixi.sh>`__.
They all can be used to setup a suitable, isolated environment
for your Manim projects.
The following pages show how to install Manim in a conda environment:
.. toctree::
@ -54,12 +62,13 @@ Installing Manim locally
************************
Manim is a Python library, and it can be
`installed via pip <https://pypi.org/project/manim/>`__. However,
installed via `pip <https://pypi.org/project/manim/>`__
or `conda <https://anaconda.org/conda-forge/manim/>`__. However,
in order for Manim to work properly, some additional system
dependencies need to be installed first. The following pages have
operating system specific instructions for you to follow.
Manim requires Python version ``3.8`` or above to run.
Manim requires Python version ``3.9`` or above to run.
.. hint::

View file

@ -4,18 +4,21 @@ Conda
Required Dependencies
---------------------
To create a conda environment, you must first install
`conda <https://docs.conda.io/projects/conda/en/latest/user-guide/install/download.html>`__
or `mamba <https://mamba.readthedocs.io/en/latest/installation.html>`__,
the two most popular conda clients.
There are several package managers that work with conda packages,
namely `conda <https://docs.conda.io/projects/conda/en/latest/user-guide/install/download.html>`__,
`mamba <https://mamba.readthedocs.io>`__ and `pixi <https://pixi.sh>`__.
After installing conda, you can create a new environment and install ``manim`` inside by running
After installing your package manager, you can create a new environment and install ``manim`` inside by running
.. code-block:: bash
# using conda or mamba
conda create -n my-manim-environment
conda activate my-manim-environment
conda install -c conda-forge manim
# using pixi
pixi init
pixi add manim
Since all dependencies (except LaTeX) are handled by conda, you don't need to worry
about needing to install additional dependencies.

View file

@ -45,7 +45,7 @@ modify to your liking. First, run
.. code-block:: sh
docker run -it --name my-manim-container -v "/full/path/to/your/directory:/manim" manimcommunity/manim /bin/bash
docker run -it --name my-manim-container -v "/full/path/to/your/directory:/manim" manimcommunity/manim bash
to obtain an interactive shell inside your container allowing you

View file

@ -66,12 +66,12 @@ then execute it.
.. code-block::
!sudo apt update
!sudo apt install libcairo2-dev ffmpeg \
!sudo apt install libcairo2-dev \
texlive texlive-latex-extra texlive-fonts-extra \
texlive-latex-recommended texlive-science \
tipa libpango1.0-dev
!pip install manim
!pip install IPython --upgrade
!pip install IPython==8.21.0
You should start to see Colab installing all the dependencies specified
in these commands. After the execution has completed, you will be prompted

View file

@ -5,10 +5,9 @@ The installation instructions depend on your particular operating
system and package manager. If you happen to know exactly what you are doing,
you can also simply ensure that your system has:
- a reasonably recent version of Python 3 (3.8 or above),
- a reasonably recent version of Python 3 (3.9 or above),
- with working Cairo bindings in the form of
`pycairo <https://cairographics.org/pycairo/>`__,
- FFmpeg accessible from the command line as ``ffmpeg``,
- and `Pango <https://pango.gnome.org>`__ headers.
Then, installing Manim is just a matter of running:
@ -33,13 +32,13 @@ Required Dependencies
apt Ubuntu / Mint / Debian
****************************
To first update your sources, and then install Cairo, Pango, and FFmpeg
To first update your sources, and then install Cairo and Pango
simply run:
.. code-block:: bash
sudo apt update
sudo apt install build-essential python3-dev libcairo2-dev libpango1.0-dev ffmpeg
sudo apt install build-essential python3-dev libcairo2-dev libpango1.0-dev
If you don't have python3-pip installed, install it via:
@ -72,14 +71,6 @@ need the Python development headers:
sudo dnf install python3-devel
FFmpeg is only available via the RPMfusion repository which you have to
configure first please consult https://rpmfusion.org/Configuration/ for
instructions. Then, install FFmpeg:
.. code-block:: bash
sudo dnf install ffmpeg
At this point you have all required dependencies and can install
Manim by running:
@ -100,12 +91,12 @@ pacman  Arch / Manjaro
If you don't want to use the packaged version from AUR, here is what
you need to do manually: Update your package sources, then install
Cairo, Pango, and FFmpeg:
Cairo and Pango:
.. code-block:: bash
sudo pacman -Syu
sudo pacman -S cairo pango ffmpeg
sudo pacman -S cairo pango
If you don't have ``python-pip`` installed, get it by running:

View file

@ -20,12 +20,12 @@ follow `Homebrew's installation instructions <https://docs.brew.sh/Installation>
Required Dependencies
---------------------
To install all required dependencies for installing Manim (namely: ffmpeg, Python,
To install all required dependencies for installing Manim (namely: Python,
and some required Python packages), run:
.. code-block:: bash
brew install py3cairo ffmpeg
brew install py3cairo
On *Apple Silicon* based machines (i.e., devices with the M1 chip or similar; if
you are unsure which processor you have check by opening the Apple menu, select

View file

@ -3,11 +3,8 @@ Windows
The easiest way of installing Manim and its dependencies is by using a
package manager like `Chocolatey <https://chocolatey.org/>`__
or `Scoop <https://scoop.sh>`__. If you are not afraid of editing
your System's ``PATH``, a manual installation is also possible.
In fact, if you already have an existing Python
installation (3.8 or above), it might be the easiest way to get
everything up and running.
or `Scoop <https://scoop.sh>`__, especially if you need optional dependencies
like LaTeX support.
If you choose to use one of the package managers, please follow
their installation instructions
@ -19,7 +16,7 @@ to make one of them available on your system.
Required Dependencies
---------------------
Manim requires a recent version of Python (3.8 or above) and ``ffmpeg``
Manim requires a recent version of Python (3.9 or above)
in order to work.
Chocolatey
@ -34,53 +31,11 @@ Manim can be installed via Chocolatey simply by running:
That's it, no further steps required. You can continue with installing
the :ref:`optional dependencies <win-optional-dependencies>` below.
Scoop
*****
While there is no recipe for installing Manim with Scoop directly,
you can install all requirements by running:
.. code-block:: powershell
scoop install python ffmpeg
and then Manim can be installed by running:
.. code-block:: powershell
python -m pip install manim
Manim should now be installed on your system. Continue reading
the :ref:`optional dependencies <win-optional-dependencies>` section
below.
Winget
******
While there is no recipe for installing Manim with Winget directly,
you can install all requirements by running:
.. code-block:: powershell
winget install python
winget install ffmpeg
and then Manim can be installed by running:
.. code-block:: powershell
python -m pip install manim
Manim should now be installed on your system. Continue reading
the :ref:`optional dependencies <win-optional-dependencies>` section
below.
Manual Installation
*******************
Pip
***
As mentioned above, Manim needs a reasonably recent version of
Python 3 (3.8 or above) and FFmpeg.
Python 3 (3.9 or above).
**Python:** Head over to https://www.python.org, download an installer
for a recent version of Python, and follow its instructions to get Python
@ -94,35 +49,16 @@ installed on your system.
install Python directly from the
`official website <https://www.python.org>`__.
**FFmpeg:** In order to install FFmpeg, you can get a
pre-compiled and ready-to-use version from one of the resources
linked at https://ffmpeg.org/download.html#build-windows, such as
`the version available here
<https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.7z>`__
(recommended), or if you know exactly what you are doing
you can alternatively get the source code
from https://ffmpeg.org/download.html and compile it yourself.
After downloading the pre-compiled archive,
`unzip it <https://www.7-zip.org>`__ and, if you like, move the
extracted directory to some more permanent place (e.g.,
``C:\Program Files\``). Next, edit the ``PATH`` environment variable:
first, visit ``Control Panel`` > ``System`` > ``System settings`` >
``Environment Variables``, then add the full path to the ``bin``
directory inside of the (moved) ffmpeg directory to the
``PATH`` variable. Finally, save your changes and exit.
If you now open a new command line prompt (or PowerShell) and
run ``ffmpeg``, the command should be recognized.
At this point, you have all the required dependencies and can now
install Manim via
Then, Manim can be installed via Pip simply by running:
.. code-block:: powershell
python -m pip install manim
Manim should now be installed on your system. Continue reading
the :ref:`optional dependencies <win-optional-dependencies>` section
below.
.. _win-optional-dependencies:

View file

@ -99,40 +99,18 @@ directory structure, build system, and naming are completely up to your
discretion as an author. The aforementioned template plugin is only a model
using Poetry since this is the build system Manim uses. The plugin's `entry
point <https://packaging.python.org/specifications/entry-points/>`_ can be
specified in poetry as:
specified in Poetry as:
.. code-block:: toml
[tool.poetry.plugins."manim.plugins"]
"name" = "object_reference"
Here ``name`` is the name of the module of the plugin.
.. versionremoved:: 0.19.0
Here ``object_reference`` can point to either a function in a module or a module
itself. For example,
.. code-block:: toml
[tool.poetry.plugins."manim.plugins"]
"manim_plugintemplate" = "manim_plugintemplate"
Here a module is used as ``object_reference``, and when this plugin is enabled,
Manim will look for ``__all__`` keyword defined in ``manim_plugintemplate`` and
everything as a global variable one by one.
If ``object_reference`` is a function, Manim calls the function and expects the
function to return a list of modules or functions that need to be defined globally.
For example,
.. code-block:: toml
[tool.poetry.plugins."manim.plugins"]
"manim_plugintemplate" = "manim_awesomeplugin.imports:setup_things"
Here, Manim will call the function ``setup_things`` defined in
``manim_awesomeplugin.imports`` and calls that. It returns a list of function or
modules which will be imported globally.
Plugins should be imported explicitly to be usable in user code. The plugin
system will probably be refactored in the future to provide a more structured
interface.
A note on Renderer Compatibility
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -9,23 +9,25 @@ Module Index
.. autosummary::
:toctree: ../reference
constants
~utils.bezier
~utils.color
~utils.commands
~utils.config_ops
~utils.deprecation
constants
~utils.debug
~utils.deprecation
~utils.docbuild
~utils.hashing
~utils.ipython_magic
~utils.images
~utils.ipython_magic
~utils.iterables
~utils.paths
~utils.rate_functions
~utils.simple_functions
~utils.sounds
~utils.space_ops
~utils.testing
~utils.tex
~utils.tex_templates
~utils.tex_file_writing
~utils.tex_templates
typing

View file

@ -376,13 +376,13 @@ and :meth:`~.Mobject.get_start`. Here is an example of some important coordinate
class MobjectExample(Scene):
def construct(self):
p1= [-1,-1,0]
p2= [1,-1,0]
p3= [1,1,0]
p4= [-1,1,0]
a = Line(p1,p2).append_points(Line(p2,p3).points).append_points(Line(p3,p4).points)
point_start= a.get_start()
point_end = a.get_end()
p1 = [-1,-1, 0]
p2 = [ 1,-1, 0]
p3 = [ 1, 1, 0]
p4 = [-1, 1, 0]
a = Line(p1,p2).append_points(Line(p2,p3).points).append_points(Line(p3,p4).points)
point_start = a.get_start()
point_end = a.get_end()
point_center = a.get_center()
self.add(Text(f"a.get_start() = {np.round(point_start,2).tolist()}", font_size=24).to_edge(UR).set_color(YELLOW))
self.add(Text(f"a.get_end() = {np.round(point_end,2).tolist()}", font_size=24).next_to(self.mobjects[-1],DOWN).set_color(RED))
@ -425,8 +425,8 @@ function of numpy:
self.camera.background_color = WHITE
m1a = Square().set_color(RED).shift(LEFT)
m1b = Circle().set_color(RED).shift(LEFT)
m2a= Square().set_color(BLUE).shift(RIGHT)
m2b= Circle().set_color(BLUE).shift(RIGHT)
m2a = Square().set_color(BLUE).shift(RIGHT)
m2b = Circle().set_color(BLUE).shift(RIGHT)
points = m2a.points
points = np.roll(points, int(len(points)/4), axis=0)

View file

@ -276,25 +276,28 @@ When executing the command
manim -pql scene.py SquareToCircle
it was necessary to specify which ``Scene`` class to render. This is because a
single file can contain more than one ``Scene`` class. If your file contains
multiple ``Scene`` classes, and you want to render them all, you can use the
``-a`` flag.
it specifies the scene to render. This is not necessary now. When a single
file contains only one ``Scene`` class, it will just render the ``Scene``
class. When a single file contains more than one ``Scene`` class, manim will
let you choose a ``Scene`` class. If your file contains multiple ``Scene``
classes, and you want to render them all, you can use the ``-a`` flag.
As discussed previously, the ``-ql`` specifies low render quality. This does
not look very good, but is very useful for rapid prototyping and testing. The
other options that specify render quality are ``-qm``, ``-qh``, and ``-qk`` for
medium, high, and 4k quality, respectively.
As discussed previously, the ``-ql`` specifies low render quality (854x480
15FPS). This does not look very good, but is very useful for rapid
prototyping and testing. The other options that specify render quality are
``-qm``, ``-qh``, ``-qp`` and ``-qk`` for medium (1280x720 30FPS), high
(1920x1080 60FPS), 2k (2560x1440 60FPS) and 4k quality (3840x2160 60FPS),
respectively.
The ``-p`` flag plays the animation once it is rendered. If you want to open
the file browser at the location of the animation instead of playing it, you
can use the ``-f`` flag. You can also omit these two flags.
Finally, by default manim will output .mp4 files. If you want your animations
in .gif format instead, use the ``-i`` flag. The output files will be in the
same folder as the .mp4 files, and with the same name, but a different file
extension.
in .gif format instead, use the ``--format gif`` flag. The output files will
be in the same folder as the .mp4 files, and with the same name, but a
different file extension.
This was a quick review of some of the most frequent command-line flags. For a
thorough review of all flags available, see the
:doc:`thematic guide on Manim's configuration system </guides/configuration>`.
This was a quick review of some of the most frequent command-line flags.
For a thorough review of all flags available, see the :doc:`thematic guide on
Manim's configuration system </guides/configuration>`.

View file

@ -113,7 +113,7 @@ Now let's look at the next two lines:
class CreateCircle(Scene):
def construct(self):
...
[...]
Most of the time, the code for scripting an animation is entirely contained within
the :meth:`~.Scene.construct` method of a :class:`.Scene` class.
@ -268,11 +268,9 @@ and animating those method calls with ``.animate``.
self.play(Create(square)) # show the square on screen
self.play(square.animate.rotate(PI / 4)) # rotate the square
self.play(Transform(square, circle)) # transform the square into a circle
self.play(
ReplacementTransform(square, circle)
) # transform the square into a circle
self.play(
circle.animate.set_fill(PINK, opacity=0.5)
square.animate.set_fill(PINK, opacity=0.5)
) # color the circle on screen
2. Render ``AnimatedSquareToCircle`` by running the following command in the command line:
@ -293,8 +291,8 @@ The following animation will render:
self.play(Create(square)) # show the square on screen
self.play(square.animate.rotate(PI / 4)) # rotate the square
self.play(ReplacementTransform(square, circle)) # transform the square into a circle
self.play(circle.animate.set_fill(PINK, opacity=0.5)) # color the circle on screen
self.play(Transform(square, circle)) # transform the square into a circle
self.play(square.animate.set_fill(PINK, opacity=0.5)) # color the circle on screen
The first ``self.play`` creates the square. The second animates rotating it 45 degrees.
The third transforms the square into a circle, and the last colors the circle pink.
@ -342,12 +340,61 @@ the corners of the square appear to contract slightly as they move into the posi
for the first square to transform into the second one.
In ``DifferentRotations``, the difference between ``.animate``'s interpretation of rotation and the
``Rotate`` method is far more apparent. The starting and ending states of a ``Mobject`` rotated 360 degrees
``Rotate`` method is far more apparent. The starting and ending states of a ``Mobject`` rotated 180 degrees
are the same, so ``.animate`` tries to interpolate two identical objects and the result is the left square.
If you find that your own usage of ``.animate`` is causing similar unwanted behavior, consider
using conventional animation methods like the right square, which uses ``Rotate``.
``Transform`` vs ``ReplacementTransform``
*****************************************
The difference between ``Transform`` and ``ReplacementTransform`` is that ``Transform(mob1, mob2)`` transforms the points
(as well as other attributes like color) of ``mob1`` into the points/attributes of ``mob2``.
``ReplacementTransform(mob1, mob2)`` on the other hand literally replaces ``mob1`` on the scene with ``mob2``.
The use of ``ReplacementTransform`` or ``Transform`` is mostly up to personal preference. They can be used to accomplish the same effect, as shown below.
.. code-block:: python
class TwoTransforms(Scene):
def transform(self):
a = Circle()
b = Square()
c = Triangle()
self.play(Transform(a, b))
self.play(Transform(a, c))
self.play(FadeOut(a))
def replacement_transform(self):
a = Circle()
b = Square()
c = Triangle()
self.play(ReplacementTransform(a, b))
self.play(ReplacementTransform(b, c))
self.play(FadeOut(c))
def construct(self):
self.transform()
self.wait(0.5) # wait for 0.5 seconds
self.replacement_transform()
However, in some cases it is more beneficial to use ``Transform``, like when you are transforming several mobjects one after the other.
The code below avoids having to keep a reference to the last mobject that was transformed.
.. manim:: TransformCycle
class TransformCycle(Scene):
def construct(self):
a = Circle()
t1 = Square()
t2 = Triangle()
self.add(a)
self.wait()
for t in [t1,t2]:
self.play(Transform(a,t))
************
You're done!
************

View file

@ -153,7 +153,7 @@ class SpiralInExample(Scene):
],
color=PURPLE_B,
fill_opacity=1,
stroke_width=0
stroke_width=0,
).shift(UP + 2 * RIGHT)
shapes = VGroup(triangle, square, circle, pentagon, pi)
self.play(SpiralIn(shapes, fade_in_fraction=0.9))
@ -167,8 +167,8 @@ Triangle.set_default(stroke_width=20)
class LineJoints(Scene):
def construct(self):
t1 = Triangle()
t2 = Triangle(line_join=LineJointType.ROUND)
t3 = Triangle(line_join=LineJointType.BEVEL)
t2 = Triangle(joint_type=LineJointType.ROUND)
t3 = Triangle(joint_type=LineJointType.BEVEL)
grp = VGroup(t1, t2, t3).arrange(RIGHT)
grp.set(width=config.frame_width - 1)

View file

@ -2,24 +2,18 @@ import time
import numpy as np
import pyglet
from PIL import Image
from pyglet import shapes
from pyglet.gl import Config
from pyglet.window import Window
import manim.utils.color.manim_colors as col
from manim._config import config, tempconfig
from manim.animation.creation import Create, DrawBorderThenFill, Write
from manim.animation.fading import FadeIn
from manim.animation.transform import Transform
from manim._config import tempconfig
from manim.animation.creation import DrawBorderThenFill
from manim.camera.camera import Camera
from manim.constants import LEFT, OUT, RIGHT, UP
from manim.mobject.geometry.arc import Circle
from manim.mobject.geometry.polygram import Square
from manim.mobject.logo import ManimBanner
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject
from manim.mobject.text.numbers import DecimalNumber
from manim.mobject.text.text_mobject import Text
from manim.renderer.opengl_renderer import OpenGLRenderer
if __name__ == "__main__":

View file

@ -406,7 +406,7 @@ class InteractiveDevelopment(Scene):
self.play(Create(square))
self.wait()
# This opens an iPython termnial where you can keep writing
# This opens an iPython terminal where you can keep writing
# lines as if they were part of this construct method.
# In particular, 'square', 'circle' and 'self' will all be
# part of the local namespace in that terminal.

View file

@ -1,22 +1,17 @@
import time
import numpy as np
import pyglet
from PIL import Image
from pyglet import shapes
from pyglet.gl import Config
from pyglet.window import Window
import manim.utils.color.manim_colors as col
from manim._config import config, tempconfig
from manim.camera.camera import OpenGLCamera, OpenGLCameraFrame
from manim._config import tempconfig
from manim.camera.camera import OpenGLCameraFrame
from manim.constants import OUT, RIGHT, UP
from manim.mobject.geometry.arc import Circle
from manim.mobject.geometry.polygram import Square
from manim.mobject.logo import ManimBanner
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject
from manim.mobject.text.numbers import DecimalNumber
from manim.mobject.text.text_mobject import Text
from manim.renderer.opengl_renderer import OpenGLRenderer
if __name__ == "__main__":

View file

@ -1,15 +1,11 @@
#!/usr/bin/env python
from __future__ import annotations
import pkg_resources
from importlib.metadata import version
__version__: str = pkg_resources.get_distribution(__name__).version
__version__ = version(__name__)
import sys
# isort: off
# Importing the config module should be the first thing we do, since other
@ -20,6 +16,7 @@ from ._config import *
from .utils.commands import *
# isort: on
import numpy as np
from .animation.animation import *
from .animation.changing import *

View file

@ -1,7 +1,5 @@
from __future__ import annotations
import sys
import click
import cloup
@ -10,18 +8,20 @@ from .cli.cfg.group import cfg
from .cli.checkhealth.commands import checkhealth
from .cli.default_group import DefaultGroup
from .cli.init.commands import init
from .cli.new.group import new
from .cli.plugins.commands import plugins
from .cli.render.commands import render
from .constants import EPILOG
def exit_early(ctx, param, value):
def show_splash(ctx, param, value):
if value:
sys.exit()
console.print(f"Manim Community [green]v{__version__}[/green]\n")
console.print(f"Manim Community [green]v{__version__}[/green]\n")
def print_version_and_exit(ctx, param, value):
show_splash(ctx, param, value)
if value:
ctx.exit()
@cloup.group(
@ -35,15 +35,24 @@ console.print(f"Manim Community [green]v{__version__}[/green]\n")
"is specified. Run 'manim render --help' if you would like to know what the "
f"'-ql' or '-p' flags do, for example.\n\n{EPILOG}",
)
@click.option(
@cloup.option(
"--version",
is_flag=True,
help="Show version and exit.",
callback=exit_early,
callback=print_version_and_exit,
is_eager=True,
expose_value=False,
)
@click.pass_context
@click.option(
"--show-splash/--hide-splash",
is_flag=True,
default=True,
help="Print splash message with version information.",
callback=show_splash,
is_eager=True,
expose_value=False,
)
@cloup.pass_context
def main(ctx):
"""The entry point for manim."""
pass
@ -53,7 +62,6 @@ main.add_command(checkhealth)
main.add_command(cfg)
main.add_command(plugins)
main.add_command(init)
main.add_command(new)
main.add_command(render)
if __name__ == "__main__":

View file

@ -3,7 +3,9 @@
from __future__ import annotations
import logging
from contextlib import _GeneratorContextManager, contextmanager
from collections.abc import Generator
from contextlib import contextmanager
from typing import Any
from .cli_colors import parse_cli_ctx
from .logger_utils import make_logger
@ -20,7 +22,6 @@ __all__ = [
]
parser = make_config_parser()
logger: logging.Logger
# The logger can be accessed from anywhere as manim.logger, or as
# logging.getLogger("manim"). The console must be accessed as manim.console.
@ -36,12 +37,14 @@ logging.getLogger("PIL").setLevel(logging.INFO)
logging.getLogger("matplotlib").setLevel(logging.INFO)
config = ManimConfig().digest_parser(parser)
# TODO: to be used in the future - see PR #620
# https://github.com/ManimCommunity/manim/pull/620
frame = ManimFrame(config)
# This has to go here because it needs access to this module's config
@contextmanager
def tempconfig(temp: ManimConfig | dict) -> _GeneratorContextManager:
def tempconfig(temp: ManimConfig | dict[str, Any]) -> Generator[None, None, None]:
"""Context manager that temporarily modifies the global ``config`` object.
Inside the ``with`` statement, the modified config will be used. After
@ -65,7 +68,6 @@ def tempconfig(temp: ManimConfig | dict) -> _GeneratorContextManager:
8.0
>>> with tempconfig({"frame_height": 100.0}):
... print(config["frame_height"])
...
100.0
>>> config["frame_height"]
8.0

View file

@ -1,10 +1,14 @@
from __future__ import annotations
import configparser
from cloup import Context, HelpFormatter, HelpTheme, Style
__all__ = ["parse_cli_ctx"]
def parse_cli_ctx(parser: configparser.ConfigParser) -> Context:
formatter_settings = {
def parse_cli_ctx(parser: configparser.SectionProxy) -> Context:
formatter_settings: dict[str, str | int] = {
"indent_increment": int(parser["indent_increment"]),
"width": int(parser["width"]),
"col1_max_width": int(parser["col1_max_width"]),
@ -30,16 +34,19 @@ def parse_cli_ctx(parser: configparser.ConfigParser) -> Context:
formatter = {}
theme = parser["theme"] if parser["theme"] else None
if theme is None:
formatter = HelpFormatter().settings(
theme=HelpTheme(**theme_settings), **formatter_settings
formatter = HelpFormatter.settings(
theme=HelpTheme(**theme_settings),
**formatter_settings, # type: ignore[arg-type]
)
elif theme.lower() == "dark":
formatter = HelpFormatter().settings(
theme=HelpTheme.dark().with_(**theme_settings), **formatter_settings
formatter = HelpFormatter.settings(
theme=HelpTheme.dark().with_(**theme_settings),
**formatter_settings, # type: ignore[arg-type]
)
elif theme.lower() == "light":
formatter = HelpFormatter().settings(
theme=HelpTheme.light().with_(**theme_settings), **formatter_settings
formatter = HelpFormatter.settings(
theme=HelpTheme.light().with_(**theme_settings),
**formatter_settings, # type: ignore[arg-type]
)
return Context.settings(

View file

@ -221,9 +221,7 @@ repr_number = green
# Uncomment the following line to manually set the loglevel for ffmpeg. See
# ffmpeg manpage for accepted values
loglevel = ERROR
# defaults to the one present in path
ffmpeg_executable = ffmpeg
[jupyter]
media_embed =
media_embed = False
media_width = 60%%

View file

@ -9,13 +9,13 @@ Both ``logger`` and ``console`` use the ``rich`` library to produce rich text
format.
"""
from __future__ import annotations
import configparser
import copy
import json
import logging
import sys
from typing import TYPE_CHECKING
from rich import color, errors
@ -26,6 +26,9 @@ from rich.theme import Theme
if TYPE_CHECKING:
from pathlib import Path
__all__ = ["make_logger", "parse_theme", "set_file_logger", "JSONFormatter"]
HIGHLIGHTED_KEYWORDS = [ # these keywords are highlighted specially
"Played",
"animations",
@ -49,9 +52,9 @@ Loading the default color configuration.[/logging.level.error]
def make_logger(
parser: configparser.ConfigParser,
parser: configparser.SectionProxy,
verbosity: str,
) -> tuple[logging.Logger, Console]:
) -> tuple[logging.Logger, Console, Console]:
"""Make the manim logger and console.
Parameters
@ -83,14 +86,13 @@ def make_logger(
theme = parse_theme(parser)
console = Console(theme=theme)
# With rich 9.5.0+ we could pass stderr=True instead
error_console = Console(theme=theme, file=sys.stderr)
error_console = Console(theme=theme, stderr=True)
# set the rich handler
RichHandler.KEYWORDS = HIGHLIGHTED_KEYWORDS
rich_handler = RichHandler(
console=console,
show_time=parser.getboolean("log_timestamps"),
keywords=HIGHLIGHTED_KEYWORDS,
)
# finally, the logger
@ -98,10 +100,14 @@ def make_logger(
logger.addHandler(rich_handler)
logger.setLevel(verbosity)
if not (libav_logger := logging.getLogger()).hasHandlers():
libav_logger.addHandler(rich_handler)
libav_logger.setLevel(verbosity)
return logger, console, error_console
def parse_theme(parser: configparser.ConfigParser) -> Theme:
def parse_theme(parser: configparser.SectionProxy) -> Theme:
"""Configure the rich style of logger and console output.
Parameters
@ -177,7 +183,7 @@ class JSONFormatter(logging.Formatter):
"""
def format(self, record: dict) -> str:
def format(self, record: logging.LogRecord) -> str:
"""Format the record in a custom JSON format."""
record_c = copy.deepcopy(record)
if record_c.args:

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,5 @@
"""Animate mobjects."""
from __future__ import annotations
from manim.mobject.opengl.opengl_mobject import OpenGLMobject
@ -16,8 +15,11 @@ from .scene_buffer import SceneBuffer
__all__ = ["Animation", "Wait", "override_animation"]
from collections.abc import Iterable, Sequence
from copy import deepcopy
from typing import TYPE_CHECKING, Callable, Iterable, Sequence, TypeVar
from typing import TYPE_CHECKING, Callable
from typing_extensions import Self, TypeVar
if TYPE_CHECKING:
from typing_extensions import Self
@ -113,7 +115,7 @@ class Animation(AnimationProtocol):
*args,
use_override=True,
**kwargs,
):
) -> Self:
if isinstance(mobject, Mobject) and use_override:
func = mobject.animation_override_for(cls)
if func is not None:
@ -393,6 +395,7 @@ class Animation(AnimationProtocol):
self.run_time = run_time
return self
# TODO: is this getter even necessary?
def get_run_time(self) -> float:
"""Get the run time of the animation.

View file

@ -12,7 +12,8 @@ if TYPE_CHECKING:
import numpy as np
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
from manim.mobject.types.vectorized_mobject import VGroup, VMobject
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVGroup as VGroup
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject as VMobject
from manim.utils.color import (
BLUE_B,
BLUE_D,

View file

@ -1,26 +1,29 @@
"""Tools for displaying multiple animations at once."""
from __future__ import annotations
from typing import TYPE_CHECKING, Callable, Sequence
from collections.abc import Iterable, Sequence
from typing import TYPE_CHECKING, Callable
import numpy as np
from manim import config, logger
from manim._config import config
from manim.animation.animation import Animation, prepare_animation
from manim.constants import RendererType
from manim.mobject.mobject import Group, Mobject
from manim.mobject.opengl.opengl_mobject import OpenGLGroup
from manim.utils.iterables import remove_list_redundancies
from manim.utils.parameter_parsing import flatten_iterable_parameters
from manim.utils.rate_functions import linear
from ..animation.animation import Animation, prepare_animation
from ..constants import RendererType
from ..mobject.mobject import Group, Mobject
from ..utils.iterables import remove_list_redundancies
from ..utils.rate_functions import linear
if TYPE_CHECKING:
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVGroup
from manim.mobject.types.vectorized_mobject import VGroup
from ..mobject.types.vectorized_mobject import VGroup
from .scene_buffer import SceneBuffer
__all__ = ["AnimationGroup", "Succession", "LaggedStart", "LaggedStartMap"]
@ -54,14 +57,15 @@ class AnimationGroup(Animation):
def __init__(
self,
*animations: Animation,
*animations: Animation | Iterable[Animation],
group: Group | VGroup | OpenGLGroup | OpenGLVGroup | None = None,
run_time: float | None = None,
rate_func: Callable[[float], float] = linear,
lag_ratio: float = 0,
**kwargs,
) -> None:
self.animations = [prepare_animation(anim) for anim in animations]
arg_anim = flatten_iterable_parameters(animations)
self.animations = [prepare_animation(anim) for anim in arg_anim]
self.rate_func = rate_func
self.group = group
if self.group is None:
@ -84,14 +88,21 @@ class AnimationGroup(Animation):
for anim in self.animations:
anim.begin()
self.process_subanimation_buffer(anim.buffer)
if not self.animations:
raise ValueError(
f"Trying to play {self} without animations, this is not supported. "
"Please add at least one subanimation."
)
self.anim_group_time = 0.0
if self.suspend_mobject_updating:
self.group.suspend_updating()
def finish(self) -> None:
self.interpolate(1)
self.anims_begun[:] = True
self.anims_begun[:] = True
for anim in self.animations:
if self.remover:
anim.remover = self.remover
anim.finish()
self.process_subanimation_buffer(anim.buffer)
if self.suspend_mobject_updating:
@ -99,7 +110,9 @@ class AnimationGroup(Animation):
self._on_finish(self.buffer)
def update_mobjects(self, dt: float) -> None:
for anim in self.animations:
for anim in self.anims_with_timings["anim"][
self.anims_begun & ~self.anims_finished
]:
anim.update_mobjects(dt)
def init_run_time(self, run_time) -> float:
@ -116,25 +129,30 @@ class AnimationGroup(Animation):
The duration of the animation in seconds.
"""
self.build_animations_with_timings()
if self.anims_with_timings:
self.max_end_time = np.max([awt[2] for awt in self.anims_with_timings])
else:
self.max_end_time = 0
# Note: if lag_ratio < 1, then not necessarily the final animation's
# end time will be the max end time! Therefore we must calculate the
# maximum over all the end times, and not just take the last one.
# Example: if you want to play 2 animations of 10s and 1s with a
# lag_ratio of 0.1, the 1st one will end at t=10 and the 2nd one will
# end at t=2, so the AnimationGroup will end at t=10.
self.max_end_time = max(self.anims_with_timings["end"], default=0)
return self.max_end_time if run_time is None else run_time
def build_animations_with_timings(self) -> None:
"""Creates a list of triplets of the form (anim, start_time, end_time)."""
run_times = np.array([anim.run_time for anim in self.animations])
num_animations = run_times.shape[0]
dtype = [("anim", "O"), ("start", "f8"), ("end", "f8")]
self.anims_with_timings = np.zeros(num_animations, dtype=dtype)
self.anims_begun = np.zeros(num_animations, dtype=bool)
self.anims_finished = np.zeros(num_animations, dtype=bool)
if num_animations == 0:
return
self.anims_with_timings = []
"""List of tuple[Animation, start_time, end_time]"""
curr_time: float = 0
for anim in self.animations:
start_time: float = curr_time
end_time: float = start_time + anim.get_run_time()
self.anims_with_timings.append((anim, start_time, end_time))
# Start time of next animation is based on the lag_ratio
curr_time = (1 - self.lag_ratio) * start_time + self.lag_ratio * end_time
lags = run_times[:-1] * self.lag_ratio
self.anims_with_timings["anim"] = self.animations
self.anims_with_timings["start"][1:] = np.add.accumulate(lags)
self.anims_with_timings["end"] = self.anims_with_timings["start"] + run_times
def interpolate(self, alpha: float) -> None:
# Note, if the run_time of AnimationGroup has been
@ -142,14 +160,30 @@ class AnimationGroup(Animation):
# times might not correspond to actual times,
# e.g. of the surrounding scene. Instead they'd
# be a rescaled version. But that's okay!
time = self.rate_func(alpha) * self.max_end_time
for anim, start_time, end_time in self.anims_with_timings:
anim_time = end_time - start_time
if anim_time == 0:
sub_alpha = 0
else:
sub_alpha = np.clip((time - start_time) / anim_time, 0, 1)
anim.interpolate(sub_alpha)
anim_group_time = self.rate_func(alpha) * self.max_end_time
time_goes_back = anim_group_time < self.anim_group_time
# Only update ongoing animations
awt = self.anims_with_timings
new_begun = anim_group_time >= awt["start"]
new_finished = anim_group_time > awt["end"]
to_update = awt[
(self.anims_begun | new_begun) & (~self.anims_finished | ~new_finished)
]
run_times = to_update["end"] - to_update["start"]
sub_alphas = (anim_group_time - to_update["start"]) / run_times
if time_goes_back:
sub_alphas[sub_alphas < 0] = 0
else:
sub_alphas[sub_alphas > 1] = 1
for anim_to_update, sub_alpha in zip(to_update["anim"], sub_alphas):
anim_to_update.interpolate(sub_alpha)
self.anim_group_time = anim_group_time
self.anims_begun = new_begun
self.anims_finished = new_finished
class Succession(AnimationGroup):
@ -193,7 +227,11 @@ class Succession(AnimationGroup):
super().__init__(*animations, lag_ratio=lag_ratio, **kwargs)
def begin(self) -> None:
assert len(self.animations) > 0
if not self.animations:
raise ValueError(
f"Trying to play {self} without animations, this is not supported. "
"Please add at least one subanimation."
)
self.update_active_animation(0)
for anim in self.animations:
@ -219,8 +257,8 @@ class Succession(AnimationGroup):
self.active_animation.begin()
self.process_subanimation_buffer(self.active_animation.buffer)
self.apply_buffer = True
self.active_start_time = self.anims_with_timings[index][1]
self.active_end_time = self.anims_with_timings[index][2]
self.active_start_time = self.anims_with_timings[index]["start"]
self.active_end_time = self.anims_with_timings[index]["end"]
def next_animation(self) -> None:
"""Proceeds to the next animation.
@ -238,7 +276,7 @@ class Succession(AnimationGroup):
self.next_animation()
if self.active_animation is not None and self.active_start_time is not None:
elapsed = current_time - self.active_start_time
active_run_time = self.active_animation.get_run_time()
active_run_time = self.active_animation.run_time
subalpha = elapsed / active_run_time if active_run_time != 0.0 else 1.0
self.active_animation.interpolate(subalpha)

View file

@ -70,11 +70,14 @@ __all__ = [
"RemoveTextLetterByLetter",
"ShowSubmobjectsOneByOne",
"AddTextWordByWord",
"TypeWithCursor",
"UntypeWithCursor",
]
import itertools as it
from typing import TYPE_CHECKING, Callable, Iterable, Sequence
from collections.abc import Iterable, Sequence
from typing import TYPE_CHECKING, Callable
import numpy as np
@ -82,17 +85,18 @@ if TYPE_CHECKING:
from typing_extensions import Self
from manim.mobject.text.text_mobject import Text
from manim.scene.scene import Scene
from manim.constants import RIGHT, TAU
from manim.mobject.opengl.opengl_surface import OpenGLSurface
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject as VMobject
from manim.utils.color import ManimColor
from .. import config
from ..animation.animation import Animation
from ..animation.composition import Succession
from ..constants import TAU
from ..mobject.mobject import Group, Mobject
from ..mobject.types.vectorized_mobject import VMobject
from ..utils.bezier import integer_interpolate
from ..utils.rate_functions import double_smooth, linear
@ -358,18 +362,15 @@ class Write(DrawBorderThenFill):
lag_ratio = min(4.0 / max(1.0, length), 0.2)
return run_time, lag_ratio
def reverse_submobjects(self) -> None:
self.mobject.invert(recursive=True)
def begin(self) -> None:
if self.reverse:
self.reverse_submobjects()
self.mobject.reverse_submobjects(recursive=True)
super().begin()
def finish(self) -> None:
super().finish()
if self.reverse:
self.reverse_submobjects()
self.mobject.reverse_submobjects(recursive=True)
class Unwrite(Write):
@ -459,7 +460,7 @@ class SpiralIn(Animation):
fade_in_fraction=0.3,
**kwargs,
) -> None:
self.shapes = shapes
self.shapes = shapes.copy()
self.scale_factor = scale_factor
self.shape_center = shapes.get_center()
self.fade_in_fraction = fade_in_fraction
@ -476,15 +477,21 @@ class SpiralIn(Animation):
def interpolate_mobject(self, alpha: float) -> None:
alpha = self.rate_func(alpha)
for shape in self.shapes:
for original_shape, shape in zip(self.shapes, self.mobject):
shape.restore()
shape.save_state()
opacity = shape.get_fill_opacity()
new_opacity = min(opacity, alpha * opacity / self.fade_in_fraction)
fill_opacity = original_shape.get_fill_opacity()
stroke_opacity = original_shape.get_stroke_opacity()
new_fill_opacity = min(
fill_opacity, alpha * fill_opacity / self.fade_in_fraction
)
new_stroke_opacity = min(
stroke_opacity, alpha * stroke_opacity / self.fade_in_fraction
)
shape.shift((shape.final_position - shape.initial_position) * alpha)
shape.rotate(TAU * alpha, about_point=self.shape_center)
shape.rotate(-TAU * alpha, about_point=shape.get_center_of_mass())
shape.set_opacity(new_opacity)
shape.set_fill(opacity=new_fill_opacity)
shape.set_stroke(opacity=new_stroke_opacity)
class ShowIncreasingSubsets(Animation):
@ -566,6 +573,11 @@ class AddTextLetterByLetter(ShowIncreasingSubsets):
**kwargs,
) -> None:
self.time_per_char = time_per_char
# Check for empty text using family_members_with_points()
if not text.family_members_with_points():
raise ValueError(
f"The text mobject {text} does not seem to contain any characters."
)
if run_time is None:
# minimum time per character is 1/frame_rate, otherwise
# the animation does not finish.
@ -666,3 +678,176 @@ class AddTextWordByWord(Succession):
)
)
super().__init__(*anims, **kwargs)
class TypeWithCursor(AddTextLetterByLetter):
"""Similar to :class:`~.AddTextLetterByLetter` , but with an additional cursor mobject at the end.
Parameters
----------
time_per_char
Frequency of appearance of the letters.
cursor
:class:`~.Mobject` shown after the last added letter.
buff
Controls how far away the cursor is to the right of the last added letter.
keep_cursor_y
If ``True``, the cursor's y-coordinate is set to the center of the ``Text`` and remains the same throughout the animation. Otherwise, it is set to the center of the last added letter.
leave_cursor_on
Whether to show the cursor after the animation.
.. tip::
This is currently only possible for class:`~.Text` and not for class:`~.MathTex`.
Examples
--------
.. manim:: InsertingTextExample
:ref_classes: Blink
class InsertingTextExample(Scene):
def construct(self):
text = Text("Inserting", color=PURPLE).scale(1.5).to_edge(LEFT)
cursor = Rectangle(
color = GREY_A,
fill_color = GREY_A,
fill_opacity = 1.0,
height = 1.1,
width = 0.5,
).move_to(text[0]) # Position the cursor
self.play(TypeWithCursor(text, cursor))
self.play(Blink(cursor, blinks=2))
"""
def __init__(
self,
text: Text,
cursor: Mobject,
buff: float = 0.1,
keep_cursor_y: bool = True,
leave_cursor_on: bool = True,
time_per_char: float = 0.1,
reverse_rate_function=False,
introducer=True,
**kwargs,
) -> None:
self.cursor = cursor
self.buff = buff
self.keep_cursor_y = keep_cursor_y
self.leave_cursor_on = leave_cursor_on
super().__init__(
text,
time_per_char=time_per_char,
reverse_rate_function=reverse_rate_function,
introducer=introducer,
**kwargs,
)
def begin(self) -> None:
self.y_cursor = self.cursor.get_y()
self.cursor.initial_position = self.mobject.get_center()
if self.keep_cursor_y:
self.cursor.set_y(self.y_cursor)
self.cursor.set_opacity(0)
self.mobject.add(self.cursor)
super().begin()
def finish(self) -> None:
if self.leave_cursor_on:
self.cursor.set_opacity(1)
else:
self.cursor.set_opacity(0)
self.mobject.remove(self.cursor)
super().finish()
def clean_up_from_scene(self, scene: Scene) -> None:
if not self.leave_cursor_on:
scene.remove(self.cursor)
super().clean_up_from_scene(scene)
def update_submobject_list(self, index: int) -> None:
for mobj in self.all_submobs[:index]:
mobj.set_opacity(1)
for mobj in self.all_submobs[index:]:
mobj.set_opacity(0)
if index != 0:
self.cursor.next_to(
self.all_submobs[index - 1], RIGHT, buff=self.buff
).set_y(self.cursor.initial_position[1])
else:
self.cursor.move_to(self.all_submobs[0]).set_y(
self.cursor.initial_position[1]
)
if self.keep_cursor_y:
self.cursor.set_y(self.y_cursor)
self.cursor.set_opacity(1)
class UntypeWithCursor(TypeWithCursor):
"""Similar to :class:`~.RemoveTextLetterByLetter` , but with an additional cursor mobject at the end.
Parameters
----------
time_per_char
Frequency of appearance of the letters.
cursor
:class:`~.Mobject` shown after the last added letter.
buff
Controls how far away the cursor is to the right of the last added letter.
keep_cursor_y
If ``True``, the cursor's y-coordinate is set to the center of the ``Text`` and remains the same throughout the animation. Otherwise, it is set to the center of the last added letter.
leave_cursor_on
Whether to show the cursor after the animation.
.. tip::
This is currently only possible for class:`~.Text` and not for class:`~.MathTex`.
Examples
--------
.. manim:: DeletingTextExample
:ref_classes: Blink
class DeletingTextExample(Scene):
def construct(self):
text = Text("Deleting", color=PURPLE).scale(1.5).to_edge(LEFT)
cursor = Rectangle(
color = GREY_A,
fill_color = GREY_A,
fill_opacity = 1.0,
height = 1.1,
width = 0.5,
).move_to(text[0]) # Position the cursor
self.play(UntypeWithCursor(text, cursor))
self.play(Blink(cursor, blinks=2))
"""
def __init__(
self,
text: Text,
cursor: VMobject | None = None,
time_per_char: float = 0.1,
reverse_rate_function=True,
introducer=False,
remover=True,
**kwargs,
) -> None:
super().__init__(
text,
cursor=cursor,
time_per_char=time_per_char,
reverse_rate_function=reverse_rate_function,
introducer=introducer,
remover=remover,
**kwargs,
)

View file

@ -12,7 +12,6 @@
"""
from __future__ import annotations
__all__ = [
@ -31,7 +30,7 @@ from ..constants import ORIGIN
from ..mobject.mobject import Group, Mobject
if TYPE_CHECKING:
from ..scene import Scene
pass
class _Fade(Transform):

View file

@ -25,6 +25,8 @@ Examples
"""
from __future__ import annotations
__all__ = [
"FocusOn",
"Indicate",
@ -34,9 +36,11 @@ __all__ = [
"ApplyWave",
"Circumscribe",
"Wiggle",
"Blink",
]
from typing import Callable, Iterable, Optional, Type, Union
from collections.abc import Iterable
from typing import Callable
import numpy as np
@ -52,12 +56,12 @@ from ..animation.creation import Create, ShowPartial, Uncreate
from ..animation.fading import FadeIn, FadeOut
from ..animation.movement import Homotopy
from ..animation.transform import Transform
from ..animation.updaters.update import UpdateFromFunc
from ..constants import *
from ..mobject.mobject import Mobject
from ..mobject.types.vectorized_mobject import VGroup, VMobject
from ..utils.bezier import interpolate, inverse_interpolate
from ..utils.color import GREY, YELLOW, ParsableManimColor
from ..utils.deprecation import deprecated
from ..utils.rate_functions import smooth, there_and_back, wiggle
from ..utils.space_ops import normalize
@ -75,8 +79,6 @@ class FocusOn(Transform):
The color of the spotlight.
run_time
The duration of the animation.
kwargs
Additional arguments to be passed to the :class:`~.Succession` constructor
Examples
--------
@ -92,11 +94,11 @@ class FocusOn(Transform):
def __init__(
self,
focus_point: Union[np.ndarray, Mobject],
focus_point: np.ndarray | Mobject,
opacity: float = 0.2,
color: str = GREY,
run_time: float = 2,
**kwargs
**kwargs,
) -> None:
self.focus_point = focus_point
self.color = color
@ -129,7 +131,7 @@ class Indicate(Transform):
color
The color the mobject temporally takes.
rate_func
The function definig the animation progress at every point in time.
The function defining the animation progress at every point in time.
kwargs
Additional arguments to be passed to the :class:`~.Succession` constructor
@ -146,17 +148,17 @@ class Indicate(Transform):
def __init__(
self,
mobject: "Mobject",
mobject: Mobject,
scale_factor: float = 1.2,
color: str = YELLOW,
rate_func: Callable[[float, Optional[float]], np.ndarray] = there_and_back,
**kwargs
rate_func: Callable[[float, float | None], np.ndarray] = there_and_back,
**kwargs,
) -> None:
self.color = color
self.scale_factor = scale_factor
super().__init__(mobject, rate_func=rate_func, **kwargs)
def create_target(self) -> "Mobject":
def create_target(self) -> Mobject:
target = self.mobject.copy()
target.scale(self.scale_factor)
target.set_color(self.color)
@ -216,7 +218,7 @@ class Flash(AnimationGroup):
def __init__(
self,
point: Union[np.ndarray, Mobject],
point: np.ndarray | Mobject,
line_length: float = 0.2,
num_lines: int = 12,
flash_radius: float = 0.1,
@ -224,7 +226,7 @@ class Flash(AnimationGroup):
color: str = YELLOW,
time_width: float = 1,
run_time: float = 1.0,
**kwargs
**kwargs,
) -> None:
if isinstance(point, Mobject):
self.point = point.get_center()
@ -254,7 +256,7 @@ class Flash(AnimationGroup):
lines.set_stroke(width=self.line_stroke_width)
return lines
def create_line_anims(self) -> Iterable["ShowPassingFlash"]:
def create_line_anims(self) -> Iterable[ShowPassingFlash]:
return [
ShowPassingFlash(
line,
@ -300,7 +302,7 @@ class ShowPassingFlash(ShowPartial):
"""
def __init__(self, mobject: "VMobject", time_width: float = 0.1, **kwargs) -> None:
def __init__(self, mobject: VMobject, time_width: float = 0.1, **kwargs) -> None:
self.time_width = time_width
super().__init__(mobject, remover=True, introducer=True, **kwargs)
@ -385,14 +387,14 @@ class ApplyWave(Homotopy):
def __init__(
self,
mobject: "Mobject",
mobject: Mobject,
direction: np.ndarray = UP,
amplitude: float = 0.2,
wave_func: Callable[[float], float] = smooth,
time_width: float = 1,
ripples: int = 1,
run_time: float = 2,
**kwargs
**kwargs,
) -> None:
x_min = mobject.get_left()[0]
x_max = mobject.get_right()[0]
@ -403,7 +405,7 @@ class ApplyWave(Homotopy):
# This wave is build up as follows:
# The time is split into 2*ripples phases. In every phase the amplitude
# either rises to one or goes down to zero. Consecutive ripples will have
# their amplitudes in oppising directions (first ripple from 0 to 1 to 0,
# their amplitudes in opposing directions (first ripple from 0 to 1 to 0,
# second from 0 to -1 to 0 and so on). This is how two ripples would be
# divided into phases:
@ -442,7 +444,7 @@ class ApplyWave(Homotopy):
return wave_func(t * phases)
elif phase == phases - 1:
# last ripple. Rising or falling depending on the number of ripples
# The (ripples % 2)-term is used to make this destinction.
# The (ripples % 2)-term is used to make this distinction.
t -= phase / phases # Time relative to the phase
return (1 - wave_func(t * phases)) * (2 * (ripples % 2) - 1)
else:
@ -504,14 +506,14 @@ class Wiggle(Animation):
def __init__(
self,
mobject: "Mobject",
mobject: Mobject,
scale_value: float = 1.1,
rotation_angle: float = 0.01 * TAU,
n_wiggles: int = 6,
scale_about_point: Optional[np.ndarray] = None,
rotate_about_point: Optional[np.ndarray] = None,
scale_about_point: np.ndarray | None = None,
rotate_about_point: np.ndarray | None = None,
run_time: float = 2,
**kwargs
**kwargs,
) -> None:
self.scale_value = scale_value
self.rotation_angle = rotation_angle
@ -532,8 +534,8 @@ class Wiggle(Animation):
def interpolate_submobject(
self,
submobject: "Mobject",
starting_submobject: "Mobject",
submobject: Mobject,
starting_submobject: Mobject,
alpha: float,
) -> None:
submobject.points[:, :] = starting_submobject.points
@ -556,7 +558,7 @@ class Circumscribe(Succession):
mobject
The mobject to be circumscribed.
shape
The shape with which to surrond the given mobject. Should be either
The shape with which to surround the given mobject. Should be either
:class:`~.Rectangle` or :class:`~.Circle`
fade_in
Whether to make the surrounding shape to fade in. It will be drawn otherwise.
@ -593,7 +595,7 @@ class Circumscribe(Succession):
def __init__(
self,
mobject: Mobject,
shape: Type = Rectangle,
shape: type = Rectangle,
fade_in=False,
fade_out=False,
time_width=0.3,
@ -601,7 +603,7 @@ class Circumscribe(Succession):
color: ParsableManimColor = YELLOW,
run_time=1,
stroke_width=DEFAULT_STROKE_WIDTH,
**kwargs
**kwargs,
):
if shape is Rectangle:
frame = SurroundingRectangle(
@ -643,3 +645,68 @@ class Circumscribe(Succession):
super().__init__(
ShowPassingFlash(frame, time_width, run_time=run_time), **kwargs
)
class Blink(Succession):
"""Blink the mobject.
Parameters
----------
mobject
The mobject to be blinked.
time_on
The duration that the mobject is shown for one blink.
time_off
The duration that the mobject is hidden for one blink.
blinks
The number of blinks
hide_at_end
Whether to hide the mobject at the end of the animation.
kwargs
Additional arguments to be passed to the :class:`~.Succession` constructor.
Examples
--------
.. manim:: BlinkingExample
class BlinkingExample(Scene):
def construct(self):
text = Text("Blinking").scale(1.5)
self.add(text)
self.play(Blink(text, blinks=3))
"""
def __init__(
self,
mobject: Mobject,
time_on: float = 0.5,
time_off: float = 0.5,
blinks: int = 1,
hide_at_end: bool = False,
**kwargs,
):
animations = [
UpdateFromFunc(
mobject,
update_function=lambda mob: mob.set_opacity(1.0),
run_time=time_on,
),
UpdateFromFunc(
mobject,
update_function=lambda mob: mob.set_opacity(0.0),
run_time=time_off,
),
] * blinks
if not hide_at_end:
animations.append(
UpdateFromFunc(
mobject,
update_function=lambda mob: mob.set_opacity(1.0),
run_time=time_on,
),
)
super().__init__(*animations, **kwargs)

View file

@ -137,8 +137,7 @@ class PhaseFlow(Animation):
class MoveAlongPath(Animation):
"""Make one mobject move along the path of another mobject.
Example
--------
.. manim:: MoveAlongPathExample
class MoveAlongPathExample(Scene):

View file

@ -1,9 +1,8 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Protocol, Sequence
from typing import TYPE_CHECKING, Protocol
if TYPE_CHECKING:
from .animation import Animation
from .scene_buffer import SceneBuffer
@ -14,17 +13,12 @@ class AnimationProtocol(Protocol):
buffer: SceneBuffer
apply_buffer: bool
def begin(self) -> None:
...
def begin(self) -> None: ...
def finish(self) -> None:
...
def finish(self) -> None: ...
def update_mobjects(self, dt: float) -> None:
...
def update_mobjects(self, dt: float) -> None: ...
def interpolate(self, alpha: float) -> None:
...
def interpolate(self, alpha: float) -> None: ...
def get_run_time(self) -> float:
...
def get_run_time(self) -> float: ...

View file

@ -4,7 +4,8 @@ from __future__ import annotations
__all__ = ["Rotating", "Rotate"]
from typing import TYPE_CHECKING, Callable, Sequence
from collections.abc import Sequence
from typing import TYPE_CHECKING, Callable
import numpy as np
@ -59,7 +60,7 @@ class Rotate(Transform):
about_point
The rotation center.
about_edge
If ``about_point``is ``None``, this argument specifies
If ``about_point`` is ``None``, this argument specifies
the direction of the bounding box point to be taken as
the rotation center.

View file

@ -1,3 +1,5 @@
from __future__ import annotations
from typing import final
from manim.mobject.opengl.opengl_mobject import OpenGLMobject as Mobject

View file

@ -2,7 +2,8 @@ from __future__ import annotations
__all__ = ["Broadcast"]
from typing import Any, Sequence
from collections.abc import Sequence
from typing import Any
from manim.animation.transform import Restore
@ -84,7 +85,7 @@ class Broadcast(LaggedStart):
mob.move_to(self.focal_point)
mob.save_state()
mob.set_width(self.initial_width)
mob.set(width=self.initial_width)
if fill_o:
mob.set_opacity(self.initial_opacity)

View file

@ -2,16 +2,20 @@
from __future__ import annotations
import inspect
import types
from typing import Callable
from typing import TYPE_CHECKING, Callable
from numpy import piecewise
from manim.utils.simple_functions import get_parameters
from ..animation.animation import Animation, Wait, prepare_animation
from ..animation.composition import AnimationGroup
from ..mobject.mobject import Mobject, Updater, _AnimationBuilder
from ..mobject.mobject import Mobject, _AnimationBuilder
if TYPE_CHECKING:
from ..mobject.mobject import Updater
__all__ = ["ChangeSpeed"]
class ChangeSpeed(Animation):
@ -259,8 +263,7 @@ class ChangeSpeed(Animation):
:class:`.ChangeSpeed`
:meth:`.Mobject.add_updater`
"""
parameters = get_parameters(update_function)
if "dt" in parameters:
if "dt" in inspect.signature(update_function).parameters:
mobject.add_updater(
lambda mob, dt: update_function(
mob, ChangeSpeed.dt if ChangeSpeed.is_changing_dt else dt

View file

@ -28,27 +28,26 @@ __all__ = [
import inspect
import types
from typing import TYPE_CHECKING, Any, Callable, Iterable, Sequence
from collections.abc import Iterable, Sequence
from typing import TYPE_CHECKING, Any, Callable
import numpy as np
from manim.mobject.opengl.opengl_mobject import OpenGLGroup, OpenGLMobject
from manim.mobject.opengl.opengl_mobject import OpenGLMobject
from .. import config
from ..animation.animation import Animation
from ..constants import (
DEFAULT_POINTWISE_FUNCTION_RUN_TIME,
DEGREES,
ORIGIN,
OUT,
RendererType,
)
from ..mobject.mobject import Group, Mobject
from ..utils.paths import path_along_arc, path_along_circles
from ..utils.rate_functions import smooth, squish_rate_func
if TYPE_CHECKING:
from ..scene.scene import Scene
pass
class Transform(Animation):

View file

@ -4,7 +4,6 @@ from __future__ import annotations
__all__ = ["TransformMatchingShapes", "TransformMatchingTex"]
from typing import TYPE_CHECKING
import numpy as np
@ -223,7 +222,7 @@ class TransformMatchingShapes(TransformMatchingAbstractBase):
def get_mobject_key(mobject: Mobject) -> int:
mobject.save_state()
mobject.center()
mobject.set_height(1)
mobject.set(height=1)
result = hash(np.round(mobject.points, 3).tobytes())
mobject.restore()
return result

View file

@ -15,22 +15,26 @@ __all__ = [
import inspect
from collections.abc import Callable
from typing import TYPE_CHECKING, Callable
import numpy as np
from manim.constants import DEGREES, RIGHT
from manim.mobject.mobject import Mobject
from manim.opengl import OpenGLMobject
from manim.utils.space_ops import normalize
if TYPE_CHECKING:
from manim.animation.animation import Animation
def assert_is_mobject_method(method):
def assert_is_mobject_method(method: Callable) -> None:
assert inspect.ismethod(method)
mobject = method.__self__
assert isinstance(mobject, (Mobject, OpenGLMobject))
def always(method, *args, **kwargs):
def always(method: Callable, *args, **kwargs) -> Mobject:
assert_is_mobject_method(method)
mobject = method.__self__
func = method.__func__
@ -38,7 +42,7 @@ def always(method, *args, **kwargs):
return mobject
def f_always(method, *arg_generators, **kwargs):
def f_always(method: Callable[[Mobject], None], *arg_generators, **kwargs) -> Mobject:
"""
More functional version of always, where instead
of taking in args, it takes in functions which output
@ -80,16 +84,18 @@ def always_redraw(func: Callable[[], Mobject]) -> Mobject:
sine = ax.plot(np.sin, color=RED)
alpha = ValueTracker(0)
point = always_redraw(
lambda: Dot(
sine.point_from_proportion(alpha.get_value()),
color=BLUE)
lambda: Dot(
sine.point_from_proportion(alpha.get_value()),
color=BLUE
)
)
tangent = always_redraw(
lambda: TangentLine(
sine,
alpha=alpha.get_value(),
color=YELLOW,
length=4)
length=4
)
)
self.add(ax, sine, point, tangent)
self.play(alpha.animate.set_value(1), rate_func=linear, run_time=2)
@ -99,36 +105,110 @@ def always_redraw(func: Callable[[], Mobject]) -> Mobject:
return mob
def always_shift(mobject, direction=RIGHT, rate=0.1):
def normalize(v):
norm = np.linalg.norm(v)
if norm == 0:
return v
return v / norm
def always_shift(
mobject: Mobject, direction: np.ndarray[np.float64] = RIGHT, rate: float = 0.1
) -> Mobject:
"""A mobject which is continuously shifted along some direction
at a certain rate.
Parameters
----------
mobject
The mobject to shift.
direction
The direction to shift. The vector is normalized, the specified magnitude
is not relevant.
rate
Length in Manim units which the mobject travels in one
second along the specified direction.
Examples
--------
.. manim:: ShiftingSquare
class ShiftingSquare(Scene):
def construct(self):
sq = Square().set_fill(opacity=1)
tri = Triangle()
VGroup(sq, tri).arrange(LEFT)
# construct a square which is continuously
# shifted to the right
always_shift(sq, RIGHT, rate=5)
self.add(sq)
self.play(tri.animate.set_fill(opacity=1))
"""
mobject.add_updater(lambda m, dt: m.shift(dt * rate * normalize(direction)))
return mobject
def always_rotate(mobject, rate=20 * DEGREES, **kwargs):
def always_rotate(mobject: Mobject, rate: float = 20 * DEGREES, **kwargs) -> Mobject:
"""A mobject which is continuously rotated at a certain rate.
Parameters
----------
mobject
The mobject to be rotated.
rate
The angle which the mobject is rotated by
over one second.
kwags
Further arguments to be passed to :meth:`.Mobject.rotate`.
Examples
--------
.. manim:: SpinningTriangle
class SpinningTriangle(Scene):
def construct(self):
tri = Triangle().set_fill(opacity=1).set_z_index(2)
sq = Square().to_edge(LEFT)
# will keep spinning while there is an animation going on
always_rotate(tri, rate=2*PI, about_point=ORIGIN)
self.add(tri, sq)
self.play(sq.animate.to_edge(RIGHT), rate_func=linear, run_time=1)
"""
mobject.add_updater(lambda m, dt: m.rotate(dt * rate, **kwargs))
return mobject
def turn_animation_into_updater(animation, cycle=False, **kwargs):
def turn_animation_into_updater(
animation: Animation, cycle: bool = False, **kwargs
) -> Mobject:
"""
Add an updater to the animation's mobject which applies
the interpolation and update functions of the animation
If cycle is True, this repeats over and over. Otherwise,
the updater will be popped upon completion
Examples
--------
.. manim:: WelcomeToManim
class WelcomeToManim(Scene):
def construct(self):
words = Text("Welcome to")
banner = ManimBanner().scale(0.5)
VGroup(words, banner).arrange(DOWN)
turn_animation_into_updater(Write(words, run_time=0.9))
self.add(words)
self.wait(0.5)
self.play(banner.expand(), run_time=0.5)
"""
mobject = animation.mobject
animation.suspend_mobject_updating = False
animation.begin()
animation.total_time = 0
def update(m, dt):
def update(m: Mobject, dt: float):
run_time = animation.get_run_time()
time_ratio = animation.total_time / run_time
if cycle:
@ -147,5 +227,5 @@ def turn_animation_into_updater(animation, cycle=False, **kwargs):
return mobject
def cycle_animation(animation, **kwargs):
def cycle_animation(animation: Animation, **kwargs) -> Mobject:
return turn_animation_into_updater(animation, cycle=True, **kwargs)

View file

@ -2,8 +2,8 @@ from __future__ import annotations
import itertools as it
import math
import sys
from typing import Any, Iterable
from collections.abc import Iterable
from typing import Any
import moderngl
import numpy as np
@ -16,7 +16,6 @@ from manim.renderer.shader_wrapper import ShaderWrapper
from manim.utils.color import BLACK, color_to_rgba
from ..constants import *
from ..constants import RADIANS
from ..utils.simple_functions import fdiv
from ..utils.space_ops import normalize

View file

@ -5,13 +5,12 @@ cfg``. Here you can specify options, subcommands, and subgroups for the cfg
group.
"""
from __future__ import annotations
import os
from ast import literal_eval
from pathlib import Path
import click
import cloup
from rich.errors import StyleSyntaxError
from rich.style import Style
@ -28,6 +27,17 @@ If left empty, the default colour will be used.[/red]
"""
RICH_NON_STYLE_ENTRIES: str = ["log.width", "log.height", "log.timestamps"]
__all__ = [
"value_from_string",
"value_from_string",
"is_valid_style",
"replace_keys",
"cfg",
"write",
"show",
"export",
]
def value_from_string(value: str) -> str | int | bool:
"""Extracts the literal of proper datatype from a string.
@ -123,21 +133,21 @@ def replace_keys(default: dict) -> dict:
epilog=EPILOG,
help="Manages Manim configuration files.",
)
@click.pass_context
@cloup.pass_context
def cfg(ctx):
"""Responsible for the cfg subcommand."""
pass
@cfg.command(context_settings=cli_ctx_settings, no_args_is_help=True)
@click.option(
@cloup.option(
"-l",
"--level",
type=click.Choice(["user", "cwd"], case_sensitive=False),
type=cloup.Choice(["user", "cwd"], case_sensitive=False),
default="cwd",
help="Specify if this config is for user or the working directory.",
)
@click.option("-o", "--open", "openfile", is_flag=True)
@cloup.option("-o", "--open", "openfile", is_flag=True)
def write(level: str = None, openfile: bool = False) -> None:
config_paths = config_file_paths()
console.print(
@ -258,8 +268,8 @@ def show():
@cfg.command(context_settings=cli_ctx_settings)
@click.option("-d", "--directory", default=Path.cwd())
@click.pass_context
@cloup.option("-d", "--directory", default=Path.cwd())
@cloup.pass_context
def export(ctx, directory):
directory_path = Path(directory)
if directory_path.absolute == Path.cwd().absolute:

View file

@ -5,10 +5,9 @@ from __future__ import annotations
import os
import shutil
import subprocess
from typing import Callable
from ..._config import config
__all__ = ["HEALTH_CHECKS"]
HEALTH_CHECKS = []
@ -102,45 +101,6 @@ def is_manim_executable_associated_to_this_library():
return b"manim.__main__" in manim_exec or b'"%~dp0\\manim"' in manim_exec
@healthcheck(
description="Checking whether ffmpeg is available",
recommendation=(
"Manim does not work without ffmpeg. Please follow our "
"installation instructions "
"at https://docs.manim.community/en/stable/installation.html "
"to download ffmpeg. Then, either ...\n\n"
"(a) ... make the ffmpeg executable available to your system's PATH,\n"
"(b) or, alternatively, use <manim cfg write --open> to create a "
"custom configuration and set the ffmpeg_executable variable to the "
"full absolute path to the ffmpeg executable."
),
)
def is_ffmpeg_available():
path_to_ffmpeg = shutil.which(config.ffmpeg_executable)
return path_to_ffmpeg is not None and os.access(path_to_ffmpeg, os.X_OK)
@healthcheck(
description="Checking whether ffmpeg is working",
recommendation=(
"Your installed version of ffmpeg does not support x264 encoding, "
"which manim requires. Please follow our installation instructions "
"at https://docs.manim.community/en/stable/installation.html "
"to download and install a newer version of ffmpeg."
),
skip_on_failed=[is_ffmpeg_available],
)
def is_ffmpeg_working():
ffmpeg_version = subprocess.run(
[config.ffmpeg_executable, "-version"],
stdout=subprocess.PIPE,
).stdout.decode()
return (
ffmpeg_version.startswith("ffmpeg version")
and "--enable-libx264" in ffmpeg_version
)
@healthcheck(
description="Checking whether latex is available",
recommendation=(

View file

@ -12,6 +12,8 @@ import cloup
from .checks import HEALTH_CHECKS
__all__ = ["checkhealth"]
@cloup.command(
context_settings=None,

View file

@ -1,10 +1,20 @@
"""DefaultGroup allows a subcommand to act as the main command
"""``DefaultGroup`` allows a subcommand to act as the main command.
In particular, this class is what allows ``manim`` to act as ``manim render``.
"""
import cloup
from .. import logger
.. note::
This is a vendored version of https://github.com/click-contrib/click-default-group/
under the BSD 3-Clause "New" or "Revised" License.
This library isn't used as a dependency as we need to inherit from ``cloup.Group`` instead
of ``click.Group``.
"""
from __future__ import annotations
import warnings
import cloup
__all__ = ["DefaultGroup"]
@ -54,8 +64,8 @@ class DefaultGroup(cloup.Group):
decorator = super().command(*args, **kwargs)
if not default:
return decorator
logger.log(
"Use default param of DefaultGroup or " "set_default_command() instead",
warnings.warn(
"Use default param of DefaultGroup or set_default_command() instead",
DeprecationWarning,
)

View file

@ -5,6 +5,7 @@ init``. Here you can specify options, subcommands, and subgroups for the init
group.
"""
from __future__ import annotations
import configparser
@ -30,6 +31,8 @@ CFG_DEFAULTS = {
"resolution": (854, 480),
}
__all__ = ["select_resolution", "update_cfg", "project", "scene"]
def select_resolution():
"""Prompts input of type click.Choice from user. Presents options from QUALITIES constant.
@ -47,7 +50,7 @@ def select_resolution():
resolution_options.pop()
choice = click.prompt(
"\nSelect resolution:\n",
type=click.Choice([f"{i[0]}p" for i in resolution_options]),
type=cloup.Choice([f"{i[0]}p" for i in resolution_options]),
show_default=False,
default="480p",
)

View file

@ -1,189 +0,0 @@
from __future__ import annotations
import configparser
from pathlib import Path
import click
import cloup
from ... import console
from ...constants import CONTEXT_SETTINGS, EPILOG, QUALITIES
from ...utils.file_ops import (
add_import_statement,
copy_template_files,
get_template_names,
get_template_path,
)
CFG_DEFAULTS = {
"frame_rate": 30,
"background_color": "BLACK",
"background_opacity": 1,
"scene_names": "Default",
"resolution": (854, 480),
}
def select_resolution():
"""Prompts input of type click.Choice from user. Presents options from QUALITIES constant.
Returns
-------
:class:`tuple`
Tuple containing height and width.
"""
resolution_options = []
for quality in QUALITIES.items():
resolution_options.append(
(quality[1]["pixel_height"], quality[1]["pixel_width"]),
)
resolution_options.pop()
choice = click.prompt(
"\nSelect resolution:\n",
type=click.Choice([f"{i[0]}p" for i in resolution_options]),
show_default=False,
default="480p",
)
return [res for res in resolution_options if f"{res[0]}p" == choice][0]
def update_cfg(cfg_dict: dict, project_cfg_path: Path):
"""Updates the manim.cfg file after reading it from the project_cfg_path.
Parameters
----------
cfg_dict
values used to update manim.cfg found project_cfg_path.
project_cfg_path
Path of manim.cfg file.
"""
config = configparser.ConfigParser()
config.read(project_cfg_path)
cli_config = config["CLI"]
for key, value in cfg_dict.items():
if key == "resolution":
cli_config["pixel_height"] = str(value[0])
cli_config["pixel_width"] = str(value[1])
else:
cli_config[key] = str(value)
with project_cfg_path.open("w") as conf:
config.write(conf)
@cloup.command(
context_settings=CONTEXT_SETTINGS,
epilog=EPILOG,
)
@cloup.argument("project_name", type=Path, required=False)
@cloup.option(
"-d",
"--default",
"default_settings",
is_flag=True,
help="Default settings for project creation.",
nargs=1,
)
def project(default_settings, **args):
"""Creates a new project.
PROJECT_NAME is the name of the folder in which the new project will be initialized.
"""
if args["project_name"]:
project_name = args["project_name"]
else:
project_name = click.prompt("Project Name", type=Path)
# in the future when implementing a full template system. Choices are going to be saved in some sort of config file for templates
template_name = click.prompt(
"Template",
type=click.Choice(get_template_names(), False),
default="Default",
)
if project_name.is_dir():
console.print(
f"\nFolder [red]{project_name}[/red] exists. Please type another name\n",
)
else:
project_name.mkdir()
new_cfg = {}
new_cfg_path = Path.resolve(project_name / "manim.cfg")
if not default_settings:
for key, value in CFG_DEFAULTS.items():
if key == "scene_names":
new_cfg[key] = template_name + "Template"
elif key == "resolution":
new_cfg[key] = select_resolution()
else:
new_cfg[key] = click.prompt(f"\n{key}", default=value)
console.print("\n", new_cfg)
if click.confirm("Do you want to continue?", default=True, abort=True):
copy_template_files(project_name, template_name)
update_cfg(new_cfg, new_cfg_path)
else:
copy_template_files(project_name, template_name)
update_cfg(CFG_DEFAULTS, new_cfg_path)
@cloup.command(
context_settings=CONTEXT_SETTINGS,
no_args_is_help=True,
epilog=EPILOG,
)
@cloup.argument("scene_name", type=str, required=True)
@cloup.argument("file_name", type=str, required=False)
def scene(**args):
"""Inserts a SCENE to an existing FILE or creates a new FILE.
SCENE is the name of the scene that will be inserted.
FILE is the name of file in which the SCENE will be inserted.
"""
if not Path("main.py").exists():
raise FileNotFoundError(f"{Path('main.py')} : Not a valid project directory.")
template_name = click.prompt(
"template",
type=click.Choice(get_template_names(), False),
default="Default",
)
scene = (get_template_path() / f"{template_name}.mtp").resolve().read_text()
scene = scene.replace(template_name + "Template", args["scene_name"], 1)
if args["file_name"]:
file_name = Path(args["file_name"] + ".py")
if file_name.is_file():
# file exists so we are going to append new scene to that file
with file_name.open("a") as f:
f.write("\n\n\n" + scene)
else:
# file does not exist so we create a new file, append the scene and prepend the import statement
file_name.write_text("\n\n\n" + scene)
add_import_statement(file_name)
else:
# file name is not provided so we assume it is main.py
# if main.py does not exist we do not continue
with Path("main.py").open("a") as f:
f.write("\n\n\n" + scene)
@cloup.group(
context_settings=CONTEXT_SETTINGS,
invoke_without_command=True,
no_args_is_help=True,
epilog=EPILOG,
help="Create a new project or insert a new scene.",
deprecated=True,
)
@cloup.pass_context
def new(ctx):
pass
new.add_command(project)
new.add_command(scene)

View file

@ -5,6 +5,7 @@ plugin``. Here you can specify options, subcommands, and subgroups for the plugi
group.
"""
from __future__ import annotations
import cloup
@ -12,6 +13,8 @@ import cloup
from ...constants import CONTEXT_SETTINGS, EPILOG
from ...plugins.plugins_flags import list_plugins
__all__ = ["plugins"]
@cloup.command(
context_settings=CONTEXT_SETTINGS,

View file

@ -5,15 +5,18 @@ Manim's render subcommand is accessed in the command-line interface via
can specify options, and arguments for the render command.
"""
from __future__ import annotations
import http.client
import json
import sys
import urllib.error
import urllib.request
from pathlib import Path
from typing import cast
import click
import cloup
import requests
from ... import __version__, config, console, error_console, logger
from ..._config import tempconfig
@ -24,14 +27,16 @@ from .global_options import global_options
from .output_options import output_options
from .render_options import render_options
__all__ = ["render"]
@cloup.command(
context_settings=None,
no_args_is_help=True,
epilog=EPILOG,
)
@click.argument("file", type=Path, required=True)
@click.argument("scene_names", required=False, nargs=-1)
@cloup.argument("file", type=Path, required=True)
@cloup.argument("scene_names", required=False, nargs=-1)
@global_options
@output_options
@render_options # type: ignore
@ -110,13 +115,26 @@ def render(
if config.notify_outdated_version:
manim_info_url = "https://pypi.org/pypi/manim/json"
warn_prompt = "Cannot check if latest release of manim is installed"
req_info = {}
try:
req_info = requests.get(manim_info_url, timeout=10)
req_info.raise_for_status()
stable = req_info.json()["info"]["version"]
with urllib.request.urlopen(
urllib.request.Request(manim_info_url),
timeout=10,
) as response:
response = cast(http.client.HTTPResponse, response)
json_data = json.loads(response.read())
except urllib.error.HTTPError:
logger.debug("HTTP Error: %s", warn_prompt)
except urllib.error.URLError:
logger.debug("URL Error: %s", warn_prompt)
except json.JSONDecodeError:
logger.debug(
"Error while decoding JSON from %r: %s", manim_info_url, warn_prompt
)
except Exception:
logger.debug("Something went wrong: %s", warn_prompt)
else:
stable = json_data["info"]["version"]
if stable != __version__:
console.print(
f"You are using manim version [red]v{__version__}[/red], but version [green]v{stable}[/green] is available.",
@ -124,16 +142,5 @@ def render(
console.print(
"You should consider upgrading via [yellow]pip install -U manim[/yellow]",
)
except requests.exceptions.HTTPError:
logger.debug(f"HTTP Error: {warn_prompt}")
except requests.exceptions.ConnectionError:
logger.debug(f"Connection Error: {warn_prompt}")
except requests.exceptions.Timeout:
logger.debug(f"Timed Out: {warn_prompt}")
except json.JSONDecodeError:
logger.debug(warn_prompt)
logger.debug(f"Error decoding JSON from {manim_info_url}")
except Exception:
logger.debug(f"Something went wrong: {warn_prompt}")
return args

View file

@ -1,7 +1,8 @@
from __future__ import annotations
import click
from cloup import option, option_group
from cloup import Choice, option, option_group
__all__ = ["ease_of_access_options"]
ease_of_access_options = option_group(
"Ease of access options",
@ -9,7 +10,7 @@ ease_of_access_options = option_group(
"--progress_bar",
default=None,
show_default=False,
type=click.Choice(
type=Choice(
["display", "leave", "none"],
case_sensitive=False,
),

Some files were not shown because too many files have changed in this diff Show more