From d5c8ef860b99507a937ea7178df34cca545aeeb0 Mon Sep 17 00:00:00 2001 From: symonk Date: Thu, 11 Jun 2020 01:28:48 +0100 Subject: [PATCH 1/5] Make the --log-file relative to inifile if it exists --- src/_pytest/logging.py | 3 ++ testing/logging/test_reporting.py | 79 +++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index ef90c94e862..c37eb450d5f 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -527,6 +527,9 @@ def __init__(self, config: Config) -> None: # File logging. self.log_file_level = get_log_level_for_setting(config, "log_file_level") log_file = get_option_ini(config, "log_file") or os.devnull + # Keep the log file relative to the inidir file (if it exists) (#7336) + if log_file != os.devnull and getattr(config, "inifile", None): + log_file = os.path.join(config.inifile.dirname, log_file) # type: ignore[union-attr] self.log_file_handler = _FileHandler(log_file, mode="w", encoding="UTF-8") log_file_format = get_option_ini(config, "log_file_format", "log_format") log_file_date_format = get_option_ini( diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index bbdf28b389a..5c3649a6300 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1152,3 +1152,82 @@ def test_bad_log(monkeypatch): ) result = testdir.runpytest() result.assert_outcomes(passed=1) + + +def test_log_file_is_in_pytest_ini_rootdir(testdir): + # as per https://docs.pytest.org/en/5.4.3/reference.html log_file + # the file should be relative to the pytest inifile + testdir.makefile( + ".ini", + pytest=""" + [pytest] + log_cli = True + log_cli_level = DEBUG + log_file = logfile.txt + log_file_level = DEBUG + """, + ) + sub = testdir.mkdir("sub") + p = testdir.makepyfile( + """ + def test_this(): + import logging + logging.getLogger().info("Normal message") + """ + ) + p.move(sub.join(p.basename)) + os.chdir(sub.strpath) + testdir.runpytest() + testdir.chdir() + files = set(os.listdir()) + assert {"logfile.txt", "pytest.ini"}.issubset(files) + + +def test_log_file_can_be_specified_to_child_dir(testdir): + testdir.makefile( + ".ini", + pytest=""" + [pytest] + log_cli = True + log_cli_level = DEBUG + log_file = sub/logfile.txt + log_file_level = DEBUG + """, + ) + sub = testdir.mkdir("sub") + p = testdir.makepyfile( + """ + def test_this(): + import logging + logging.getLogger().info("Normal message") + """ + ) + p.move(sub.join(p.basename)) + os.chdir(sub.strpath) + testdir.runpytest() + files = set(os.listdir()) + assert "logfile.txt" in files + assert "pytest.ini" not in files + + +def test_log_file_cli_is_also_relative(testdir): + testdir.makefile( + ".ini", + pytest=""" + [pytest] + """, + ) + sub = testdir.mkdir("sub") + p = testdir.makepyfile( + """ + def test_this(): + import logging + logging.getLogger().info("Normal message") + """ + ) + p.move(sub.join(p.basename)) + os.chdir(sub.strpath) + testdir.runpytest("--log-file", "sub{}logfile.txt".format(os.sep)) + files = set(os.listdir()) + assert "logfile.txt" in files + assert "pytest.ini" not in files From afaacc55a156ff7653f1f46225a48873c6033d2e Mon Sep 17 00:00:00 2001 From: symonk Date: Thu, 11 Jun 2020 13:25:29 +0100 Subject: [PATCH 2/5] remove unnecessary None default --- src/_pytest/logging.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index c37eb450d5f..1d71930f0b4 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -528,7 +528,7 @@ def __init__(self, config: Config) -> None: self.log_file_level = get_log_level_for_setting(config, "log_file_level") log_file = get_option_ini(config, "log_file") or os.devnull # Keep the log file relative to the inidir file (if it exists) (#7336) - if log_file != os.devnull and getattr(config, "inifile", None): + if log_file != os.devnull and getattr(config, "inifile"): log_file = os.path.join(config.inifile.dirname, log_file) # type: ignore[union-attr] self.log_file_handler = _FileHandler(log_file, mode="w", encoding="UTF-8") log_file_format = get_option_ini(config, "log_file_format", "log_format") From 951a63998d3db273d3dbbb77cf9f6dcd4ad52acc Mon Sep 17 00:00:00 2001 From: symonk Date: Thu, 11 Jun 2020 13:55:16 +0100 Subject: [PATCH 3/5] Fix nested inidir lookup on cfg; fix spacing of comment --- src/_pytest/logging.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 1d71930f0b4..c0df130b946 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -527,9 +527,11 @@ def __init__(self, config: Config) -> None: # File logging. self.log_file_level = get_log_level_for_setting(config, "log_file_level") log_file = get_option_ini(config, "log_file") or os.devnull + # Keep the log file relative to the inidir file (if it exists) (#7336) - if log_file != os.devnull and getattr(config, "inifile"): - log_file = os.path.join(config.inifile.dirname, log_file) # type: ignore[union-attr] + inidir = getattr(getattr(config, "inifile", None), "dirname", None) + if log_file != os.devnull and inidir: + log_file = os.path.join(inidir, log_file) self.log_file_handler = _FileHandler(log_file, mode="w", encoding="UTF-8") log_file_format = get_option_ini(config, "log_file_format", "log_format") log_file_date_format = get_option_ini( From 45d6a10c076dc6759afca8d95ae0f90a64f2f7fc Mon Sep 17 00:00:00 2001 From: symonk Date: Fri, 12 Jun 2020 00:07:11 +0100 Subject: [PATCH 4/5] relative --log-line PR feedback improvements --- changelog/7336.breaking.rst | 1 + src/_pytest/config/findpaths.py | 2 +- src/_pytest/logging.py | 5 ++--- testing/logging/test_reporting.py | 29 +++++++++++++++++------------ 4 files changed, 21 insertions(+), 16 deletions(-) create mode 100644 changelog/7336.breaking.rst diff --git a/changelog/7336.breaking.rst b/changelog/7336.breaking.rst new file mode 100644 index 00000000000..31d44f11cff --- /dev/null +++ b/changelog/7336.breaking.rst @@ -0,0 +1 @@ +The pytest ``--log-file`` cli or ``log_file`` ini marker is now relative to the configs ``inifile`` directory, as it was always the intention. It was originally introduced as relative to the current working directory unintentionally. diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 796fa9b0ae0..ff6b54acb66 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -161,7 +161,7 @@ def determine_setup( args: List[str], rootdir_cmd_arg: Optional[str] = None, config: Optional["Config"] = None, -) -> Tuple[py.path.local, Optional[str], Dict[str, Union[str, List[str]]]]: +) -> Tuple[py.path.local, Optional[py.path.local], Dict[str, Union[str, List[str]]]]: rootdir = None dirs = get_dirs_from_args(args) if inifile: diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index c0df130b946..7e666f6927a 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -529,9 +529,8 @@ def __init__(self, config: Config) -> None: log_file = get_option_ini(config, "log_file") or os.devnull # Keep the log file relative to the inidir file (if it exists) (#7336) - inidir = getattr(getattr(config, "inifile", None), "dirname", None) - if log_file != os.devnull and inidir: - log_file = os.path.join(inidir, log_file) + if log_file != os.devnull and config.inifile is not None: + log_file = os.path.join(config.inifile.dirname, log_file) self.log_file_handler = _FileHandler(log_file, mode="w", encoding="UTF-8") log_file_format = get_option_ini(config, "log_file_format", "log_format") log_file_date_format = get_option_ini( diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 5c3649a6300..b2871998353 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1154,9 +1154,10 @@ def test_bad_log(monkeypatch): result.assert_outcomes(passed=1) -def test_log_file_is_in_pytest_ini_rootdir(testdir): - # as per https://docs.pytest.org/en/5.4.3/reference.html log_file - # the file should be relative to the pytest inifile +def test_log_file_is_in_pytest_ini_rootdir(testdir, monkeypatch): + """ + #7336|#7350 - log_file should be relative to the config inifile + """ testdir.makefile( ".ini", pytest=""" @@ -1176,14 +1177,17 @@ def test_this(): """ ) p.move(sub.join(p.basename)) - os.chdir(sub.strpath) + monkeypatch.chdir(sub.strpath) testdir.runpytest() testdir.chdir() files = set(os.listdir()) assert {"logfile.txt", "pytest.ini"}.issubset(files) -def test_log_file_can_be_specified_to_child_dir(testdir): +def test_log_file_can_be_specified_to_child_dir(testdir, monkeypatch): + """ + #7336|#7350 - log_file should be relative to the config inifile + """ testdir.makefile( ".ini", pytest=""" @@ -1198,19 +1202,21 @@ def test_log_file_can_be_specified_to_child_dir(testdir): p = testdir.makepyfile( """ def test_this(): - import logging - logging.getLogger().info("Normal message") + pass """ ) p.move(sub.join(p.basename)) - os.chdir(sub.strpath) + monkeypatch.chdir(sub.strpath) testdir.runpytest() files = set(os.listdir()) assert "logfile.txt" in files assert "pytest.ini" not in files -def test_log_file_cli_is_also_relative(testdir): +def test_log_file_cli_is_also_relative(testdir, monkeypatch): + """ + #7336|#7350 - log_file should be relative to the config inifile + """ testdir.makefile( ".ini", pytest=""" @@ -1221,12 +1227,11 @@ def test_log_file_cli_is_also_relative(testdir): p = testdir.makepyfile( """ def test_this(): - import logging - logging.getLogger().info("Normal message") + pass """ ) p.move(sub.join(p.basename)) - os.chdir(sub.strpath) + monkeypatch.chdir(sub.strpath) testdir.runpytest("--log-file", "sub{}logfile.txt".format(os.sep)) files = set(os.listdir()) assert "logfile.txt" in files From bd4a57fa78a2c81c5182d86c5fccdc5f24c6f59f Mon Sep 17 00:00:00 2001 From: symonk Date: Fri, 12 Jun 2020 14:31:03 +0100 Subject: [PATCH 5/5] convert inifile to path.local when it is a string --- src/_pytest/config/findpaths.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index ff6b54acb66..68a96019e8a 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -165,7 +165,8 @@ def determine_setup( rootdir = None dirs = get_dirs_from_args(args) if inifile: - inicfg = load_config_dict_from_file(py.path.local(inifile)) or {} + inifile = py.path.local(inifile) + inicfg = load_config_dict_from_file(inifile) or {} if rootdir_cmd_arg is None: rootdir = get_common_ancestor(dirs) else: