Move get_scene_module logic to extract_scene.py

This commit is contained in:
Grant Sanderson 2024-12-06 12:24:16 -07:00
parent e270f5c3d3
commit 90dfb02cc6
3 changed files with 58 additions and 43 deletions

View file

@ -14,13 +14,11 @@ from pathlib import Path
from functools import lru_cache
from manimlib.logger import log
from manimlib.module_loader import ModuleLoader
from manimlib.utils.dict_ops import merge_dicts_recursively
from manimlib.utils.init_config import init_customization
from typing import TYPE_CHECKING
if TYPE_CHECKING:
Module = importlib.util.types.ModuleType
from typing import Optional
@ -207,43 +205,6 @@ def get_manim_dir():
return os.path.abspath(os.path.join(manimlib_dir, ".."))
def get_indent(code_lines: list[str], line_number: int) -> str:
for line in code_lines[line_number - 1::-1]:
if len(line.strip()) == 0:
continue
n_spaces = len(line) - len(line.lstrip())
if line.endswith(":"):
n_spaces += 4
return n_spaces * " "
return ""
def insert_embed_line_to_module(module: Module, line_number: int):
"""
This is hacky, but convenient. When user includes the argument "-e", it will try
to recreate a file that inserts the line `self.embed()` into the end of the scene's
construct method. If there is an argument passed in, it will insert the line after
the last line in the sourcefile which includes that string.
"""
lines = inspect.getsource(module).splitlines()
# Add the relevant embed line to the code
indent = get_indent(lines, line_number)
lines.insert(line_number, indent + "self.embed()")
new_code = "\n".join(lines)
code_object = compile(new_code, module.__name__, 'exec')
exec(code_object, module.__dict__)
return module
def get_scene_module(args: Namespace) -> Module:
from manimlib.reload_manager import reload_manager
module = ModuleLoader.get_module(args.file, is_during_reload=reload_manager.is_reload)
if args.embed:
insert_embed_line_to_module(module, int(args.embed))
return module
def load_yaml(file_path: str):
try:
with open(file_path, "r") as file:
@ -435,7 +396,9 @@ def get_scene_config(args: Namespace) -> dict:
def get_run_config(args: Namespace):
window_config = get_window_config(args, get_global_config())
return {
"module": get_scene_module(args),
"file_name": args.file,
"embed_line": int(args.embed) if args.embed is not None else None,
"is_reload": False,
"prerun": args.prerun,
"scene_names": args.scene_names,
"quiet": args.quiet or args.write_all,

View file

@ -1,12 +1,21 @@
from __future__ import annotations
import copy
import inspect
import sys
from manimlib.module_loader import ModuleLoader
from manimlib.config import get_global_config
from manimlib.logger import log
from manimlib.scene.interactive_scene import InteractiveScene
from manimlib.scene.scene import Scene
from typing import TYPE_CHECKING
if TYPE_CHECKING:
Module = importlib.util.types.ModuleType
from typing import Optional
class BlankScene(InteractiveScene):
def construct(self):
@ -115,10 +124,52 @@ def get_scene_classes_from_module(module):
]
def get_indent(code_lines: list[str], line_number: int) -> str:
for line in code_lines[line_number - 1::-1]:
if len(line.strip()) == 0:
continue
n_spaces = len(line) - len(line.lstrip())
if line.endswith(":"):
n_spaces += 4
return n_spaces * " "
return ""
def insert_embed_line_to_module(module: Module, line_number: int):
"""
This is hacky, but convenient. When user includes the argument "-e", it will try
to recreate a file that inserts the line `self.embed()` into the end of the scene's
construct method. If there is an argument passed in, it will insert the line after
the last line in the sourcefile which includes that string.
"""
lines = inspect.getsource(module).splitlines()
# Add the relevant embed line to the code
indent = get_indent(lines, line_number)
lines.insert(line_number, indent + "self.embed()")
new_code = "\n".join(lines)
code_object = compile(new_code, module.__name__, 'exec')
exec(code_object, module.__dict__)
return module
def get_scene_module(file_name: Optional[str], embed_line: Optional[int], is_reload: bool = False) -> Module:
module = ModuleLoader.get_module(file_name, is_reload)
if embed_line:
insert_embed_line_to_module(module, embed_line)
return module
def main(scene_config, run_config):
if run_config["module"] is None:
module = get_scene_module(
run_config["file_name"],
run_config["embed_line"],
run_config["is_reload"]
)
if module is None:
# If no module was passed in, just play the blank scene
return [BlankScene(**scene_config)]
all_scene_classes = get_scene_classes_from_module(run_config["module"])
all_scene_classes = get_scene_classes_from_module(module)
return get_scenes_to_render(all_scene_classes, scene_config, run_config)

View file

@ -66,11 +66,12 @@ class ReloadManager:
# Args to Config
scene_config = manimlib.config.get_scene_config(self.args)
run_config = manimlib.config.get_run_config(self.args)
run_config.update(is_reload=self.is_reload)
# Create or reuse window
if run_config["show_in_window"] and not self.window:
self.window = Window(**run_config["window_config"])
scene_config["window"] = self.window
scene_config.update(window=self.window)
# Scenes
self.scenes = manimlib.extract_scene.main(scene_config, run_config)