Skip to content

Commit bfe3f1e

Browse files
Fix jupyter
1 parent 8f131f0 commit bfe3f1e

File tree

4 files changed

+34
-76
lines changed

4 files changed

+34
-76
lines changed

manim/_config/default.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ show_in_file_browser = False
4040
verbosity = INFO
4141

4242
# --progress_bar
43-
progress_bar = show
43+
progress_bar = display
4444

4545
# -o, --output_file
4646
output_file =

manim/_config/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ def digest_file(self, filename: str) -> "ManimConfig":
758758
progress_bar = property(
759759
lambda self: self._d["progress_bar"],
760760
lambda self, val: self._set_from_list(
761-
"progress_bar", val, ["none", "show", "leave"]
761+
"progress_bar", val, ["none", "display", "leave"]
762762
),
763763
doc="Whether to show progress bars while rendering animations.",
764764
)

manim/cli/render/commands.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ def open_file_if_needed(file_writer):
246246
help="Show the output file in the file browser.",
247247
)
248248
@optgroup.option("--sound", is_flag=True, help="Play a success/failure sound.")
249+
@optgroup.option("--jupyter", is_flag=True, help="Using jupyter notebook magic.")
249250
@click.pass_context
250251
def render(
251252
ctx,
@@ -275,6 +276,7 @@ def render(
275276
preview,
276277
show_in_file_browser,
277278
sound,
279+
jupyter,
278280
):
279281
"""Render SCENE(S) from the input FILE.
280282
@@ -310,6 +312,7 @@ def render(
310312
"preview": preview,
311313
"show_in_file_browser": show_in_file_browser,
312314
"sound": sound,
315+
"jupyter": jupyter,
313316
}
314317

315318
class ClickArgs:
@@ -327,8 +330,13 @@ def __eq__(self, other):
327330

328331
def __contains__(self, key):
329332
return key in self.__dict__
333+
334+
def __repr__(self):
335+
return str(self.__dict__)
330336

331337
click_args = ClickArgs(args)
338+
if jupyter:
339+
return config
332340
config.digest_args(click_args)
333341

334342
if webgl_renderer:

manim/utils/ipython_magic.py

Lines changed: 24 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
"""Utilities for using Manim with IPython (in particular: Jupyter notebooks)"""
22

3-
import hashlib
43
import mimetypes
5-
import os
6-
import shutil
74
from pathlib import Path
85

9-
from manim import config, tempconfig
6+
from manim.__main__ import main
7+
from click.testing import CliRunner
108

119
try:
12-
from IPython import get_ipython
1310
from IPython.core.magic import (
1411
Magics,
1512
magics_class,
@@ -62,73 +59,26 @@ def construct(self):
6259
"""
6360
if cell:
6461
exec(cell, local_ns)
65-
66-
cli_args = ["manim", ""] + line.split()
67-
if len(cli_args) == 2:
68-
# empty line.split(): no commands have been passed, call with -h
69-
cli_args.append("-h")
70-
71-
class ClickArgs:
72-
def __init__(self, args):
73-
for name in args:
74-
setattr(self, name, args[name])
75-
76-
def _get_kwargs(self):
77-
return list(self.__dict__.items())
78-
79-
def __eq__(self, other):
80-
if not isinstance(other, ClickArgs):
81-
return NotImplemented
82-
return vars(self) == vars(other)
83-
84-
def __contains__(self, key):
85-
return key in self.__dict__
86-
87-
try:
88-
args = ClickArgs(cli_args)
89-
except SystemExit:
90-
return # probably manim -h was called, process ended preemptively
91-
92-
with tempconfig(local_ns.get("config", {})):
93-
config.digest_args(args)
94-
95-
exec(f"{config['scene_names'][0]}().render()", local_ns)
96-
local_path = Path(config["output_file"]).relative_to(Path.cwd())
97-
tmpfile = (
98-
Path(config["media_dir"])
99-
/ "jupyter"
100-
/ f"{_video_hash(local_path)}{local_path.suffix}"
101-
)
102-
103-
if local_path in self.rendered_files:
104-
self.rendered_files[local_path].unlink()
105-
self.rendered_files[local_path] = tmpfile
106-
os.makedirs(tmpfile.parent, exist_ok=True)
107-
shutil.copy(local_path, tmpfile)
108-
109-
file_type = mimetypes.guess_type(config["output_file"])[0]
110-
if file_type.startswith("image"):
111-
display(Image(filename=config["output_file"]))
112-
return
113-
114-
# videos need to be embedded when running in google colab
115-
video_embed = "google.colab" in str(get_ipython())
116-
117-
display(
118-
Video(
119-
tmpfile,
120-
html_attributes='controls autoplay loop style="max-width: 100%;"',
121-
embed=video_embed,
122-
)
62+
args = line.split()
63+
if not len(args) or "-h" in args or "--help" in args or "--version" in args:
64+
main.main(args, standalone_mode=False)
65+
return
66+
67+
runner = CliRunner() # This runs the command.
68+
result = runner.invoke(main, args, input=cell)
69+
70+
config = main.main(["--jupyter"]+args, standalone_mode=False) # This runs the render subcommand, but returns config
71+
file = Path(config.output_file)
72+
73+
file_type = mimetypes.guess_type(file)[0]
74+
if file_type.startswith("image"):
75+
display(Image(filename=config["output_file"]))
76+
return
77+
78+
display(
79+
Video(
80+
file,
81+
html_attributes='controls autoplay loop style="max-width: 100%;"',
82+
embed=True,
12383
)
124-
125-
126-
def _video_hash(path):
127-
sha1 = hashlib.sha1()
128-
with open(path, "rb") as f:
129-
while True:
130-
data = f.read(65536)
131-
if not data:
132-
break
133-
sha1.update(data)
134-
return sha1.hexdigest()
84+
)

0 commit comments

Comments
 (0)