Skip to content

Commit e644bdd

Browse files
committed
TEST: Update Gantt chart tests for coverage
1 parent 376d6e2 commit e644bdd

File tree

2 files changed

+42
-14
lines changed

2 files changed

+42
-14
lines changed

nipype/pipeline/plugins/tests/test_callback.py

+25-7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
# vi: set ft=python sts=4 ts=4 sw=4 et:
33
"""Tests for workflow callbacks
44
"""
5+
from datetime import datetime
6+
from pathlib import Path
57
from time import sleep
8+
import json
69
import pytest
710
import nipype.interfaces.utility as niu
811
import nipype.pipeline.engine as pe
12+
from nipype.utils.draw_gantt_chart import _convert_string_to_datetime
913

1014
try:
1115
import pandas
@@ -71,22 +75,22 @@ def test_callback_exception(tmpdir, plugin, stop_on_first_crash):
7175

7276
@pytest.mark.parametrize("plugin", ["Linear", "MultiProc", "LegacyMultiProc"])
7377
@pytest.mark.skipif(not has_pandas, reason="Test requires pandas")
74-
def test_callback_gantt(tmpdir, plugin):
78+
def test_callback_gantt(tmp_path: Path, plugin: str) -> None:
7579
import logging
7680

7781
from os import path
7882

7983
from nipype.utils.profiler import log_nodes_cb
8084
from nipype.utils.draw_gantt_chart import generate_gantt_chart
8185

82-
log_filename = path.join(tmpdir, "callback.log")
86+
log_filename = tmp_path / "callback.log"
8387
logger = logging.getLogger("callback")
8488
logger.setLevel(logging.DEBUG)
8589
handler = logging.FileHandler(log_filename)
8690
logger.addHandler(handler)
8791

8892
# create workflow
89-
wf = pe.Workflow(name="test", base_dir=tmpdir.strpath)
93+
wf = pe.Workflow(name="test", base_dir=str(tmp_path))
9094
f_node = pe.Node(
9195
niu.Function(function=func, input_names=[], output_names=[]), name="f_node"
9296
)
@@ -98,7 +102,21 @@ def test_callback_gantt(tmpdir, plugin):
98102
plugin_args["n_procs"] = 8
99103
wf.run(plugin=plugin, plugin_args=plugin_args)
100104

101-
generate_gantt_chart(
102-
path.join(tmpdir, "callback.log"), 1 if plugin == "Linear" else 8
103-
)
104-
assert path.exists(path.join(tmpdir, "callback.log.html"))
105+
with open(log_filename, "r") as _f:
106+
loglines = _f.readlines()
107+
108+
# test missing duration
109+
first_line = json.loads(loglines[0])
110+
if "duration" in first_line:
111+
del first_line["duration"]
112+
loglines[0] = json.dumps(first_line)
113+
114+
# test duplicate timestamp warning
115+
loglines.append(loglines[-1])
116+
117+
with open(log_filename, "w") as _f:
118+
_f.write("".join(loglines))
119+
120+
with pytest.warns(Warning):
121+
generate_gantt_chart(str(log_filename), 1 if plugin == "Linear" else 8)
122+
assert (tmp_path / "callback.log.html").exists()

nipype/utils/draw_gantt_chart.py

+17-7
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,25 @@ def log_to_dict(logfile):
102102

103103
nodes_list = [json.loads(l) for l in lines]
104104

105-
def _convert_string_to_datetime(datestring):
106-
try:
105+
def _convert_string_to_datetime(
106+
datestring: str | datetime.datetime,
107+
) -> datetime.datetime:
108+
"""Convert a date string to a datetime object."""
109+
if isinstance(datestring, datetime.datetime):
110+
datetime_object = datestring
111+
elif isinstance(datestring, str):
112+
date_format = (
113+
"%Y-%m-%dT%H:%M:%S.%f%z"
114+
if "+" in datestring
115+
else "%Y-%m-%dT%H:%M:%S.%f"
116+
)
107117
datetime_object: datetime.datetime = datetime.datetime.strptime(
108-
datestring, "%Y-%m-%dT%H:%M:%S.%f"
118+
datestring, date_format
109119
)
110-
return datetime_object
111-
except Exception as _:
112-
pass
113-
return datestring
120+
else:
121+
msg = f"{datestring} is not a string or datetime object."
122+
raise TypeError(msg)
123+
return datetime_object
114124

115125
date_object_node_list: list = list()
116126
for n in nodes_list:

0 commit comments

Comments
 (0)