Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge with pypa/distutils@6852b20 #3617

Merged
merged 29 commits into from Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
8878032
Use path.Path for changing the cwd temporarily.
jaraco Sep 24, 2022
9b6aadf
Remove needless assert renderings. Any decent test runner will provid…
jaraco Sep 24, 2022
01b7e7f
Remove reference to duplicate issue.
jaraco Sep 24, 2022
ef5eeb3
Refactor _is_python_source_dir using pathlib.
jaraco Sep 24, 2022
b25c1ea
Use 'samefile' to check for same file, because they may not be the sa…
jaraco Sep 24, 2022
0e01a9b
Split test into two tests.
jaraco Sep 24, 2022
b0ee610
Use pathlib
jaraco Sep 25, 2022
a5abb05
Remove special case for TestCore.write_setup.
jaraco Sep 25, 2022
6d49c53
Replace TESTFN with temp_file fixture.
jaraco Sep 25, 2022
b74612b
Remove 'cleanup_testfn', unused.
jaraco Sep 25, 2022
7a88119
Remove distracting comments
jaraco Sep 25, 2022
7064287
In test_sysconfig, prefer fixtures to TESTFN.
jaraco Sep 25, 2022
917d8e2
Remove cleanup_testfn, no longer used.
jaraco Sep 25, 2022
e115de7
Replace TESTFN with fixture.
jaraco Sep 25, 2022
c7655fd
Remove empty logic branch.
jaraco Sep 25, 2022
e081813
Use path.Path for changing the cwd temporarily.
jaraco Sep 25, 2022
835bc17
Remove reliance on TESTFN in test_dist
jaraco Sep 25, 2022
c073b6f
Remove TESTFN from py38compat, no longer needed.
jaraco Sep 25, 2022
a3e4591
xfail srcdir_simple on Windows
jaraco Sep 25, 2022
fad6dbd
Remove reliance on os_helper in test_build_ext
jaraco Sep 25, 2022
a74bcdf
Remove reliance on change_cwd
jaraco Sep 25, 2022
096a5cc
Add compatibility shim for subprocess on Python 3.7 on Windows
jaraco Sep 25, 2022
be4c242
Extract _save_cwd for saving the current working directory.
jaraco Sep 25, 2022
3980ab7
Prefer a temp_cwd fixture to reduce indentation.
jaraco Sep 25, 2022
d2529ff
Remove reliance on create_empty_file
jaraco Sep 25, 2022
faaf778
Add test for PermissionError. Ref pypa/distutils#181.
jaraco Sep 29, 2022
6852b20
Use os.path.isfile for checking if path.is_file, suppresses exception…
jaraco Sep 29, 2022
aea5615
Merge https://github.com/pypa/distutils into distutils-6852b20
jaraco Sep 29, 2022
58b9692
Update changelog
jaraco Sep 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/3617.misc.rst
@@ -0,0 +1 @@
Merge with pypa/distutils@6852b20 including fix for pypa/distutils#181.
2 changes: 1 addition & 1 deletion setuptools/_distutils/dist.py
Expand Up @@ -334,7 +334,7 @@ def find_config_files(self):
- a file named by an environment variable
"""
check_environ()
files = [str(path) for path in self._gen_paths() if path.is_file()]
files = [str(path) for path in self._gen_paths() if os.path.isfile(path)]

if DEBUG:
self.announce("using config files: %s" % ', '.join(files))
Expand Down
14 changes: 7 additions & 7 deletions setuptools/_distutils/sysconfig.py
Expand Up @@ -13,6 +13,7 @@
import re
import sys
import sysconfig
import pathlib

from .errors import DistutilsPlatformError
from . import py39compat
Expand Down Expand Up @@ -40,14 +41,13 @@
project_base = os.getcwd()


# python_build: (Boolean) if true, we're either building Python or
# building an extension with an un-installed Python, so we use
# different (hard-wired) directories.
def _is_python_source_dir(d):
for fn in ("Setup", "Setup.local"):
if os.path.isfile(os.path.join(d, "Modules", fn)):
return True
return False
"""
Return True if the target directory appears to point to an
un-installed Python.
"""
modules = pathlib.Path(d).joinpath('Modules')
return any(modules.joinpath(fn).is_file() for fn in ('Setup', 'Setup.local'))


_sys_home = getattr(sys, '_home', None)
Expand Down
18 changes: 18 additions & 0 deletions setuptools/_distutils/tests/py37compat.py
@@ -0,0 +1,18 @@
import os
import sys
import platform


def subprocess_args_compat(*args):
return list(map(os.fspath, args))


def subprocess_args_passthrough(*args):
return list(args)


subprocess_args = (
subprocess_args_compat
if platform.system() == "Windows" and sys.version_info < (3, 8)
else subprocess_args_passthrough
)
8 changes: 0 additions & 8 deletions setuptools/_distutils/tests/py38compat.py
Expand Up @@ -18,27 +18,19 @@

try:
from test.support.os_helper import (
change_cwd,
rmtree,
EnvironmentVarGuard,
TESTFN,
unlink,
skip_unless_symlink,
temp_dir,
create_empty_file,
temp_cwd,
)
except (ModuleNotFoundError, ImportError):
from test.support import (
change_cwd,
rmtree,
EnvironmentVarGuard,
TESTFN,
unlink,
skip_unless_symlink,
temp_dir,
create_empty_file,
temp_cwd,
)


Expand Down
8 changes: 4 additions & 4 deletions setuptools/_distutils/tests/test_archive_util.py
Expand Up @@ -9,6 +9,7 @@
import pathlib

import pytest
import path

from distutils import archive_util
from distutils.archive_util import (
Expand All @@ -23,7 +24,6 @@
from test.support import patch
from .unix_compat import require_unix_id, require_uid_0, grp, pwd, UID_0_SUPPORT

from .py38compat import change_cwd
from .py38compat import check_warnings


Expand Down Expand Up @@ -95,7 +95,7 @@ def _make_tarball(self, tmpdir, target_name, suffix, **kwargs):
base_name = os.path.join(tmpdir2, target_name)

# working with relative paths to avoid tar warnings
with change_cwd(tmpdir):
with path.Path(tmpdir):
make_tarball(splitdrive(base_name)[1], 'dist', **kwargs)

# check if the compressed tarball was created
Expand Down Expand Up @@ -227,7 +227,7 @@ def test_make_zipfile(self):
# creating something to tar
tmpdir = self._create_files()
base_name = os.path.join(self.mkdtemp(), 'archive')
with change_cwd(tmpdir):
with path.Path(tmpdir):
make_zipfile(base_name, 'dist')

# check if the compressed tarball was created
Expand All @@ -253,7 +253,7 @@ def fake_zipfile(*a, **kw):
# create something to tar and compress
tmpdir = self._create_files()
base_name = os.path.join(self.mkdtemp(), 'archive')
with change_cwd(tmpdir):
with path.Path(tmpdir):
make_zipfile(base_name, 'dist')

tarball = base_name + '.zip'
Expand Down
9 changes: 5 additions & 4 deletions setuptools/_distutils/tests/test_build_ext.py
Expand Up @@ -8,6 +8,10 @@
import tempfile
import importlib
import shutil
import re

import path
import pytest

from distutils.core import Distribution
from distutils.command.build_ext import build_ext
Expand All @@ -27,10 +31,7 @@
)

from test import support
from . import py38compat as os_helper
from . import py38compat as import_helper
import pytest
import re


@pytest.fixture()
Expand All @@ -47,7 +48,7 @@ def user_site_dir(request):
# bpo-30132: On Windows, a .pdb file may be created in the current
# working directory. Create a temporary working directory to cleanup
# everything at the end of the test.
with os_helper.change_cwd(self.tmp_dir):
with path.Path(self.tmp_dir):
yield

site.USER_BASE = orig_user_base
Expand Down
59 changes: 28 additions & 31 deletions setuptools/_distutils/tests/test_core.py
Expand Up @@ -8,7 +8,6 @@

import pytest

from . import py38compat as os_helper
from distutils.dist import Distribution

# setup script that uses __file__
Expand Down Expand Up @@ -61,65 +60,63 @@ def save_stdout(monkeypatch):
monkeypatch.setattr(sys, 'stdout', sys.stdout)


@pytest.fixture
def temp_file(tmp_path):
return tmp_path / 'file'


@pytest.mark.usefixtures('save_env')
@pytest.mark.usefixtures('save_argv')
@pytest.mark.usefixtures('cleanup_testfn')
class TestCore:
def write_setup(self, text, path=os_helper.TESTFN):
f = open(path, "w")
try:
f.write(text)
finally:
f.close()
return path

def test_run_setup_provides_file(self):
def test_run_setup_provides_file(self, temp_file):
# Make sure the script can use __file__; if that's missing, the test
# setup.py script will raise NameError.
distutils.core.run_setup(self.write_setup(setup_using___file__))
temp_file.write_text(setup_using___file__)
distutils.core.run_setup(temp_file)

def test_run_setup_preserves_sys_argv(self):
def test_run_setup_preserves_sys_argv(self, temp_file):
# Make sure run_setup does not clobber sys.argv
argv_copy = sys.argv.copy()
distutils.core.run_setup(self.write_setup(setup_does_nothing))
temp_file.write_text(setup_does_nothing)
distutils.core.run_setup(temp_file)
assert sys.argv == argv_copy

def test_run_setup_defines_subclass(self):
def test_run_setup_defines_subclass(self, temp_file):
# Make sure the script can use __file__; if that's missing, the test
# setup.py script will raise NameError.
dist = distutils.core.run_setup(self.write_setup(setup_defines_subclass))
temp_file.write_text(setup_defines_subclass)
dist = distutils.core.run_setup(temp_file)
install = dist.get_command_obj('install')
assert 'cmd' in install.sub_commands

def test_run_setup_uses_current_dir(self):
# This tests that the setup script is run with the current directory
# as its own current directory; this was temporarily broken by a
# previous patch when TESTFN did not use the current directory.
def test_run_setup_uses_current_dir(self, tmp_path):
"""
Test that the setup script is run with the current directory
as its own current directory.
"""
sys.stdout = io.StringIO()
cwd = os.getcwd()

# Create a directory and write the setup.py file there:
os.mkdir(os_helper.TESTFN)
setup_py = os.path.join(os_helper.TESTFN, "setup.py")
distutils.core.run_setup(self.write_setup(setup_prints_cwd, path=setup_py))
setup_py = tmp_path / 'setup.py'
setup_py.write_text(setup_prints_cwd)
distutils.core.run_setup(setup_py)

output = sys.stdout.getvalue()
if output.endswith("\n"):
output = output[:-1]
assert cwd == output

def test_run_setup_within_if_main(self):
dist = distutils.core.run_setup(
self.write_setup(setup_within_if_main), stop_after="config"
)
def test_run_setup_within_if_main(self, temp_file):
temp_file.write_text(setup_within_if_main)
dist = distutils.core.run_setup(temp_file, stop_after="config")
assert isinstance(dist, Distribution)
assert dist.get_name() == "setup_within_if_main"

def test_run_commands(self):
def test_run_commands(self, temp_file):
sys.argv = ['setup.py', 'build']
dist = distutils.core.run_setup(
self.write_setup(setup_within_if_main), stop_after="commandline"
)
temp_file.write_text(setup_within_if_main)
dist = distutils.core.run_setup(temp_file, stop_after="commandline")
assert 'build' not in dist.have_run
distutils.core.run_commands(dist)
assert 'build' in dist.have_run
Expand Down
37 changes: 24 additions & 13 deletions setuptools/_distutils/tests/test_dist.py
Expand Up @@ -14,7 +14,6 @@
from distutils.cmd import Command

from test.support import captured_stdout, captured_stderr
from .py38compat import TESTFN
from distutils.tests import support
from distutils import log

Expand Down Expand Up @@ -95,15 +94,15 @@ def test_command_packages_cmdline(self, clear_argv):
'distutils' not in Distribution.parse_config_files.__module__,
reason='Cannot test when virtualenv has monkey-patched Distribution',
)
def test_venv_install_options(self, request):
def test_venv_install_options(self, tmp_path):
sys.argv.append("install")
request.addfinalizer(functools.partial(os.unlink, TESTFN))
file = str(tmp_path / 'file')

fakepath = '/somedir'

jaraco.path.build(
{
TESTFN: f"""
file: f"""
[install]
install-base = {fakepath}
install-platbase = {fakepath}
Expand All @@ -124,9 +123,9 @@ def test_venv_install_options(self, request):

# Base case: Not in a Virtual Environment
with mock.patch.multiple(sys, prefix='/a', base_prefix='/a'):
d = self.create_distribution([TESTFN])
d = self.create_distribution([file])

option_tuple = (TESTFN, fakepath)
option_tuple = (file, fakepath)

result_dict = {
'install_base': option_tuple,
Expand All @@ -153,35 +152,35 @@ def test_venv_install_options(self, request):

# Test case: In a Virtual Environment
with mock.patch.multiple(sys, prefix='/a', base_prefix='/b'):
d = self.create_distribution([TESTFN])
d = self.create_distribution([file])

for key in result_dict.keys():
assert key not in d.command_options.get('install', {})

def test_command_packages_configfile(self, request, clear_argv):
def test_command_packages_configfile(self, tmp_path, clear_argv):
sys.argv.append("build")
request.addfinalizer(functools.partial(os.unlink, TESTFN))
file = str(tmp_path / "file")
jaraco.path.build(
{
TESTFN: """
file: """
[global]
command_packages = foo.bar, splat
""",
}
)

