Skip to content

Implement Logging of Terminal Output to a .log file. #180

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

Merged
merged 36 commits into from
Aug 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
876ab24
Implemented logging of terminal output to file.
Jul 8, 2020
5611a31
Set default config values for log_to_file, log_dir
Jul 8, 2020
e9d9b29
Change default log_dir to ./logs
Jul 8, 2020
a6c4151
Bring log-file up to date with Master.
Jul 10, 2020
980b947
Merge branch 'master' into log-file
Jul 20, 2020
8c771ec
Re-implement logging of Terminal output to log file.
Jul 20, 2020
33efe31
Move log _writing_ statements to separate function.
Jul 20, 2020
5549f3a
Add a test for logging.
Jul 20, 2020
175b6c7
Added test to check if logs generated are same.
Jul 21, 2020
aa0415c
Added model log file.
Jul 21, 2020
f35032b
Test on this branch
Jul 21, 2020
cdce065
Change Regex expression for windows.
Jul 21, 2020
219600c
Print log on failure
Jul 21, 2020
bb914ef
Print log windows.
Jul 21, 2020
7749bf4
Edit regex expression for both unix and windows.
Jul 21, 2020
7604d53
Edit regex expression.
Jul 21, 2020
366d202
Edit expected log.
Jul 21, 2020
b2daaeb
Try stripping whitespace.
Jul 21, 2020
44ce406
Move test_logging to a separate file.
Jul 21, 2020
40b2b70
Print log for all OS's
Jul 22, 2020
6df05c0
Make rules for passing looser.
Jul 22, 2020
ad5ae6f
Fix a typo
Jul 22, 2020
cabd956
Split string before cleaning.
Jul 22, 2020
60a11de
Change testing method for log files.
Jul 22, 2020
bd485d8
Remove duplicate test_logging file.
Jul 22, 2020
64e8d2a
Move default log directory into media directory.
Aathish04 Jul 29, 2020
19a7c7c
Ignored Line Numbers during test.
Aathish04 Jul 29, 2020
e63ce10
Allow changing of Max width and height of logs via config files.
Aathish04 Aug 3, 2020
53420f0
Implemented word-for-word tests for log file.
Aathish04 Aug 3, 2020
e375a48
Merge branch 'master' into log-file
Aathish04 Aug 3, 2020
232b7c9
Formatted as per black's wishes.
Aathish04 Aug 3, 2020
2329b1a
Merge branch 'log-file' of https://github.com/ManimCommunity/manim in…
Aathish04 Aug 3, 2020
fac22b3
Add cfg subcmd case for log_width and height.
Aathish04 Aug 3, 2020
1ca28b2
Make regex remove list indicators as well.
Aathish04 Aug 3, 2020
cc574f3
Make regex remove timestamps.
Aathish04 Aug 3, 2020
1f51a2d
Added a comment about the monstrous regex.
Aathish04 Aug 3, 2020
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
8 changes: 8 additions & 0 deletions manim/default.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ output_file =
# --leave_progress_bars
leave_progress_bars = False

# --log_to_file
log_to_file = False

# -c, --color
background_color = BLACK

Expand All @@ -67,6 +70,9 @@ upto_animation_number = -1
# --media_dir
media_dir = ./media

# --log_dir
log_dir = %(media_dir)s/logs

# # --video_dir
# video_dir = %(MEDIA_DIR)s/videos

Expand Down Expand Up @@ -153,3 +159,5 @@ log_level =
log_time = cyan dim
log_message =
log_path = dim
log_width = -1
log_height = -1
31 changes: 21 additions & 10 deletions manim/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,39 @@ def parse_theme(fp):
config_parser.read(fp)
theme = dict(config_parser["logger"])
# replaces `_` by `.` as rich understands it
for key in theme:
temp = theme[key]
del theme[key]
key = key.replace("_", ".")
theme[key] = temp
theme = dict(
zip([key.replace("_", ".") for key in theme.keys()], list(theme.values()))
)

theme["log.width"] = None if theme["log.width"] == "-1" else int(theme["log.width"])

