summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2022-09-24 14:24:50 -0400
committerJason R. Coombs <jaraco@jaraco.com>2022-09-24 14:24:50 -0400
commit3bae7527d2a47b83e44f418e3c30af8a52a94cf1 (patch)
tree3f2d4d1603cb15a5ec6996676139d3b525c5eca3
parentba3995e5705a22e13bb5d2231ac22c77e4417747 (diff)
parentd82d926fa2a1f98cae05b21528fe2fafebb52938 (diff)
downloadpython-setuptools-git-3bae7527d2a47b83e44f418e3c30af8a52a94cf1.tar.gz
Merge https://github.com/pypa/distutils into distutils-d82d926
-rw-r--r--docs/deprecated/distutils/configfile.rst3
-rw-r--r--setuptools/_distutils/dist.py57
-rw-r--r--setuptools/_distutils/tests/test_dist.py141
-rw-r--r--setuptools/_distutils/tests/test_util.py7
-rw-r--r--setuptools/_distutils/util.py12
5 files changed, 90 insertions, 130 deletions
diff --git a/docs/deprecated/distutils/configfile.rst b/docs/deprecated/distutils/configfile.rst
index 328936fb..2a0fbb31 100644
--- a/docs/deprecated/distutils/configfile.rst
+++ b/docs/deprecated/distutils/configfile.rst
@@ -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:
diff --git a/setuptools/_distutils/dist.py b/setuptools/_distutils/dist.py
index 0406ab19..1dc25fe5 100644
--- a/setuptools/_distutils/dist.py
+++ b/setuptools/_distutils/dist.py
@@ -7,6 +7,8 @@ being built/installed/distributed.
import sys
import os
import re
+import pathlib
+import contextlib
from email import message_from_file
try:
@@ -322,47 +324,40 @@ Common commands: (see '--help-commands' for more)
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
diff --git a/setuptools/_distutils/tests/test_dist.py b/setuptools/_distutils/tests/test_dist.py
index ddfaf921..a9438326 100644
--- a/setuptools/_distutils/tests/test_dist.py
+++ b/setuptools/_distutils/tests/test_dist.py
@@ -8,6 +8,7 @@ import functools
import unittest.mock as mock
import pytest
+import jaraco.path
from distutils.dist import Distribution, fix_help_options
from distutils.cmd import Command
@@ -18,6 +19,9 @@ from distutils.tests import support
from distutils import log
+pydistutils_cfg = '.' * (os.name == 'posix') + 'pydistutils.cfg'
+
+
class test_dist(Command):
"""Sample distutils extension command."""
@@ -97,26 +101,26 @@ class TestDistributionBehavior(
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'):
@@ -157,12 +161,14 @@ class TestDistributionBehavior(
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"]
@@ -240,30 +246,15 @@ class TestDistributionBehavior(
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)
@@ -271,7 +262,7 @@ class TestDistributionBehavior(
@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)
@@ -456,41 +447,20 @@ class MetadataTestCase(support.TempdirManager):
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)]
@@ -498,9 +468,10 @@ class MetadataTestCase(support.TempdirManager):
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
diff --git a/setuptools/_distutils/tests/test_util.py b/setuptools/_distutils/tests/test_util.py
index 605b0d40..070a2770 100644
--- a/setuptools/_distutils/tests/test_util.py
+++ b/setuptools/_distutils/tests/test_util.py
@@ -136,17 +136,16 @@ class TestUtil:
# 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
@@ -159,7 +158,7 @@ class TestUtil:
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
diff --git a/setuptools/_distutils/util.py b/setuptools/_distutils/util.py
index d95992ec..4763202b 100644
--- a/setuptools/_distutils/util.py
+++ b/setuptools/_distutils/util.py
@@ -11,6 +11,8 @@ import string
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
@@ -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,
@@ -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
@@ -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):
"""