d = self.create_distribution([TESTFN])
d = self.create_distribution([file])
assert d.get_command_packages() == ["distutils.command", "foo.bar", "splat"]

# ensure command line overrides config:
sys.argv[1:] = ["--command-packages", "spork", "build"]
d = self.create_distribution([TESTFN])
d = self.create_distribution([file])
assert d.get_command_packages() == ["distutils.command", "spork"]

# Setting --command-packages to '' should cause the default to
# be used even if a config file specified something else:
sys.argv[1:] = ["--command-packages", "", "build"]
d = self.create_distribution([TESTFN])
d = self.create_distribution([file])
assert d.get_command_packages() == ["distutils.command"]

def test_empty_options(self, request):
Expand Down Expand Up @@ -259,6 +258,18 @@ def test_find_config_files_disable(self, temp_home):
# make sure --no-user-cfg disables the user cfg file
assert len(all_files) - 1 == len(files)

@pytest.mark.skipif(
'platform.system() == "Windows"',
reason='Windows does not honor chmod 000',
)
def test_find_config_files_permission_error(self, fake_home):
"""
Finding config files should not fail when directory is inaccessible.
"""
fake_home.joinpath(pydistutils_cfg).write_text('')
fake_home.chmod(0o000)
Distribution().find_config_files()


@pytest.mark.usefixtures('save_env')
@pytest.mark.usefixtures('save_argv')
Expand Down