summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2022-07-03 20:10:33 -0400
committerJason R. Coombs <jaraco@jaraco.com>2022-07-03 20:17:54 -0400
commitcd62fb6f7c4fc9df6407a0edb23231e39a7954ed (patch)
tree2cf2e8594e0f94026409732227eafd5d58cfad9f
parent120d9270c50a07caad0c697ca1f4b865226dde99 (diff)
parent152c13de811b302dcc673f6ed4c595cd29fd671d (diff)
downloadpython-setuptools-git-cd62fb6f7c4fc9df6407a0edb23231e39a7954ed.tar.gz
Merge with pypa/distutils@152c13d
-rw-r--r--changelog.d/3430.change.rst1
-rw-r--r--setuptools/_distutils/command/_framework_compat.py52
-rw-r--r--setuptools/_distutils/command/build_py.py7
-rw-r--r--setuptools/_distutils/command/install.py9
-rw-r--r--setuptools/_distutils/cygwinccompiler.py19
-rw-r--r--setuptools/_distutils/tests/test_build_py.py42
-rw-r--r--setuptools/_distutils/tests/test_cygwinccompiler.py6
7 files changed, 128 insertions, 8 deletions
diff --git a/changelog.d/3430.change.rst b/changelog.d/3430.change.rst
new file mode 100644
index 00000000..10bf768c
--- /dev/null
+++ b/changelog.d/3430.change.rst
@@ -0,0 +1 @@
+Merge with pypa/distutils@152c13d including pypa/distutils#155 (improved compatibility for editable installs on homebrew Python 3.9), pypa/distutils#150 (better handling of runtime_library_dirs on cygwin), and pypa/distutils#151 (remove warnings for namespace packages).
diff --git a/setuptools/_distutils/command/_framework_compat.py b/setuptools/_distutils/command/_framework_compat.py
new file mode 100644
index 00000000..e032603a
--- /dev/null
+++ b/setuptools/_distutils/command/_framework_compat.py
@@ -0,0 +1,52 @@
+"""
+Backward compatibility for homebrew builds on macOS.
+"""
+
+
+import sys
+import os
+import functools
+import subprocess
+
+
+@functools.lru_cache()
+def enabled():
+ """
+ Only enabled for Python 3.9 framework builds except ensurepip and venv.
+ """
+ PY39 = (3, 9) < sys.version_info < (3, 10)
+ framework = sys.platform == 'darwin' and sys._framework
+ venv = sys.prefix != sys.base_prefix
+ ensurepip = os.environ.get("ENSUREPIP_OPTIONS")
+ return PY39 and framework and not venv and not ensurepip
+
+
+schemes = dict(
+ osx_framework_library=dict(
+ stdlib='{installed_base}/{platlibdir}/python{py_version_short}',
+ platstdlib='{platbase}/{platlibdir}/python{py_version_short}',
+ purelib='{homebrew_prefix}/lib/python{py_version_short}/site-packages',
+ platlib='{homebrew_prefix}/{platlibdir}/python{py_version_short}/site-packages',
+ include='{installed_base}/include/python{py_version_short}{abiflags}',
+ platinclude='{installed_platbase}/include/python{py_version_short}{abiflags}',
+ scripts='{homebrew_prefix}/bin',
+ data='{homebrew_prefix}',
+ )
+)
+
+
+@functools.lru_cache()
+def vars():
+ if not enabled():
+ return {}
+ homebrew_prefix = subprocess.check_output(['brew', '--prefix'], text=True).strip()
+ return locals()
+
+
+def scheme(name):
+ """
+ Override the selected scheme for posix_prefix.
+ """
+ if not enabled() or not name.endswith('_prefix'):
+ return name
+ return 'osx_framework_library'
diff --git a/setuptools/_distutils/command/build_py.py b/setuptools/_distutils/command/build_py.py
index 1b22004e..7723d359 100644
--- a/setuptools/_distutils/command/build_py.py
+++ b/setuptools/_distutils/command/build_py.py
@@ -201,16 +201,11 @@ class build_py(Command):
"but is not a directory" % package_dir
)
- # Require __init__.py for all but the "root package"
+ # Directories without __init__.py are namespace packages (PEP 420).
if package:
init_py = os.path.join(package_dir, "__init__.py")
if os.path.isfile(init_py):
return init_py
- else:
- log.warn(
- ("package init file '%s' not found " + "(or not a regular file)"),
- init_py,
- )
# Either not in a package at all (__init__.py not expected), or
# __init__.py doesn't exist -- so don't return the filename.
diff --git a/setuptools/_distutils/command/install.py b/setuptools/_distutils/command/install.py
index 0660406f..7d9054e3 100644
--- a/setuptools/_distutils/command/install.py
+++ b/setuptools/_distutils/command/install.py
@@ -17,6 +17,7 @@ from distutils.file_util import write_file
from distutils.util import convert_path, subst_vars, change_root
from distutils.util import get_platform
from distutils.errors import DistutilsOptionError
+from . import _framework_compat as fw
from .. import _collections
from site import USER_BASE
@@ -82,6 +83,10 @@ if HAS_USER_SITE:
'data': '{userbase}',
}
+
+INSTALL_SCHEMES.update(fw.schemes)
+
+
# The keys to an installation scheme; if any new types of files are to be
# installed, be sure to add an entry to every installation scheme above,
# and to SCHEME_KEYS here.
@@ -136,7 +141,7 @@ def _resolve_scheme(name):
try:
resolved = sysconfig.get_preferred_scheme(key)
except Exception:
- resolved = _pypy_hack(name)
+ resolved = fw.scheme(_pypy_hack(name))
return resolved
@@ -426,7 +431,7 @@ class install(Command):
local_vars['usersite'] = self.install_usersite
self.config_vars = _collections.DictStack(
- [compat_vars, sysconfig.get_config_vars(), local_vars]
+ [fw.vars(), compat_vars, sysconfig.get_config_vars(), local_vars]
)
self.expand_basedirs()
diff --git a/setuptools/_distutils/cygwinccompiler.py b/setuptools/_distutils/cygwinccompiler.py
index 931b3661..445e2e51 100644
--- a/setuptools/_distutils/cygwinccompiler.py
+++ b/setuptools/_distutils/cygwinccompiler.py
@@ -58,6 +58,7 @@ from distutils.unixccompiler import UnixCCompiler
from distutils.file_util import write_file
from distutils.errors import (
DistutilsExecError,
+ DistutilsPlatformError,
CCompilerError,
CompileError,
UnknownFileError,
@@ -197,6 +198,12 @@ class CygwinCCompiler(UnixCCompiler):
libraries = copy.copy(libraries or [])
objects = copy.copy(objects or [])
+ if runtime_library_dirs:
+ self.warn(
+ "I don't know what to do with 'runtime_library_dirs': "
+ + str(runtime_library_dirs)
+ )
+
# Additional libraries
libraries.extend(self.dll_libraries)
@@ -265,6 +272,13 @@ class CygwinCCompiler(UnixCCompiler):
target_lang,
)
+ def runtime_library_dir_option(self, dir):
+ # cygwin doesn't support rpath. While in theory we could error
+ # out like MSVC does, code might expect it to work like on Unix, so
+ # just warn and hope for the best.
+ self.warn("don't know how to set runtime library search path on Windows")
+ return []
+
# -- Miscellaneous methods -----------------------------------------
def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
@@ -325,6 +339,11 @@ class Mingw32CCompiler(CygwinCCompiler):
# with MSVC 7.0 or later.
self.dll_libraries = get_msvcr()
+ def runtime_library_dir_option(self, dir):
+ raise DistutilsPlatformError(
+ "don't know how to set runtime library search path on Windows"
+ )
+
# Because these compilers aren't configured in Python's pyconfig.h file by
# default, we should at least warn the user if he is using an unmodified
diff --git a/setuptools/_distutils/tests/test_build_py.py b/setuptools/_distutils/tests/test_build_py.py
index 4585d799..eb01d81a 100644
--- a/setuptools/_distutils/tests/test_build_py.py
+++ b/setuptools/_distutils/tests/test_build_py.py
@@ -7,6 +7,7 @@ import unittest
from distutils.command.build_py import build_py
from distutils.core import Distribution
from distutils.errors import DistutilsFileError
+from unittest.mock import patch
from distutils.tests import support
from test.support import run_unittest
@@ -167,6 +168,47 @@ class BuildPyTestCase(
self.assertIn('byte-compiling is disabled', self.logs[0][1] % self.logs[0][2])
+ @patch("distutils.command.build_py.log.warn")
+ def test_namespace_package_does_not_warn(self, log_warn):
+ """
+ Originally distutils implementation did not account for PEP 420
+ and included warns for package directories that did not contain
+ ``__init__.py`` files.
+ After the acceptance of PEP 420, these warnings don't make more sense
+ so we want to ensure there are not displayed to not confuse the users.
+ """
+ # Create a fake project structure with a package namespace:
+ tmp = self.mkdtemp()
+ os.chdir(tmp)
+ os.makedirs("ns/pkg")
+ open("ns/pkg/module.py", "w").close()
+
+ # Set up a trap if the undesirable effect is observed:
+ def _trap(msg, *args):
+ if "package init file" in msg and "not found" in msg:
+ raise AssertionError(f"Undesired warning: {msg!r} {args!r}")
+
+ log_warn.side_effect = _trap
+
+ # Configure the package:
+ attrs = {
+ "name": "ns.pkg",
+ "packages": ["ns", "ns.pkg"],
+ "script_name": "setup.py",
+ }
+ dist = Distribution(attrs)
+
+ # Run code paths that would trigger the trap:
+ cmd = dist.get_command_obj("build_py")
+ cmd.finalize_options()
+ modules = cmd.find_all_modules()
+ assert len(modules) == 1
+ module_path = modules[0][-1]
+ assert module_path.replace(os.sep, "/") == "ns/pkg/module.py"
+
+ cmd.run()
+ # Test should complete successfully with no exception
+
def test_suite():
return unittest.TestLoader().loadTestsFromTestCase(BuildPyTestCase)
diff --git a/setuptools/_distutils/tests/test_cygwinccompiler.py b/setuptools/_distutils/tests/test_cygwinccompiler.py
index b3c164ed..7760436a 100644
--- a/setuptools/_distutils/tests/test_cygwinccompiler.py
+++ b/setuptools/_distutils/tests/test_cygwinccompiler.py
@@ -48,6 +48,12 @@ class CygwinCCompilerTestCase(support.TempdirManager, unittest.TestCase):
self.assertTrue(os.path.exists(linkable_file))
self.assertEquals(linkable_file, "/usr/lib/lib{:s}.dll.a".format(link_name))
+ @unittest.skipIf(sys.platform != "cygwin", "Not running on Cygwin")
+ def test_runtime_library_dir_option(self):
+ from distutils.cygwinccompiler import CygwinCCompiler
+ compiler = CygwinCCompiler()
+ self.assertEqual(compiler.runtime_library_dir_option('/foo'), [])
+
def test_check_config_h(self):
# check_config_h looks for "GCC" in sys.version first