From be847e002eacf1431470f5d6592de5caddb521e5 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Wed, 19 Jun 2024 12:59:30 +0100 Subject: [PATCH 1/6] Add interop tests for pkg_resources and zope-interface --- .../tests/integration/test_zope_interface.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 setuptools/tests/integration/test_zope_interface.py diff --git a/setuptools/tests/integration/test_zope_interface.py b/setuptools/tests/integration/test_zope_interface.py new file mode 100644 index 0000000000..c340c4137d --- /dev/null +++ b/setuptools/tests/integration/test_zope_interface.py @@ -0,0 +1,61 @@ +import platform +import subprocess +import sys +from inspect import cleandoc + +import jaraco.path +import pytest + +pytestmark = pytest.mark.integration + +VIRTUALENV = (sys.executable, "-m", "virtualenv") + + +def run(cmd, **kwargs): + proc = subprocess.run(cmd, encoding="utf-8", capture_output=True, **kwargs) + if proc.returncode != 0: + pytest.fail(f"Command {cmd} failed with:\n{proc.stdout=!s}\n{proc.stderr=!s}") + return proc.stdout + + +@pytest.mark.skipif( + platform.system() != "Linux", + reason="only demonstrated to fail on Linux in #4399", +) +def test_interop_pkg_resources_iter_entry_points(tmp_path, venv): + """ + Importing pkg_resources.iter_entry_points on console_scripts + seems to cause trouble with zope-interface, when deprecates installation method + is used. See #4399. + """ + project = { + "pkg": { + "foo.py": cleandoc( + """ + from pkg_resources import iter_entry_points + + def bar(): + print("Print me if you can") + """ + ), + "setup.py": cleandoc( + """ + from setuptools import setup, find_packages + + setup( + install_requires=["zope-interface==6.4.post2"], + entry_points={ + "console_scripts": [ + "foo=foo:bar", + ], + }, + ) + """ + ), + } + } + jaraco.path.build(project, prefix=tmp_path) + cmd = [venv.exe("pip"), "install", "-e", ".", "--no-use-pep517"] + run(cmd, cwd=tmp_path / "pkg") + out = run([venv.exe("foo")]) + assert "Print me if you can" in out From b95d168faa3fe25d7e9e947472094d23124428cf Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 17 Jun 2024 15:12:06 +0100 Subject: [PATCH 2/6] Move piece of code inside pkg_resources/__init__.py --- pkg_resources/__init__.py | 64 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 894b45ac25..15f96693e7 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -3426,6 +3426,38 @@ class PkgResourcesDeprecationWarning(Warning): """ +# Ported from ``setuptools`` to avoid introducing an import inter-dependency: +_LOCALE_ENCODING = "locale" if sys.version_info >= (3, 10) else None + + +def _read_utf8_with_fallback(file: str, fallback_encoding=_LOCALE_ENCODING) -> str: + """See setuptools.unicode_utils._read_utf8_with_fallback""" + try: + with open(file, "r", encoding="utf-8") as f: + return f.read() + except UnicodeDecodeError: # pragma: no cover + msg = f"""\ + ******************************************************************************** + `encoding="utf-8"` fails with {file!r}, trying `encoding={fallback_encoding!r}`. + + This fallback behaviour is considered **deprecated** and future versions of + `setuptools/pkg_resources` may not implement it. + + Please encode {file!r} with "utf-8" to ensure future builds will succeed. + + If this file was produced by `setuptools` itself, cleaning up the cached files + and re-building/re-installing the package with a newer version of `setuptools` + (e.g. by updating `build-system.requires` in its `pyproject.toml`) + might solve the problem. + ******************************************************************************** + """ + # TODO: Add a deadline? + # See comment in setuptools.unicode_utils._Utf8EncodingNeeded + warnings.warn(msg, PkgResourcesDeprecationWarning, stacklevel=2) + with open(file, "r", encoding=fallback_encoding) as f: + return f.read() + + # from jaraco.functools 1.3 def _call_aside(f, *args, **kwargs): f(*args, **kwargs) @@ -3498,35 +3530,3 @@ def _initialize_master_working_set(): add_activation_listener = working_set.subscribe run_script = working_set.run_script run_main = run_script - - -# ---- Ported from ``setuptools`` to avoid introducing an import inter-dependency ---- -LOCALE_ENCODING = "locale" if sys.version_info >= (3, 10) else None - - -def _read_utf8_with_fallback(file: str, fallback_encoding=LOCALE_ENCODING) -> str: - """See setuptools.unicode_utils._read_utf8_with_fallback""" - try: - with open(file, "r", encoding="utf-8") as f: - return f.read() - except UnicodeDecodeError: # pragma: no cover - msg = f"""\ - ******************************************************************************** - `encoding="utf-8"` fails with {file!r}, trying `encoding={fallback_encoding!r}`. - - This fallback behaviour is considered **deprecated** and future versions of - `setuptools/pkg_resources` may not implement it. - - Please encode {file!r} with "utf-8" to ensure future builds will succeed. - - If this file was produced by `setuptools` itself, cleaning up the cached files - and re-building/re-installing the package with a newer version of `setuptools` - (e.g. by updating `build-system.requires` in its `pyproject.toml`) - might solve the problem. - ******************************************************************************** - """ - # TODO: Add a deadline? - # See comment in setuptools.unicode_utils._Utf8EncodingNeeded - warnings.warn(msg, PkgResourcesDeprecationWarning, stacklevel=2) - with open(file, "r", encoding=fallback_encoding) as f: - return f.read() From 03edaaa41059cf580709ec714586a6f7762cd99d Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Mon, 17 Jun 2024 17:14:59 +0100 Subject: [PATCH 3/6] Add newsfragment --- newsfragments/4422.misc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 newsfragments/4422.misc.rst diff --git a/newsfragments/4422.misc.rst b/newsfragments/4422.misc.rst new file mode 100644 index 0000000000..e45b6d44b2 --- /dev/null +++ b/newsfragments/4422.misc.rst @@ -0,0 +1 @@ +Reorder code in ``pkg_resources/__init__.py`` to avoid definitions after ``@_call_aside``. From 06fd687e048224fc2293be50ed30d7f1a04378f4 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Wed, 19 Jun 2024 13:04:11 +0100 Subject: [PATCH 4/6] Move integration test to pkg_resources --- .../tests/test_integration_zope_interface.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename setuptools/tests/integration/test_zope_interface.py => pkg_resources/tests/test_integration_zope_interface.py (100%) diff --git a/setuptools/tests/integration/test_zope_interface.py b/pkg_resources/tests/test_integration_zope_interface.py similarity index 100% rename from setuptools/tests/integration/test_zope_interface.py rename to pkg_resources/tests/test_integration_zope_interface.py From 051e70d9b232c5c24b3a64a4fdac07e9a347c4fb Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Wed, 19 Jun 2024 13:06:28 +0100 Subject: [PATCH 5/6] Simplify integration test for zop interface --- .../tests/test_integration_zope_interface.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/pkg_resources/tests/test_integration_zope_interface.py b/pkg_resources/tests/test_integration_zope_interface.py index c340c4137d..634025c238 100644 --- a/pkg_resources/tests/test_integration_zope_interface.py +++ b/pkg_resources/tests/test_integration_zope_interface.py @@ -1,6 +1,4 @@ import platform -import subprocess -import sys from inspect import cleandoc import jaraco.path @@ -8,15 +6,6 @@ pytestmark = pytest.mark.integration -VIRTUALENV = (sys.executable, "-m", "virtualenv") - - -def run(cmd, **kwargs): - proc = subprocess.run(cmd, encoding="utf-8", capture_output=True, **kwargs) - if proc.returncode != 0: - pytest.fail(f"Command {cmd} failed with:\n{proc.stdout=!s}\n{proc.stderr=!s}") - return proc.stdout - @pytest.mark.skipif( platform.system() != "Linux", @@ -55,7 +44,7 @@ def bar(): } } jaraco.path.build(project, prefix=tmp_path) - cmd = [venv.exe("pip"), "install", "-e", ".", "--no-use-pep517"] - run(cmd, cwd=tmp_path / "pkg") - out = run([venv.exe("foo")]) + cmd = ["pip", "install", "-e", ".", "--no-use-pep517"] + venv.run(cmd, cwd=tmp_path / "pkg") # Needs this version of pkg_resources installed + out = venv.run(["foo"]) assert "Print me if you can" in out From a4b15f3a07c914c1da9bda2cf458237c97d0e042 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Wed, 19 Jun 2024 13:09:32 +0100 Subject: [PATCH 6/6] Add comments on test --- pkg_resources/tests/test_integration_zope_interface.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg_resources/tests/test_integration_zope_interface.py b/pkg_resources/tests/test_integration_zope_interface.py index 634025c238..4e37c3401b 100644 --- a/pkg_resources/tests/test_integration_zope_interface.py +++ b/pkg_resources/tests/test_integration_zope_interface.py @@ -7,6 +7,10 @@ pytestmark = pytest.mark.integration +# For the sake of simplicity this test uses fixtures defined in +# `setuptools.test.fixtures`, +# and it also exercise conditions considered deprecated... +# So if needed this test can be deleted. @pytest.mark.skipif( platform.system() != "Linux", reason="only demonstrated to fail on Linux in #4399",