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 distutils@d82d926 #3609

Merged
merged 23 commits into from Sep 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f545f29
Revert "Exclude Python 3.11 on macOS due to lack of wheels. Ref pypa/…
jaraco Sep 24, 2022
3f39e17
Restore metadata tests (not discovered due to class name).
jaraco Sep 24, 2022
ef78ba5
Add DISTUTILS_EXTRA_CONFIG option for passing setup.cfg overrides dur…
zooba Sep 1, 2022
825f02a
Fix name in test
zooba Sep 1, 2022
457df38
Prefer monkeypatch for setting environment variable
jaraco Sep 24, 2022
a361461
Use tmp_path and jaraco.path.build to build files.
jaraco Sep 24, 2022
57de35b
Use functools.lru_cache to memoize check_environ.
jaraco Sep 24, 2022
c7d65dd
Use pathlib for generating paths and generate the paths in a separate…
jaraco Sep 24, 2022
48eb7ff
Merge branch 'main' into extra-config
jaraco Sep 24, 2022
98a46db
Update docs to reference environment variable.
jaraco Sep 24, 2022
8620c04
Rename environment variable to DIST_EXTRA_CONFIG, decoupling it from …
jaraco Sep 24, 2022
0d022d6
Merge pull request #177 from zooba/extra-config
jaraco Sep 24, 2022
19c0e93
Simplify logic in test_custom_pydistutils
jaraco Sep 24, 2022
4ea21ea
Inline variables used once
jaraco Sep 24, 2022
66d0ccd
Remove meaningless dot from config files
jaraco Sep 24, 2022
1587bbb
Extract a temp_home fixture.
jaraco Sep 24, 2022
b26aa11
Re-use temp_home in test_find_config_files_disable
jaraco Sep 24, 2022
aac4d4f
Extract property for pydistutils.cfg name
jaraco Sep 24, 2022
00608cb
Move property to a module attribute and re-use jaraco.path for simple…
jaraco Sep 24, 2022
01d6f1d
Use jaraco.path for more tests
jaraco Sep 24, 2022
d82d926
Fix warning in test
jaraco Sep 24, 2022
3bae752
Merge https://github.com/pypa/distutils into distutils-d82d926
jaraco Sep 24, 2022
517587c
Add changelog.
jaraco Sep 24, 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/3609.change.rst
@@ -0,0 +1 @@
Merge with pypa/distutils@d82d926 including support for DIST_EXTRA_CONFIG in pypa/distutils#177.
3 changes: 2 additions & 1 deletion docs/deprecated/distutils/configfile.rst
Expand Up @@ -36,7 +36,8 @@ consequences:
:file:`setup.py`

* installers can override anything in :file:`setup.cfg` using the command-line
options to :file:`setup.py`
options to :file:`setup.py` or by pointing :envvar:`DIST_EXTRA_CONFIG`
to another configuration file

The basic syntax of the configuration file is simple:

Expand Down
57 changes: 26 additions & 31 deletions setuptools/_distutils/dist.py
Expand Up @@ -7,6 +7,8 @@
import sys
import os
import re
import pathlib
import contextlib
from email import message_from_file

try:
Expand Down Expand Up @@ -322,47 +324,40 @@ def find_config_files(self):
should be parsed. The filenames returned are guaranteed to exist
(modulo nasty race conditions).

There are three possible config files: distutils.cfg in the
Distutils installation directory (ie. where the top-level
Distutils __inst__.py file lives), a file in the user's home
directory named .pydistutils.cfg on Unix and pydistutils.cfg
on Windows/Mac; and setup.cfg in the current directory.

