Skip to content

Commit

Permalink
Fix yaml formatting for logger
Browse files Browse the repository at this point in the history
  • Loading branch information
ElliottKasoar committed Mar 28, 2024
1 parent ae58f7d commit 357452f
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 7 deletions.
57 changes: 52 additions & 5 deletions janus_core/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,48 @@
message: %(message)s
trace: %(module)s
line: %(lineno)d
""".strip()
"""


class CustomFormatter(logging.Formatter):
"""
Custom formatter to convert multiline messages into yaml list.
Methods
-------
format(record)
Format log message to convert new lines into a yaml list.
"""

def format(self, record: logging.LogRecord) -> str:
"""
Format log message to convert new lines into a yaml list.
Parameters
----------
record : logging.LogRecord
Log record to be formatted.
Returns
-------
str
Formatted log message.
"""
# Convert new lines into yaml list
if len(record.msg.split("\n")) > 1:
msg = record.msg
record.msg = "\n"
for line in msg.split("\n"):
# Exclude empty lines
if line.strip():
record.msg += f' - "{line.strip()}"\n'
# Remove final newline (single character)
record.msg = record.msg[:-1]
else:
# Wrap line in quotes here rather than in FORMAT due to list
record.msg = f'"{record.msg}"'

return super().format(record)


def config_logger(
Expand Down Expand Up @@ -49,13 +90,19 @@ def config_logger(
if filename:
logger = logging.getLogger(name)

handler = logging.FileHandler(
filename,
filemode,
encoding="utf-8",
)
handler.setLevel(level)
formatter = CustomFormatter(FORMAT)
handler.setFormatter(formatter)

logging.basicConfig(
level=level,
filename=filename,
filemode=filemode,
format=FORMAT,
encoding="utf-8",
force=force,
handlers=[handler],
)
logging.captureWarnings(capture=capture_warnings)
else:
Expand Down
27 changes: 27 additions & 0 deletions tests/test_geomopt_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

runner = CliRunner()

# Many pylint now warnings raised due to similar log/summary flags
# These depend on tmp_path, so not easily refactorisable
# pylint: disable=duplicate-code


def test_help():
"""Test calling `janus geomopt --help`."""
Expand All @@ -26,6 +30,7 @@ def test_help():
def test_geomopt(tmp_path):
"""Test geomopt calculation."""
results_path = Path("./NaCl-opt.xyz").absolute()
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

assert not results_path.exists()
Expand All @@ -38,6 +43,8 @@ def test_geomopt(tmp_path):
DATA_PATH / "NaCl.cif",
"--max-force",
"0.2",
"--log",
log_path,
"--summary",
summary_path,
],
Expand Down Expand Up @@ -77,6 +84,7 @@ def test_traj(tmp_path):
"""Test trajectory correctly written for geomopt."""
results_path = tmp_path / "NaCl-opt.xyz"
traj_path = f"{tmp_path}/test.xyz"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

result = runner.invoke(
Expand All @@ -89,6 +97,8 @@ def test_traj(tmp_path):
results_path,
"--traj",
traj_path,
"--log",
log_path,
"--summary",
summary_path,
],
Expand All @@ -101,6 +111,7 @@ def test_traj(tmp_path):
def test_fully_opt(tmp_path, caplog):
"""Test passing --fully-opt without --vectors-only"""
results_path = tmp_path / "NaCl-opt.xyz"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

with caplog.at_level("INFO", logger="janus_core.geom_opt"):
Expand All @@ -113,6 +124,8 @@ def test_fully_opt(tmp_path, caplog):
"--out",
results_path,
"--fully-opt",
"--log",
log_path,
"--summary",
summary_path,
],
Expand Down Expand Up @@ -161,6 +174,7 @@ def test_fully_opt_and_vectors(tmp_path, caplog):
def test_vectors_not_fully_opt(tmp_path, caplog):
"""Test passing --vectors-only without --fully-opt."""
results_path = tmp_path / "NaCl-opt.xyz"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

with caplog.at_level("INFO", logger="janus_core.geom_opt"):
Expand All @@ -173,6 +187,8 @@ def test_vectors_not_fully_opt(tmp_path, caplog):
"--out",
results_path,
"--vectors-only",
"--log",
log_path,
"--summary",
summary_path,
],
Expand All @@ -184,6 +200,7 @@ def test_vectors_not_fully_opt(tmp_path, caplog):
def test_duplicate_traj(tmp_path):
"""Test trajectory file cannot be not passed via traj_kwargs."""
traj_path = tmp_path / "NaCl-traj.xyz"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

