diff --git a/manim/__init__.py b/manim/__init__.py index 505db0fb4e..2bf9147035 100644 --- a/manim/__init__.py +++ b/manim/__init__.py @@ -4,7 +4,7 @@ from . import constants -def main(): +def main(): args = config.parse_cli() cfg = config.get_configuration(args) config.initialize_directories(cfg) diff --git a/manim/camera/camera.py b/manim/camera/camera.py index a0985388ff..5a76684b98 100644 --- a/manim/camera/camera.py +++ b/manim/camera/camera.py @@ -10,6 +10,7 @@ import numpy as np from ..constants import * +from ..logger import logger from ..mobject.types.image_mobject import AbstractImageMobject from ..mobject.mobject import Mobject from ..mobject.types.point_cloud_mobject import PMobject @@ -24,7 +25,6 @@ from ..utils.space_ops import angle_of_vector from ..utils.space_ops import get_norm - class Camera(object): """ Base Camera class. @@ -348,14 +348,14 @@ def make_background_from_func(self, coords_to_colors_func): The pixel array which can then be passed to set_background. """ - print("Starting set_background; for reference, the current time is ", time.strftime("%H:%M:%S")) + logger.info("Starting set_background; for reference, the current time is ", time.strftime("%H:%M:%S")) coords = self.get_coords_of_all_pixels() new_background = np.apply_along_axis( coords_to_colors_func, 2, coords ) - print("Ending set_background; for reference, the current time is ", time.strftime("%H:%M:%S")) + logger.info("Ending set_background; for reference, the current time is ", time.strftime("%H:%M:%S")) return self.convert_pixel_array(new_background, convert_from_floats=True) diff --git a/manim/config.py b/manim/config.py index 01dce9102a..b511fe342d 100644 --- a/manim/config.py +++ b/manim/config.py @@ -6,6 +6,7 @@ from . import constants from . import dirs +from .logger import logger def parse_cli(): try: @@ -138,7 +139,7 @@ def parse_cli(): ) return parser.parse_args() except argparse.ArgumentError as err: - print(str(err)) + logger.error(str(err)) sys.exit(2) @@ -225,8 +226,8 @@ def get_camera_configuration(args): try: camera_config["background_color"] = colour.Color(args.color) except AttributeError as err: - print("Please use a valid color") - print(err) + logger.warning("Please use a valid color") + logger.error(err) sys.exit(2) # If rendering a transparent image/move, make sure the diff --git a/manim/constants.py b/manim/constants.py index 23769bbdb5..c1b2e8687b 100644 --- a/manim/constants.py +++ b/manim/constants.py @@ -1,11 +1,11 @@ import numpy as np import os +from .logger import logger NOT_SETTING_FONT_MSG=''' -Warning: -You haven't set a font. -If you are not using English, this may cause text rendering problems. -You set fonts like: +You haven't set font. +If you are not using English, this may cause text rendering problem. +You set font like: text = Text('your text', font='your font') or: class MyText(Text): diff --git a/manim/extract_scene.py b/manim/extract_scene.py index 27f9e1fbd5..e0d750af9c 100644 --- a/manim/extract_scene.py +++ b/manim/extract_scene.py @@ -11,6 +11,7 @@ from .utils.sounds import play_error_sound from .utils.sounds import play_finish_sound from . import constants +from .logger import logger def open_file_if_needed(file_writer, **config): @@ -83,7 +84,7 @@ def prompt_user_for_choice(scene_classes): for num_str in user_input.split(",") ] except KeyError: - print(constants.INVALID_NUMBER_MESSAGE) + logger.error(constants.INVALID_NUMBER_MESSAGE) sys.exit(2) user_input = input(constants.CHOOSE_NUMBER_MESSAGE) return [ @@ -96,7 +97,7 @@ def prompt_user_for_choice(scene_classes): def get_scenes_to_render(scene_classes, config): if len(scene_classes) == 0: - print(constants.NO_SCENE_MESSAGE) + logger.error(constants.NO_SCENE_MESSAGE) return [] if config["write_all"]: return scene_classes @@ -109,11 +110,10 @@ def get_scenes_to_render(scene_classes, config): found = True break if not found and (scene_name != ""): - print( + logger.error( constants.SCENE_NOT_FOUND_MESSAGE.format( scene_name - ), - file=sys.stderr + ) ) if result: return result @@ -141,7 +141,7 @@ def get_module(file_name): exec(code, module.__dict__) return module except Exception as e: - print(f"Failed to render scene: {str(e)}") + logger.error(f"Failed to render scene: {str(e)}") sys.exit(2) else: module_name = file_name.replace(os.sep, ".").replace(".py", "") diff --git a/manim/logger.py b/manim/logger.py new file mode 100644 index 0000000000..416a06a801 --- /dev/null +++ b/manim/logger.py @@ -0,0 +1,12 @@ +import logging +from rich.logging import RichHandler + + +logging.basicConfig( + level="NOTSET", + format="%(message)s", + datefmt="[%X]", + handlers=[RichHandler()] +) + +logger = logging.getLogger("rich") diff --git a/manim/mobject/svg/text_mobject.py b/manim/mobject/svg/text_mobject.py index 64da1c4dc2..f229a95ba1 100644 --- a/manim/mobject/svg/text_mobject.py +++ b/manim/mobject/svg/text_mobject.py @@ -7,6 +7,7 @@ from ...constants import * from ... import dirs from ...container.container import Container +from ...logger import logger from ...mobject.geometry import Dot, Rectangle from ...mobject.svg.svg_mobject import SVGMobject from ...mobject.types.vectorized_mobject import VGroup @@ -289,7 +290,7 @@ def text2svg(self): if self.font == '': if NOT_SETTING_FONT_MSG != '': - print(NOT_SETTING_FONT_MSG) + logger.warning(NOT_SETTING_FONT_MSG) dir_name = dirs.TEXT_DIR hash_name = self.text2hash() diff --git a/manim/mobject/vector_field.py b/manim/mobject/vector_field.py index 50a5bd82ec..774b753eee 100644 --- a/manim/mobject/vector_field.py +++ b/manim/mobject/vector_field.py @@ -5,7 +5,7 @@ import random from ..constants import * - +from ..logger import logger from ..animation.composition import AnimationGroup from ..animation.indication import ShowPassingFlash from ..mobject.geometry import Vector @@ -85,7 +85,7 @@ def get_color_field_image_file(scalar_func, file_name = "%d.png" % func_hash full_path = os.path.join(RASTER_IMAGE_DIR, file_name) if not os.path.exists(full_path): - print("Rendering color field image " + str(func_hash)) + logger.info("Rendering color field image " + str(func_hash)) rgb_gradient_func = get_rgb_gradient_function( min_value=min_value, max_value=max_value, diff --git a/manim/scene/scene.py b/manim/scene/scene.py index 1dac19dfdf..ce24579c48 100644 --- a/manim/scene/scene.py +++ b/manim/scene/scene.py @@ -11,6 +11,7 @@ from ..camera.camera import Camera from ..constants import * from ..container.container import Container +from ..logger import logger from ..mobject.mobject import Mobject from ..scene.scene_file_writer import SceneFileWriter from ..utils.iterables import list_update @@ -110,7 +111,7 @@ def print_end_message(self): Used internally to print the number of animations played after the scene ends. """ - print("Played {} animations".format(self.num_plays)) + logger.info("Played {} animations".format(self.num_plays)) def set_variables_as_attrs(self, *objects, **newly_named_objects): """ diff --git a/manim/scene/scene_file_writer.py b/manim/scene/scene_file_writer.py index 5467ed59e7..820e25ea8c 100644 --- a/manim/scene/scene_file_writer.py +++ b/manim/scene/scene_file_writer.py @@ -13,6 +13,7 @@ from ..constants import STREAMING_PORT from ..constants import STREAMING_PROTOCOL from .. import dirs +from ..logger import logger from ..utils.config_ops import digest_config from ..utils.file_ops import guarantee_existence from ..utils.file_ops import add_extension_if_not_present @@ -467,7 +468,7 @@ def combine_movie_files(self): **kwargs ) if len(partial_movie_files) == 0: - print("No animations in this scene") + logger.error("No animations in this scene") return # Write a file partial_file_list.txt containing all @@ -536,4 +537,4 @@ def print_file_ready_message(self, file_path): """ Prints the "File Ready" message to STDOUT. """ - print("\nFile ready at {}\n".format(file_path)) + logger.info("\nFile ready at {}\n".format(file_path)) diff --git a/manim/scene/scene_from_video.py b/manim/scene/scene_from_video.py index ba3e6562ec..170c6f0162 100644 --- a/manim/scene/scene_from_video.py +++ b/manim/scene/scene_from_video.py @@ -2,6 +2,7 @@ import cv2 from ..scene.scene import Scene +from ..logger import logger # TODO, is this depricated? @@ -24,7 +25,7 @@ def construct(self, file_name, start_frame, end_frame = [fps * t for t in time_range] frame_count = end_frame - start_frame - print("Reading in " + file_name + "...") + logger.info("Reading in " + file_name + "...") for count in show_progress(list(range(start_frame, end_frame + 1))): returned, frame = cap.read() if not returned: diff --git a/manim/utils/tex_file_writing.py b/manim/utils/tex_file_writing.py index 78cf60ba32..e3951187d6 100644 --- a/manim/utils/tex_file_writing.py +++ b/manim/utils/tex_file_writing.py @@ -6,6 +6,7 @@ from ..constants import TEX_TEXT_TO_REPLACE from ..constants import TEX_USE_CTEX from .. import dirs +from ..logger import logger def tex_hash(expression, template_tex_file_body): id_str = str(expression + template_tex_file_body) @@ -27,7 +28,7 @@ def generate_tex_file(expression, template_tex_file_body): tex_hash(expression, template_tex_file_body) ) + ".tex" if not os.path.exists(result): - print("Writing \"%s\" to %s" % ( + logger.info("Writing \"%s\" to %s" % ( "".join(expression), result )) new_body = template_tex_file_body.replace( diff --git a/requirements.txt b/requirements.txt index 9b54f76ae4..7dec25c9b3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ opencv-python pycairo pydub pygments -pyreadline; sys_platform == 'win32' +pyreadline; sys_platform == 'win32', +rich diff --git a/setup.py b/setup.py index 688d12981a..51b8279813 100755 --- a/setup.py +++ b/setup.py @@ -26,5 +26,6 @@ "pydub", "pygments", "pyreadline; sys_platform == 'win32'", + "rich" ], )