Skip to content

Commit 7fa57dd

Browse files
committed
--no-warnings includes schema-salad; --validate should complain to stdout
1 parent 6c86caa commit 7fa57dd

File tree

5 files changed

+107
-31
lines changed

5 files changed

+107
-31
lines changed

cwltool/loghandler.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
def configure_logging(
14-
stderr_handler: logging.Handler,
14+
err_handler: logging.Handler,
1515
no_warnings: bool,
1616
quiet: bool,
1717
debug: bool,
@@ -21,25 +21,29 @@ def configure_logging(
2121
) -> None:
2222
"""Configure logging."""
2323
rdflib_logger = logging.getLogger("rdflib.term")
24-
rdflib_logger.addHandler(stderr_handler)
24+
rdflib_logger.addHandler(err_handler)
2525
rdflib_logger.setLevel(logging.ERROR)
2626
deps_logger = logging.getLogger("galaxy.tool_util.deps")
27-
deps_logger.addHandler(stderr_handler)
27+
deps_logger.addHandler(err_handler)
2828
ss_logger = logging.getLogger("salad")
29-
ss_logger.addHandler(stderr_handler)
3029
if no_warnings:
31-
stderr_handler.setLevel(logging.ERROR)
32-
if quiet:
30+
err_handler.setLevel(logging.ERROR)
31+
ss_logger.setLevel(logging.ERROR)
32+
elif quiet:
3333
# Silence STDERR, not an eventual provenance log file
34-
stderr_handler.setLevel(logging.WARN)
34+
err_handler.setLevel(logging.WARN)
35+
ss_logger.setLevel(logging.WARN)
36+
else:
37+
err_handler.setLevel(logging.INFO)
38+
ss_logger.setLevel(logging.INFO)
3539
if debug:
3640
# Increase to debug for both stderr and provenance log file
3741
base_logger.setLevel(logging.DEBUG)
38-
stderr_handler.setLevel(logging.DEBUG)
42+
err_handler.setLevel(logging.DEBUG)
3943
rdflib_logger.setLevel(logging.DEBUG)
4044
deps_logger.setLevel(logging.DEBUG)
4145
fmtclass = coloredlogs.ColoredFormatter if enable_color else logging.Formatter
4246
formatter = fmtclass("%(levelname)s %(message)s")
4347
if timestamps:
4448
formatter = fmtclass("[%(asctime)s] %(levelname)s %(message)s", "%Y-%m-%d %H:%M:%S")
45-
stderr_handler.setFormatter(formatter)
49+
err_handler.setFormatter(formatter)

cwltool/main.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -967,12 +967,6 @@ def main(
967967
stdout = cast(IO[str], stdout)
968968

969969
_logger.removeHandler(defaultStreamHandler)
970-
stderr_handler = logger_handler
971-
if stderr_handler is not None:
972-
_logger.addHandler(stderr_handler)
973-
else:
974-
coloredlogs.install(logger=_logger, stream=stderr)
975-
stderr_handler = _logger.handlers[-1]
976970
workflowobj = None
977971
prov_log_handler: Optional[logging.StreamHandler[ProvOut]] = None
978972
global docker_exe
@@ -997,6 +991,13 @@ def main(
997991
if not args.cidfile_dir:
998992
args.cidfile_dir = os.getcwd()
999993
del args.record_container_id
994+
if logger_handler is not None:
995+
err_handler = logger_handler
996+
_logger.addHandler(err_handler)
997+
else:
998+
coloredlogs.install(logger=_logger, stream=stdout if args.validate else stderr)
999+
err_handler = _logger.handlers[-1]
1000+
logging.getLogger("salad").handlers = _logger.handlers
10001001

10011002
if runtimeContext is None:
10021003
runtimeContext = RuntimeContext(vars(args))
@@ -1015,7 +1016,7 @@ def main(
10151016
setattr(args, key, val)
10161017

10171018
configure_logging(
1018-
stderr_handler,
1019+
err_handler,
10191020
args.no_warnings,
10201021
args.quiet,
10211022
runtimeContext.debug,
@@ -1413,8 +1414,7 @@ def loc_to_path(obj: CWLObjectType) -> None:
14131414
# public API for logging.StreamHandler
14141415
prov_log_handler.close()
14151416
close_ro(research_obj, args.provenance)
1416-
1417-
_logger.removeHandler(stderr_handler)
1417+
_logger.removeHandler(err_handler)
14181418
_logger.addHandler(defaultStreamHandler)
14191419

14201420

tests/test_examples.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,9 +1820,9 @@ def test_validate_optional_src_with_mandatory_sink() -> None:
18201820
["--validate", get_data("tests/wf/optional_src_mandatory_sink.cwl")]
18211821
)
18221822
assert exit_code == 0
1823-
stderr = re.sub(r"\s\s+", " ", stderr)
1824-
assert 'Source \'opt_file\' of type ["null", "File"] may be incompatible' in stderr
1825-
assert "with sink 'r' of type \"File\"" in stderr
1823+
stdout = re.sub(r"\s\s+", " ", stdout)
1824+
assert 'Source \'opt_file\' of type ["null", "File"] may be incompatible' in stdout
1825+
assert "with sink 'r' of type \"File\"" in stdout
18261826

18271827

18281828
def test_res_req_expr_float_1_0() -> None:
@@ -1875,12 +1875,11 @@ def test_invalid_nested_array() -> None:
18751875
]
18761876
)
18771877
assert exit_code == 1, stderr
1878-
stderr = re.sub(r"\n\s+", " ", stderr)
1879-
stderr = re.sub(r"\s\s+", " ", stderr)
1880-
assert "Tool definition failed validation:" in stderr
1878+
stdout = re.sub(r"\s\s+", " ", stdout)
1879+
assert "Tool definition failed validation:" in stdout
18811880
assert (
18821881
"tests/nested-array.cwl:6:5: Field 'type' references unknown identifier 'string[][]'"
1883-
) in stderr
1882+
) in stdout
18841883

18851884

18861885
def test_input_named_id() -> None:

tests/test_validate.py

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Tests --validation."""
22

3+
import io
4+
import logging
35
import re
46

57
from .util import get_data, get_main_output
@@ -43,13 +45,83 @@ def test_validate_with_invalid_input_object() -> None:
4345
]
4446
)
4547
assert exit_code == 1
46-
stderr = re.sub(r"\s\s+", " ", stderr)
47-
assert "Invalid job input record" in stderr
48+
stdout = re.sub(r"\s\s+", " ", stdout)
49+
assert "Invalid job input record" in stdout
4850
assert (
4951
"tests/wf/1st-workflow_bad_inputs.yml:2:1: * the 'ex' field is not "
50-
"valid because the value is not string" in stderr
52+
"valid because the value is not string" in stdout
5153
)
5254
assert (
5355
"tests/wf/1st-workflow_bad_inputs.yml:1:1: * the 'inp' field is not "
54-
"valid because is not a dict. Expected a File object." in stderr
56+
"valid because is not a dict. Expected a File object." in stdout
57+
)
58+
59+
60+
def test_validate_quiet() -> None:
61+
"""Ensure that --validate --quiet prints the correct amount of information."""
62+
exit_code, stdout, stderr = get_main_output(
63+
[
64+
"--validate",
65+
"--quiet",
66+
get_data("tests/CometAdapter.cwl"),
67+
]
68+
)
69+
assert exit_code == 0
70+
stdout = re.sub(r"\s\s+", " ", stdout)
71+
assert "INFO" not in stdout
72+
assert "INFO" not in stderr
73+
assert "tests/CometAdapter.cwl:9:3: object id" in stdout
74+
assert "tests/CometAdapter.cwl#out' previously defined" in stdout
75+
76+
77+
def test_validate_no_warnings() -> None:
78+
"""Ensure that --validate --no-warnings doesn't print any warnings."""
79+
exit_code, stdout, stderr = get_main_output(
80+
[
81+
"--validate",
82+
"--no-warnings",
83+
get_data("tests/CometAdapter.cwl"),
84+
]
5585
)
86+
assert exit_code == 0
87+
stdout = re.sub(r"\s\s+", " ", stdout)
88+
stderr = re.sub(r"\s\s+", " ", stderr)
89+
assert "INFO" not in stdout
90+
assert "INFO" not in stderr
91+
assert "WARNING" not in stdout
92+
assert "WARNING" not in stderr
93+
assert "tests/CometAdapter.cwl:9:3: object id" not in stdout
94+
assert "tests/CometAdapter.cwl:9:3: object id" not in stderr
95+
assert "tests/CometAdapter.cwl#out' previously defined" not in stdout
96+
assert "tests/CometAdapter.cwl#out' previously defined" not in stderr
97+
98+
99+
def test_validate_custom_logger() -> None:
100+
"""Custom log handling test."""
101+
custom_log = io.StringIO()
102+
handler = logging.StreamHandler(custom_log)
103+
handler.setLevel(logging.DEBUG)
104+
exit_code, stdout, stderr = get_main_output(
105+
[
106+
"--validate",
107+
get_data("tests/CometAdapter.cwl"),
108+
],
109+
logger_handler=handler,
110+
)
111+
custom_log_text = custom_log.getvalue()
112+
assert exit_code == 0
113+
custom_log_text = re.sub(r"\s\s+", " ", custom_log_text)
114+
stdout = re.sub(r"\s\s+", " ", stdout)
115+
stderr = re.sub(r"\s\s+", " ", stderr)
116+
assert "INFO" not in stdout
117+
assert "INFO" not in stderr
118+
assert "INFO" in custom_log_text
119+
assert "WARNING" not in stdout
120+
assert "WARNING" not in stderr
121+
assert "WARNING" in custom_log_text
122+
assert "tests/CometAdapter.cwl:9:3: object id" not in stdout
123+
assert "tests/CometAdapter.cwl:9:3: object id" not in stderr
124+
assert "tests/CometAdapter.cwl:9:3: object id" in custom_log_text
125+
assert "tests/CometAdapter.cwl#out' previously defined" not in stdout
126+
assert "tests/CometAdapter.cwl#out' previously defined" not in stderr
127+
assert "tests/CometAdapter.cwl#out' previously defined" in custom_log_text

tests/util.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from collections.abc import Generator, Mapping
1212
from contextlib import ExitStack
1313
from pathlib import Path
14-
from typing import Optional, Union
14+
from typing import Any, Optional, Union
1515

1616
import pytest
1717

@@ -88,6 +88,7 @@ def get_main_output(
8888
replacement_env: Optional[Mapping[str, str]] = None,
8989
extra_env: Optional[Mapping[str, str]] = None,
9090
monkeypatch: Optional[pytest.MonkeyPatch] = None,
91+
**extra_kwargs: Any,
9192
) -> tuple[Optional[int], str, str]:
9293
"""Run cwltool main.
9394
@@ -113,7 +114,7 @@ def get_main_output(
113114
monkeypatch.setenv(k, v)
114115

115116
try:
116-
rc = main(argsl=args, stdout=stdout, stderr=stderr)
117+
rc = main(argsl=args, stdout=stdout, stderr=stderr, **extra_kwargs)
117118
except SystemExit as e:
118119
if isinstance(e.code, int):
119120
rc = e.code

0 commit comments

Comments
 (0)