result = runner.invoke(
Expand All @@ -194,6 +211,8 @@ def test_duplicate_traj(tmp_path):
DATA_PATH / "NaCl.cif",
"--opt-kwargs",
f"{{'trajectory': '{str(traj_path)}'}}",
"--log",
log_path,
"--summary",
summary_path,
],
Expand All @@ -207,6 +226,7 @@ def test_restart(tmp_path):
data_path = DATA_PATH / "NaCl-deformed.cif"
restart_path = tmp_path / "NaCl-res.pkl"
results_path = tmp_path / "NaCl-opt.xyz"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

result = runner.invoke(
Expand All @@ -221,6 +241,8 @@ def test_restart(tmp_path):
f"{{'restart': '{str(restart_path)}'}}",
"--steps",
2,
"--log",
log_path,
"--summary",
summary_path,
],
Expand All @@ -241,6 +263,8 @@ def test_restart(tmp_path):
f"{{'restart': '{str(restart_path)}'}}",
"--steps",
2,
"--log",
log_path,
"--summary",
summary_path,
],
Expand All @@ -254,6 +278,7 @@ def test_restart(tmp_path):
def test_summary(tmp_path):
"""Test summary file can be read correctly."""
results_path = tmp_path / "NaCl-results.xyz"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

result = runner.invoke(
Expand All @@ -264,6 +289,8 @@ def test_summary(tmp_path):
DATA_PATH / "NaCl.cif",
"--out",
results_path,
"--log",
log_path,
"--summary",
summary_path,
],
Expand Down
20 changes: 19 additions & 1 deletion tests/test_md_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

runner = CliRunner()

# Many pylint now warnings raised due to similar log/summary flags
# These depend on tmp_path, so not easily refactorisable
# pylint: disable=duplicate-code


def test_md_help():
"""Test calling `janus md --help`."""
Expand All @@ -37,6 +41,7 @@ def test_md(ensemble, tmp_path):
"""Test all MD simulations are able to run."""
file_prefix = tmp_path / f"{ensemble}-T300"
traj_path = tmp_path / f"{ensemble}-T300-traj.xyz"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

result = runner.invoke(
Expand All @@ -55,6 +60,8 @@ def test_md(ensemble, tmp_path):
2,
"--traj-every",
1,
"--log",
log_path,
"--summary",
summary_path,
],
Expand All @@ -71,6 +78,7 @@ def test_log(tmp_path, caplog):
"""Test log correctly written for MD."""
file_prefix = tmp_path / "nvt-T300"
stats_path = tmp_path / "nvt-T300-stats.dat"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

with caplog.at_level("INFO", logger="janus_core.md"):
Expand All @@ -90,12 +98,14 @@ def test_log(tmp_path, caplog):
20,
"--stats-every",
1,
"--log",
log_path,
"--summary",
summary_path,
],
)
assert result.exit_code == 0
assert " Starting molecular dynamics simulation" in caplog.text
assert "Starting molecular dynamics simulation" in caplog.text

with open(stats_path, encoding="utf8") as stats_file:
lines = stats_file.readlines()
Expand All @@ -121,6 +131,7 @@ def test_seed(tmp_path):
"""Test seed enables reproducable results for NVT."""
file_prefix = tmp_path / "nvt-T300"
stats_path = tmp_path / "nvt-T300-stats.dat"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

result_1 = runner.invoke(
Expand All @@ -141,6 +152,8 @@ def test_seed(tmp_path):
20,
"--seed",
42,
"--log",
log_path,
"--summary",
summary_path,
],
Expand Down Expand Up @@ -174,6 +187,8 @@ def test_seed(tmp_path):
20,
"--seed",
42,
"--log",
log_path,
"--summary",
summary_path,
],
Expand All @@ -195,6 +210,7 @@ def test_seed(tmp_path):
def test_summary(tmp_path):
"""Test summary file can be read correctly."""
file_prefix = tmp_path / "nvt-T300"
log_path = tmp_path / "test.log"
summary_path = tmp_path / "summary.yml"

result = runner.invoke(
Expand All @@ -213,6 +229,8 @@ def test_summary(tmp_path):
2,
"--traj-every",
1,
"--log",
log_path,
"--summary",
summary_path,
],
Expand Down
Loading

0 comments on commit 357452f

Please sign in to comment.