The file in the user's home directory can be disabled with the
--no-user-cfg option.
There are multiple possible config files:
- distutils.cfg in the Distutils installation directory (i.e.
where the top-level Distutils __inst__.py file lives)
- a file in the user's home directory named .pydistutils.cfg
on Unix and pydistutils.cfg on Windows/Mac; may be disabled
with the ``--no-user-cfg`` option
- setup.cfg in the current directory
- a file named by an environment variable
"""
files = []
check_environ()
files = [str(path) for path in self._gen_paths() if path.is_file()]

# Where to look for the system-wide Distutils config file
sys_dir = os.path.dirname(sys.modules['distutils'].__file__)
if DEBUG:
self.announce("using config files: %s" % ', '.join(files))

# Look for the system config file
sys_file = os.path.join(sys_dir, "distutils.cfg")
if os.path.isfile(sys_file):
files.append(sys_file)
return files

# What to call the per-user config file
if os.name == 'posix':
user_filename = ".pydistutils.cfg"
else:
user_filename = "pydistutils.cfg"
def _gen_paths(self):
# The system-wide Distutils config file
sys_dir = pathlib.Path(sys.modules['distutils'].__file__).parent
yield sys_dir / "distutils.cfg"

# And look for the user config file
# The per-user config file
prefix = '.' * (os.name == 'posix')
filename = prefix + 'pydistutils.cfg'
if self.want_user_cfg:
user_file = os.path.join(os.path.expanduser('~'), user_filename)
if os.path.isfile(user_file):
files.append(user_file)
yield pathlib.Path('~').expanduser() / filename

# All platforms support local setup.cfg
local_file = "setup.cfg"
if os.path.isfile(local_file):
files.append(local_file)
yield pathlib.Path('setup.cfg')

if DEBUG:
self.announce("using config files: %s" % ', '.join(files))

return files
# Additional config indicated in the environment
with contextlib.suppress(TypeError):
yield pathlib.Path(os.getenv("DIST_EXTRA_CONFIG"))

def parse_config_files(self, filenames=None): # noqa: C901
from configparser import ConfigParser
Expand Down
141 changes: 56 additions & 85 deletions setuptools/_distutils/tests/test_dist.py
Expand Up @@ -8,6 +8,7 @@
import unittest.mock as mock

import pytest
import jaraco.path

from distutils.dist import Distribution, fix_help_options
from distutils.cmd import Command
Expand All @@ -18,6 +19,9 @@
from distutils import log


pydistutils_cfg = '.' * (os.name == 'posix') + 'pydistutils.cfg'


class test_dist(Command):
"""Sample distutils extension command."""

Expand Down Expand Up @@ -97,26 +101,26 @@ def test_venv_install_options(self, request):

fakepath = '/somedir'

with open(TESTFN, "w") as f:
print(
(
"[install]\n"
"install-base = {0}\n"
"install-platbase = {0}\n"
"install-lib = {0}\n"
"install-platlib = {0}\n"
"install-purelib = {0}\n"
"install-headers = {0}\n"
"install-scripts = {0}\n"
"install-data = {0}\n"
"prefix = {0}\n"
"exec-prefix = {0}\n"
"home = {0}\n"
"user = {0}\n"
"root = {0}"
).format(fakepath),
file=f,
)
jaraco.path.build(
{
TESTFN: f"""
[install]
install-base = {fakepath}
install-platbase = {fakepath}
install-lib = {fakepath}
install-platlib = {fakepath}
install-purelib = {fakepath}
install-headers = {fakepath}
install-scripts = {fakepath}
install-data = {fakepath}
prefix = {fakepath}
exec-prefix = {fakepath}
home = {fakepath}
user = {fakepath}
root = {fakepath}
""",
}
)

# Base case: Not in a Virtual Environment
with mock.patch.multiple(sys, prefix='/a', base_prefix='/a'):
Expand Down Expand Up @@ -157,12 +161,14 @@ def test_venv_install_options(self, request):
def test_command_packages_configfile(self, request, clear_argv):
sys.argv.append("build")
request.addfinalizer(functools.partial(os.unlink, TESTFN))
f = open(TESTFN, "w")
try:
print("[global]", file=f)
print("command_packages = foo.bar, splat", file=f)
finally:
f.close()
jaraco.path.build(
{
TESTFN: """
[global]
command_packages = foo.bar, splat
""",
}
)

d = self.create_distribution([TESTFN])
assert d.get_command_packages() == ["distutils.command", "foo.bar", "splat"]
Expand Down Expand Up @@ -240,38 +246,23 @@ def test_announce(self):
with pytest.raises(ValueError):
dist.announce(args, kwargs)

def test_find_config_files_disable(self):
def test_find_config_files_disable(self, temp_home):
# Ticket #1180: Allow user to disable their home config file.
temp_home = self.mkdtemp()
if os.name == 'posix':
user_filename = os.path.join(temp_home, ".pydistutils.cfg")
else:
user_filename = os.path.join(temp_home, "pydistutils.cfg")

with open(user_filename, 'w') as f:
f.write('[distutils]\n')

def _expander(path):
return temp_home
jaraco.path.build({pydistutils_cfg: '[distutils]\n'}, temp_home)

old_expander = os.path.expanduser
os.path.expanduser = _expander
try:
d = Distribution()
all_files = d.find_config_files()
d = Distribution()
all_files = d.find_config_files()

d = Distribution(attrs={'script_args': ['--no-user-cfg']})
files = d.find_config_files()
finally:
os.path.expanduser = old_expander
d = Distribution(attrs={'script_args': ['--no-user-cfg']})
files = d.find_config_files()

# make sure --no-user-cfg disables the user cfg file
assert len(all_files) - 1 == len(files)


@pytest.mark.usefixtures('save_env')
@pytest.mark.usefixtures('save_argv')
class MetadataTestCase(support.TempdirManager):
class TestMetadata(support.TempdirManager):
def format_metadata(self, dist):
sio = io.StringIO()
dist.metadata.write_pkg_file(sio)
Expand Down Expand Up @@ -456,51 +447,31 @@ def test_long_description(self):
meta = meta.replace('\n' + 8 * ' ', '\n')
assert long_desc in meta

def test_custom_pydistutils(self):
# fixes #2166
# make sure pydistutils.cfg is found
if os.name == 'posix':
user_filename = ".pydistutils.cfg"
else:
user_filename = "pydistutils.cfg"

temp_dir = self.mkdtemp()
user_filename = os.path.join(temp_dir, user_filename)
f = open(user_filename, 'w')
try:
f.write('.')
finally:
f.close()

try:
dist = Distribution()

# linux-style
if sys.platform in ('linux', 'darwin'):
os.environ['HOME'] = temp_dir
files = dist.find_config_files()
assert user_filename in files

# win32-style
if sys.platform == 'win32':
# home drive should be found
os.environ['USERPROFILE'] = temp_dir
files = dist.find_config_files()
assert user_filename in files, '{!r} not found in {!r}'.format(
user_filename, files
)
finally:
os.remove(user_filename)
def test_custom_pydistutils(self, temp_home):
"""
pydistutils.cfg is found
"""
jaraco.path.build({pydistutils_cfg: ''}, temp_home)
config_path = temp_home / pydistutils_cfg

assert str(config_path) in Distribution().find_config_files()

def test_extra_pydistutils(self, monkeypatch, tmp_path):
jaraco.path.build({'overrides.cfg': ''}, tmp_path)
filename = tmp_path / 'overrides.cfg'
monkeypatch.setenv('DIST_EXTRA_CONFIG', str(filename))
assert str(filename) in Distribution().find_config_files()

def test_fix_help_options(self):
help_tuples = [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
fancy_options = fix_help_options(help_tuples)
assert fancy_options[0] == ('a', 'b', 'c')
assert fancy_options[1] == (1, 2, 3)

def test_show_help(self):
def test_show_help(self, request):
# smoke test, just makes sure some help is displayed
self.addCleanup(log.set_threshold, log._global_log.threshold)
reset_log = functools.partial(log.set_threshold, log._global_log.threshold)
request.addfinalizer(reset_log)
dist = Distribution()
sys.argv = []
dist.help = 1
Expand Down
7 changes: 3 additions & 4 deletions setuptools/_distutils/tests/test_util.py
Expand Up @@ -136,17 +136,16 @@ def _join(*path):
# XXX platforms to be covered: mac

def test_check_environ(self):
util._environ_checked = 0
util.check_environ.cache_clear()
os.environ.pop('HOME', None)

check_environ()

assert os.environ['PLAT'] == get_platform()
assert util._environ_checked == 1

@pytest.mark.skipif("os.name != 'posix'")
def test_check_environ_getpwuid(self):
util._environ_checked = 0
util.check_environ.cache_clear()
os.environ.pop('HOME', None)

import pwd
Expand All @@ -159,7 +158,7 @@ def test_check_environ_getpwuid(self):
check_environ()
assert os.environ['HOME'] == '/home/distutils'

util._environ_checked = 0
util.check_environ.cache_clear()
os.environ.pop('HOME', None)

# bpo-10496: Catch pwd.getpwuid() error
Expand Down
12 changes: 3 additions & 9 deletions setuptools/_distutils/util.py
Expand Up @@ -11,6 +11,8 @@
import subprocess
import sys
import sysconfig
import functools

from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError
from distutils.dep_util import newer
from distutils.spawn import spawn
Expand Down Expand Up @@ -170,9 +172,7 @@ def change_root(new_root, pathname):
raise DistutilsPlatformError(f"nothing known about platform '{os.name}'")


_environ_checked = 0


@functools.lru_cache()
def check_environ():
"""Ensure that 'os.environ' has all the environment variables we
guarantee that users can use in config files, command-line options,
Expand All @@ -181,10 +181,6 @@ def check_environ():
PLAT - description of the current platform, including hardware
and OS (see 'get_platform()')
"""
global _environ_checked
if _environ_checked:
return

if os.name == 'posix' and 'HOME' not in os.environ:
try:
import pwd
Expand All @@ -198,8 +194,6 @@ def check_environ():
if 'PLAT' not in os.environ:
os.environ['PLAT'] = get_platform()

_environ_checked = 1


def subst_vars(s, local_vars):
"""
Expand Down