From 1546d40ae9cc26a3fa998d174984cda3ebbae4dd Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 5 Oct 2022 19:11:32 -0400 Subject: [PATCH 1/6] Remove hack around distutils.dist.log, no longer relevant with pypa/distutils#183. --- setuptools/logging.py | 6 ------ setuptools/tests/test_distutils_adoption.py | 21 --------------------- 2 files changed, 27 deletions(-) diff --git a/setuptools/logging.py b/setuptools/logging.py index 5d41c9882a..a902e3b970 100644 --- a/setuptools/logging.py +++ b/setuptools/logging.py @@ -24,12 +24,6 @@ def configure(): format="{message}", style='{', handlers=handlers, level=logging.DEBUG) monkey.patch_func(set_threshold, distutils.log, 'set_threshold') - # For some reason `distutils.log` module is getting cached in `distutils.dist` - # and then loaded again when patched, - # implying: id(distutils.log) != id(distutils.dist.log). - # Make sure the same module object is used everywhere: - distutils.dist.log = distutils.log - def set_threshold(level): logging.root.setLevel(level*10) diff --git a/setuptools/tests/test_distutils_adoption.py b/setuptools/tests/test_distutils_adoption.py index df8f35419c..5669aab8c0 100644 --- a/setuptools/tests/test_distutils_adoption.py +++ b/setuptools/tests/test_distutils_adoption.py @@ -135,24 +135,3 @@ def test_modules_are_not_duplicated_on_import( cmd = ['python', '-c', script] output = popen_text(venv.run)(cmd, env=win_sr(env)).strip() assert output == "success" - - -ENSURE_LOG_IMPORT_IS_NOT_DUPLICATED = r""" -# Similar to ENSURE_IMPORTS_ARE_NOT_DUPLICATED -import distutils.dist as dist -from distutils import log - -assert dist.log == log, ( - f"\n{dist.log}\n!=\n{log}" -) - -print("success") -""" - - -@pytest.mark.parametrize("distutils_version", "local stdlib".split()) -def test_log_module_is_not_duplicated_on_import(distutils_version, tmpdir_cwd, venv): - env = dict(SETUPTOOLS_USE_DISTUTILS=distutils_version) - cmd = ['python', '-c', ENSURE_LOG_IMPORT_IS_NOT_DUPLICATED] - output = popen_text(venv.run)(cmd, env=win_sr(env)).strip() - assert output == "success" From 9859d69f471002738a4d679113e2d4fbebf45014 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 5 Oct 2022 19:19:41 -0400 Subject: [PATCH 2/6] Support caplog and capsys now that logs go through logging. --- setuptools/tests/test_build_ext.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/setuptools/tests/test_build_ext.py b/setuptools/tests/test_build_ext.py index 92ce80efe2..62ba925e6d 100644 --- a/setuptools/tests/test_build_ext.py +++ b/setuptools/tests/test_build_ext.py @@ -194,16 +194,26 @@ def get_build_ext_cmd(self, optional: bool, **opts): cmd.ensure_finalized() return cmd - def test_optional(self, tmpdir_cwd, capsys): + def get_log_messages(self, caplog, capsys): + """ + Historically, distutils "logged" by printing to sys.std*. + Later versions adopted the logging framework. Grab + messages regardless of how they were captured. + """ + std = capsys.readouterr() + return std.out.splitlines() + std.err.splitlines() + caplog.messages + + def test_optional(self, tmpdir_cwd, caplog, capsys): """ If optional extensions fail to build, setuptools should show the error in the logs but not fail to build """ cmd = self.get_build_ext_cmd(optional=True, inplace=True) cmd.run() - logs = capsys.readouterr() - messages = (logs.out + logs.err) - assert 'build_ext: building extension "spam.eggs" failed' in messages + assert any( + 'build_ext: building extension "spam.eggs" failed' + for msg in self.get_log_messages(caplog, capsys) + ) # No compile error exception should be raised def test_non_optional(self, tmpdir_cwd): From 18df8d79063af9436532f927c3c03023184a95a5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 5 Oct 2022 19:58:21 -0400 Subject: [PATCH 3/6] Suppress monkeypatch when Log is gone, indicating distutils is using logging natively. --- setuptools/logging.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/logging.py b/setuptools/logging.py index a902e3b970..70708adb7f 100644 --- a/setuptools/logging.py +++ b/setuptools/logging.py @@ -22,7 +22,8 @@ def configure(): handlers = err_handler, out_handler logging.basicConfig( format="{message}", style='{', handlers=handlers, level=logging.DEBUG) - monkey.patch_func(set_threshold, distutils.log, 'set_threshold') + if hasattr(distutils.log, 'Log'): + monkey.patch_func(set_threshold, distutils.log, 'set_threshold') def set_threshold(level): From 4fb68b0efdfc6b8e5a4931ed7f6a98d97ad46a79 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 5 Oct 2022 20:07:08 -0400 Subject: [PATCH 4/6] Skip manifest tests as they're copy pasta and broken under a unified logging framework. --- setuptools/tests/test_manifest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setuptools/tests/test_manifest.py b/setuptools/tests/test_manifest.py index 82bdb9c643..ecc83c2fdd 100644 --- a/setuptools/tests/test_manifest.py +++ b/setuptools/tests/test_manifest.py @@ -322,6 +322,8 @@ class TestFileListTest(TempDirTestCase): """ def setup_method(self, method): + if not hasattr(log, 'Log'): + pytest.skip("These tests rely on old logging infra") super(TestFileListTest, self).setup_method(method) self.threshold = log.set_threshold(log.FATAL) self._old_log = log.Log._log From 177a89319ee3135b3c4ed0780bd8fc1c3e3d0161 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 8 Oct 2022 20:52:34 -0400 Subject: [PATCH 5/6] Restore test for log module, but bypass when irrelevant. --- setuptools/tests/test_distutils_adoption.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/setuptools/tests/test_distutils_adoption.py b/setuptools/tests/test_distutils_adoption.py index 5669aab8c0..47493004bb 100644 --- a/setuptools/tests/test_distutils_adoption.py +++ b/setuptools/tests/test_distutils_adoption.py @@ -135,3 +135,21 @@ def test_modules_are_not_duplicated_on_import( cmd = ['python', '-c', script] output = popen_text(venv.run)(cmd, env=win_sr(env)).strip() assert output == "success" + + +ENSURE_LOG_IMPORT_IS_NOT_DUPLICATED = r""" +import types +import distutils.dist as dist +from distutils import log +if isinstance(dist.log, types.ModuleType): + assert dist.log == log, f"\n{dist.log}\n!=\n{log}" +print("success") +""" + + +@pytest.mark.parametrize("distutils_version", "local stdlib".split()) +def test_log_module_is_not_duplicated_on_import(distutils_version, tmpdir_cwd, venv): + env = dict(SETUPTOOLS_USE_DISTUTILS=distutils_version) + cmd = ['python', '-c', ENSURE_LOG_IMPORT_IS_NOT_DUPLICATED] + output = popen_text(venv.run)(cmd, env=win_sr(env)).strip() + assert output == "success" From a2d5c43368573f0fe0a620c87ef4dd9391d40eda Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 8 Oct 2022 20:57:44 -0400 Subject: [PATCH 6/6] Restore protection of distutils.log patching. --- setuptools/logging.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setuptools/logging.py b/setuptools/logging.py index 70708adb7f..e99c1b9d50 100644 --- a/setuptools/logging.py +++ b/setuptools/logging.py @@ -24,6 +24,11 @@ def configure(): format="{message}", style='{', handlers=handlers, level=logging.DEBUG) if hasattr(distutils.log, 'Log'): monkey.patch_func(set_threshold, distutils.log, 'set_threshold') + # For some reason `distutils.log` module is getting cached in `distutils.dist` + # and then loaded again when patched, + # implying: id(distutils.log) != id(distutils.dist.log). + # Make sure the same module object is used everywhere: + distutils.dist.log = distutils.log def set_threshold(level):