Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically identifies the class name based on the specified line number. #2280

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions manimlib/default_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
# you are running manim. For 3blue1brown, for instance, mind is
# here: https://github.com/3b1b/videos/blob/master/custom_config.yml

# Alternatively, you can create it whereever you like, and on running
# Alternatively, you can create it where ever you like, and on running
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Alternatively, you can create it where ever you like, and on running
# Alternatively, you can create it wherever you like, and on running

See the Cambridge dictionary

# manim, pass in `--config_file /path/to/custom/config/file.yml`

directories:
# Set this to true if you want the path to video files
# to match the directory structure of the path to the
# sourcecode generating that video
# source code generating that video
mirror_module_path: False
# Manim may write to and read from the file system, e.g.
# to render videos and to look for svg/png assets. This
Expand Down Expand Up @@ -44,7 +44,7 @@ window:
# If not full screen, the default to give it half the screen width
full_screen: False
# Other optional specifications that override the above include:
# position: (500, 500) # Specific position, in pixel coordiantes, for upper right corner
# position: (500, 500) # Specific position, in pixel coordinates, for upper right corner
# size: (1920, 1080) # Specific size, in pixels
camera:
resolution: (1920, 1080)
Expand Down
26 changes: 20 additions & 6 deletions manimlib/extract_scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from manimlib.scene.scene import Scene

from typing import TYPE_CHECKING

if TYPE_CHECKING:
Module = importlib.util.types.ModuleType
from typing import Optional
Expand Down Expand Up @@ -142,35 +143,48 @@ def get_indent(code_lines: list[str], line_number: int) -> str:
return n_spaces * " "


def insert_embed_line_to_module(module: Module, line_number: int):
def insert_embed_line_to_module(module: Module, run_config: Dict) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing run_config inside here, an alternative could be to return the scene names from this function and then update the scene_names of run_config from somewhere outside, e.g. in get_module that is calling insert_embed_line_to_module).

"""
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()
line_number = run_config.embed_line

# 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)

# When the user executes the `-e <line_number>` command,
# it should automatically identifies the nearest class
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# it should automatically identifies the nearest class
# it should automatically identify the nearest class

# defined above `<line_number>` as 'scene_names'.
classes = list(filter(lambda line: line.startswith("class"), lines[:line_number]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about classes that are defined as nested class, i.e. inside some other classes? They would have an indentation so line.startswith("class") would return False.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the Scene Class (like: class SomeName(Scene)) would not be the nested one. So, I think in that case as well, it works.

if classes:
from re import search

name_search = search(r"(\w+)\(", classes[-1])
run_config.update(scene_names=[name_search.group(1)])
else:
log.error(f"No 'class' has been found above {line_number}!")

# Execute the code, which presumably redefines the user's
# scene to include this embed line, within the relevant module.
code_object = compile(new_code, module.__name__, 'exec')
exec(code_object, module.__dict__)


def get_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)
def get_module(run_config: Dict) -> Module:
module = ModuleLoader.get_module(run_config.file_name, run_config.is_reload)
if run_config.embed_line:
insert_embed_line_to_module(module, run_config)
return module


def main(scene_config: Dict, run_config: Dict):
module = get_module(run_config.file_name, run_config.embed_line, run_config.is_reload)
module = get_module(run_config)
all_scene_classes = get_scene_classes(module)
scenes = get_scenes_to_render(all_scene_classes, scene_config, run_config)
if len(scenes) == 0:
Expand Down
1 change: 1 addition & 0 deletions manimlib/mobject/probability.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def __init__(
fill_opacity=fill_opacity,
stroke_width=stroke_width,
stroke_color=stroke_color,
**kwargs
)
self.default_label_scale_val = default_label_scale_val

Expand Down
4 changes: 2 additions & 2 deletions manimlib/mobject/svg/string_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ def mobjects_from_svg_string(self, svg_string: str) -> list[VMobject]:
# of submobject which are and use those for labels
unlabelled_submobs = submobs
labelled_content = self.get_content(is_labelled=True)
labelled_file = self.get_file_path_by_content(labelled_content)
labelled_submobs = super().mobjects_from_file(labelled_file)
labelled_file = self.get_svg_string_by_content(labelled_content)
labelled_submobs = super().mobjects_from_svg_string(labelled_file)
self.labelled_submobs = labelled_submobs
self.unlabelled_submobs = unlabelled_submobs

Expand Down
3 changes: 0 additions & 3 deletions manimlib/mobject/svg/text_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,6 @@ def __init__(
self.disable_ligatures = disable_ligatures
self.isolate = isolate

if not isinstance(self, Text):
self.validate_markup_string(text)

super().__init__(text, height=height, **kwargs)

if self.t2g:
Expand Down