theme["log.height"] = (
None if theme["log.height"] == "-1" else int(theme["log.height"])
)
try:
customTheme = Theme(theme)
customTheme = Theme(
{k: v for k, v in theme.items() if k not in ["log.width", "log.height"]}
)
except (color.ColorParseError, errors.StyleSyntaxError):
customTheme = None
printf(
"[logging.level.error]It seems your colour configuration couldn't be parsed. Loading the default color configuration...[/logging.level.error]"
)
return customTheme
return customTheme, theme


config_items = _run_config()
config_parser, successfully_read_files = config_items[1], config_items[-1]
try:
customTheme = parse_theme(successfully_read_files)
console = Console(theme=customTheme)
customTheme, themedict = parse_theme(successfully_read_files)
console = Console(
theme=customTheme,
record=True,
height=themedict["log.height"],
width=themedict["log.width"],
)
except KeyError:
console = Console()
console = Console(record=True)
printf(
"[logging.level.warning]No cfg file found, creating one in "
+ successfully_read_files[0]
Expand Down
12 changes: 11 additions & 1 deletion manim/scene/scene_file_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from ..constants import FFMPEG_BIN, GIF_FILE_EXTENSION
from ..config import file_writer_config
from ..logger import logger
from ..logger import logger, console
from ..utils.config_ops import digest_config
from ..utils.file_ops import guarantee_existence
from ..utils.file_ops import add_extension_if_not_present
Expand Down Expand Up @@ -533,3 +533,13 @@ def print_file_ready_message(self, file_path):
Prints the "File Ready" message to STDOUT.
"""
logger.info("\nFile ready at {}\n".format(file_path))

if file_writer_config["log_to_file"]:
self.write_log()

def write_log(self):
log_file_path = os.path.join(
file_writer_config["log_dir"], f"{self.get_default_scene_name()}.log"
)
console.save_text(log_file_path)
logger.info("Log written to {}\n".format(log_file_path))
19 changes: 14 additions & 5 deletions manim/utils/cfg_subcmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,24 @@ def write(level=None, openfile=False):
console.print(RICH_COLOUR_INSTRUCTIONS)
default = replace_keys(default)
for key in default:
console.print(f"Enter the style for {key}:", style=key, end="")
desc = (
"style" if key not in ["log.width", "log.height"] else "value"
)
style = key if key not in ["log.width", "log.height"] else None
cond = (
is_valid_style
if key not in ["log.width", "log.height"]
else lambda m: m.isdigit()
)
console.print(f"Enter the {desc} for {key}:", style=style, end="")
temp = input()
if temp:
while not is_valid_style(temp):
while not cond(temp):
console.print(
"[red bold]Invalid style. Try again.[/red bold]"
f"[red bold]Invalid {desc}. Try again.[/red bold]"
)
console.print(
f"Enter the style for {key}:", style=key, end=""
f"Enter the {desc} for {key}:", style=style, end=""
)
temp = input()
else:
Expand Down Expand Up @@ -162,7 +171,7 @@ def show():
for category in current_config:
console.print(f"{category}", style="bold green underline")
for entry in current_config[category]:
if category == "logger":
if category == "logger" and entry not in ["log_width", "log_height"]:
console.print(f"{entry} :", end="")
console.print(
f" {current_config[category][entry]}",
Expand Down
22 changes: 20 additions & 2 deletions manim/utils/config_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ def _parse_file_writer_config(config_parser, args):
"save_pngs",
"save_as_gif",
"write_all",
"log_to_file",
]:
attr = getattr(args, boolean_opt)
fw_config[boolean_opt] = (
default.getboolean(boolean_opt) if attr is None else attr
)
# for str_opt in ['media_dir', 'video_dir', 'tex_dir', 'text_dir']:
for str_opt in ["media_dir"]:
for str_opt in ["media_dir", "log_dir"]:
attr = getattr(args, str_opt)
fw_config[str_opt] = os.path.relpath(default[str_opt]) if attr is None else attr
dir_names = {"video_dir": "videos", "tex_dir": "Tex", "text_dir": "texts"}
Expand Down Expand Up @@ -255,6 +256,13 @@ def _parse_cli(arg_list, input=True):
help="Save the video as gif",
)

parser.add_argument(
"--log_to_file",
action="store_const",
const=True,
help="Log terminal output to file.",
)

# The default value of the following is set in manim.cfg
parser.add_argument(
"-c", "--color", help="Background color",
Expand All @@ -265,6 +273,11 @@ def _parse_cli(arg_list, input=True):
parser.add_argument(
"--media_dir", help="directory to write media",
)

parser.add_argument(
"--log_dir", help="directory to write log files to",
)

# video_group = parser.add_mutually_exclusive_group()
# video_group.add_argument(
# "--video_dir",
Expand Down Expand Up @@ -370,9 +383,14 @@ def _init_dirs(config):
config["video_dir"],
config["tex_dir"],
config["text_dir"],
config["log_dir"],
]:
if not os.path.exists(folder):
os.makedirs(folder)
# If log_to_file is False, ignore log_dir
if folder is config["log_dir"] and (not config["log_to_file"]):
pass
else:
os.makedirs(folder)


def _from_command_line():
Expand Down
2 changes: 1 addition & 1 deletion tests/test_cli/test_cfg_subcmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_cfg_show(python_version):
"""Test if the `manim cfg show` command works as intended."""
command = f"cd {this_folder} && {python_version} -m manim cfg show"
out, err, exitcode = capture(command, use_shell=True)
assert exitcode == 0
assert exitcode == 0, err
assert f"{os.path.sep}tests{os.path.sep}".encode("utf-8") in out, err


Expand Down
3 changes: 3 additions & 0 deletions tests/test_cli/write_cfg_sbcmd_input.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ False






4 changes: 4 additions & 0 deletions tests/test_logging/expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
INFO Read configuration files: config.py:
INFO scene_file_writer.py:
File ready at

58 changes: 58 additions & 0 deletions tests/test_logging/test_logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import subprocess
import os
import sys
from shutil import rmtree
import pytest
import re


def capture(command, instream=None):
proc = subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=instream
)
out, err = proc.communicate()
return out, err, proc.returncode


def test_logging_to_file(python_version):
"""Test logging Terminal output to a log file.
As some data will differ with each log (the timestamps, file paths, line nums etc)
a regex substitution has been employed to replace the strings that may change with
whitespace.
"""
path_basic_scene = os.path.join("tests", "tests_data", "basic_scenes.py")
path_output = os.path.join("tests_cache", "media_temp")
command = [
python_version,
"-m",
"manim",
path_basic_scene,
"SquareToCircle",
"-l",
"--log_to_file",
"--log_dir",
os.path.join(path_output, "logs"),
"--media_dir",
path_output,
]
out, err, exitcode = capture(command)
log_file_path = os.path.join(path_output, "logs", "SquareToCircle.log")
assert exitcode == 0, err
assert os.path.exists(log_file_path), err
if sys.platform.startswith("win32") or sys.platform.startswith("cygwin"):
enc = "Windows-1252"
else:
enc = "utf-8"
with open(log_file_path, encoding=enc) as logfile:
logs = logfile.read()
# The following regex pattern selects timestamps, file paths and all numbers..
pattern = r"(\[?\d+:?]?)|(\['[A-Z]?:?[\/\\].*cfg'])|([A-Z]?:?[\/\\].*mp4)"
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick : Maybe document this saying that this is provisional.


logs = re.sub(pattern, lambda m: " " * len((m.group(0))), logs)
with open(
os.path.join(os.path.dirname(__file__), "expected.txt"), "r"
) as expectedfile:
expected = re.sub(
pattern, lambda m: " " * len((m.group(0))), expectedfile.read()
)
assert logs == expected, logs
3 changes: 3 additions & 0 deletions tests/tests_data/manim.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ write_to_movie = True
# write_all = False
save_last_frame = False
# save_pngs = False

[logger]
log_width = 256