summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉric Araujo <merwok@netwok.org>2011-06-09 14:07:46 +0200
committerÉric Araujo <merwok@netwok.org>2011-06-09 14:07:46 +0200
commite00a6703e8d13ae4ab30466998ef62098868f98c (patch)
treea4d6fcb7fe4b323727b491c7a7b042fc0f14a657
parent9a82eaade3cbfba9895b6121daf8ddb65b5aaa4d (diff)
parente6792c1e771fab4ed025beeb8f71fb2d5c7d53e8 (diff)
downloadcpython-git-e00a6703e8d13ae4ab30466998ef62098868f98c.tar.gz
Branch merge
-rw-r--r--Doc/library/packaging.compiler.rst6
-rw-r--r--Doc/packaging/setupcfg.rst68
-rw-r--r--Lib/packaging/create.py8
-rw-r--r--Lib/packaging/database.py6
-rw-r--r--Lib/packaging/depgraph.py29
-rw-r--r--Lib/packaging/dist.py8
-rw-r--r--Lib/packaging/pypi/dist.py6
-rw-r--r--Lib/packaging/pypi/simple.py7
-rw-r--r--Lib/packaging/run.py21
-rw-r--r--Lib/packaging/tests/test_command_bdist_dumb.py1
-rw-r--r--Lib/packaging/tests/test_command_build_py.py4
-rw-r--r--Lib/packaging/tests/test_command_install_dist.py2
-rw-r--r--Lib/packaging/tests/test_command_install_lib.py2
-rw-r--r--Lib/packaging/tests/test_command_sdist.py10
-rw-r--r--Lib/packaging/tests/test_config.py4
-rw-r--r--Lib/packaging/util.py2
-rw-r--r--setup.py7
17 files changed, 108 insertions, 83 deletions
diff --git a/Doc/library/packaging.compiler.rst b/Doc/library/packaging.compiler.rst
index dac62632a4..cf88685144 100644
--- a/Doc/library/packaging.compiler.rst
+++ b/Doc/library/packaging.compiler.rst
@@ -569,10 +569,10 @@ extension modules.
.. class:: Extension
The Extension class describes a single C or C++ extension module. It accepts
- the following keyword arguments in its constructor
+ the following keyword arguments in its constructor:
+------------------------+--------------------------------+---------------------------+
- | argument name | value | type |
+ | argument name | value | type [#]_ |
+========================+================================+===========================+
| *name* | the full name of the | string |
| | extension, including any | |
@@ -670,3 +670,5 @@ extension modules.
| | from the source extensions if | |
| | not provided. | |
+------------------------+--------------------------------+---------------------------+
+
+.. [#] For values documented as lists, the given type is the type of each element.
diff --git a/Doc/packaging/setupcfg.rst b/Doc/packaging/setupcfg.rst
index d3fc07a944..aa8216fdf1 100644
--- a/Doc/packaging/setupcfg.rst
+++ b/Doc/packaging/setupcfg.rst
@@ -141,13 +141,16 @@ files
Modules, scripts, data, documentation and other files to include in the
distribution.
+extension sections
+ Options used to build extension modules.
+
command sections
Options given for specific commands, identical to those that can be given
on the command line.
Global options
-==============
+--------------
Contains global options for Packaging. This section is shared with Distutils.
@@ -185,7 +188,7 @@ setup_hook
Metadata
-========
+--------
The metadata section contains the metadata for the project as described in
:PEP:`345`. Field names are case-insensitive.
@@ -308,7 +311,7 @@ from the fields present in the file.
Files
-=====
+-----
This section describes the files included in the project.
@@ -352,7 +355,7 @@ Example::
Resources
----------
+^^^^^^^^^
This section describes the files used by the project which must not be installed
in the same place that python modules or libraries, they are called
@@ -448,10 +451,10 @@ Where {datafir} category will be platform-dependent.
More control on source part
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+"""""""""""""""""""""""""""
Glob syntax
-"""""""""""
+'''''''''''
When you declare source file, you can use a glob-like syntax to match multiples file, for example::
@@ -469,7 +472,7 @@ Glob tokens are:
.. TODO Add examples
Order of declaration
-""""""""""""""""""""
+''''''''''''''''''''
The order of declaration is important if one file match multiple rules. The last
rules matched by file is used, this is useful if you have this source tree::
@@ -492,7 +495,7 @@ one by one, you can declare them in this way::
doc/README = {help}
Exclude
-"""""""
+'''''''
You can exclude some files of resources declaration by giving no destination, it
can be useful if you have a non-resources file in the same directory of
@@ -513,12 +516,12 @@ Your **files** section will be::
doc/RELEASES =
More control on destination part
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+""""""""""""""""""""""""""""""""
.. _setupcfg-resources-base-prefix:
Defining a base prefix
-""""""""""""""""""""""
+''''''''''''''''''''''
When you define your resources, you can have more control of how the final path
is computed.
@@ -577,7 +580,7 @@ path will be::
Overwriting paths for categories
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+""""""""""""""""""""""""""""""""
This part is intended for system administrators or downstream OS packagers.
@@ -614,18 +617,18 @@ The platform-dependent categories are:
Defining extra categories
-^^^^^^^^^^^^^^^^^^^^^^^^^
+"""""""""""""""""""""""""
.. TODO
Examples
-^^^^^^^^
+""""""""
These examples are incremental but work unitarily.
Resources in root dir
-"""""""""""""""""""""
+'''''''''''''''''''''
Source tree::
@@ -647,7 +650,7 @@ So babar.sh and launch.sh will be placed in {scripts} directory.
Now let's move all the scripts into a scripts directory.
Resources in sub-directory
-""""""""""""""""""""""""""
+''''''''''''''''''''''''''
Source tree::
@@ -673,7 +676,7 @@ scripts into {scripts} instead of {scripts}/scripts.
Now let's add some docs.
Resources in multiple sub-directories
-"""""""""""""""""""""""""""""""""""""
+'''''''''''''''''''''''''''''''''''''
Source tree::
@@ -706,7 +709,7 @@ file is used.
Now let's add some scripts for windows users.
Complete example
-""""""""""""""""
+''''''''''''''''
Source tree::
@@ -736,8 +739,37 @@ We use brace expansion syntax to place all the shell and batch scripts into
{scripts} category.
+Extension sections
+------------------
+
+If a project includes extension modules written in C or C++, each one of them
+needs to have its options defined in a dedicated section. Here's an example::
+
+ [files]
+ packages = coconut
+
+ [extension=_fastcoconut]
+ name = coconut._fastcoconut
+ language = cxx
+ sources = cxx_src/cononut_utils.cxx
+ cxx_src/python_module.cxx
+ include_dirs = /usr/include/gecode
+ /usr/include/blitz
+ extra_compile_args =
+ -fPIC -O2
+ -DGECODE_VERSION=$(./gecode_version) -- sys.platform != 'win32'
+ /DGECODE_VERSION='win32' -- sys.platform == 'win32'
+
+The section name must start with ``extension=``; the righ-hand part is currently
+discarded. Valid fields and their values are listed in the documentation of the
+:class:`packaging.compiler.extension.Extension` class; values documented as
+Python lists translate to multi-line values in the configuration file. In
+addition, multi-line values accept environment markers on each line, after a
+``--``.
+
+
Command sections
-================
+----------------
To pass options to commands without having to type them on the command line
for each invocation, you can write them in the :file:`setup.cfg` file, in a
diff --git a/Lib/packaging/create.py b/Lib/packaging/create.py
index c18d42fb02..917b6cf849 100644
--- a/Lib/packaging/create.py
+++ b/Lib/packaging/create.py
@@ -175,11 +175,11 @@ def convert_yn_to_bool(yn, yes=True, no=False):
def _build_classifiers_dict(classifiers):
d = {}
for key in classifiers:
- subDict = d
+ subdict = d
for subkey in key.split(' :: '):
- if not subkey in subDict:
- subDict[subkey] = {}
- subDict = subDict[subkey]
+ if subkey not in subdict:
+ subdict[subkey] = {}
+ subdict = subdict[subkey]
return d
CLASSIFIERS = _build_classifiers_dict(_CLASSIFIERS_LIST)
diff --git a/Lib/packaging/database.py b/Lib/packaging/database.py
index 22d4b138ed..e3c57bacab 100644
--- a/Lib/packaging/database.py
+++ b/Lib/packaging/database.py
@@ -104,12 +104,12 @@ def _generate_cache(use_egg_info=False, paths=sys.path):
for dist in _yield_distributions(gen_dist, gen_egg, paths):
if isinstance(dist, Distribution):
_cache_path[dist.path] = dist
- if not dist.name in _cache_name:
+ if dist.name not in _cache_name:
_cache_name[dist.name] = []
_cache_name[dist.name].append(dist)
else:
_cache_path_egg[dist.path] = dist
- if not dist.name in _cache_name_egg:
+ if dist.name not in _cache_name_egg:
_cache_name_egg[dist.name] = []
_cache_name_egg[dist.name].append(dist)
@@ -150,7 +150,7 @@ class Distribution:
self.version = self.metadata['Version']
self.path = path
- if _cache_enabled and not path in _cache_path:
+ if _cache_enabled and path not in _cache_path:
_cache_path[path] = self
def __repr__(self):
diff --git a/Lib/packaging/depgraph.py b/Lib/packaging/depgraph.py
index 48ea3d9252..b3c555a8a2 100644
--- a/Lib/packaging/depgraph.py
+++ b/Lib/packaging/depgraph.py
@@ -58,7 +58,7 @@ class DependencyGraph:
"""
self.adjacency_list[x].append((y, label))
# multiple edges are allowed, so be careful
- if not x in self.reverse_list[y]:
+ if x not in self.reverse_list[y]:
self.reverse_list[y].append(x)
def add_missing(self, distribution, requirement):
@@ -72,7 +72,7 @@ class DependencyGraph:
self.missing[distribution].append(requirement)
def _repr_dist(self, dist):
- return '%s %s' % (dist.name, dist.metadata['Version'])
+ return '%r %s' % (dist.name, dist.metadata['Version'])
def repr_node(self, dist, level=1):
"""Prints only a subgraph"""
@@ -154,10 +154,10 @@ def generate_graph(dists):
if len(comps) == 2:
version = comps[1]
if len(version) < 3 or version[0] != '(' or version[-1] != ')':
- raise PackagingError('Distribution %s has ill formed' \
- 'provides field: %s' % (dist.name, p))
+ raise PackagingError('distribution %r has ill-formed'
+ 'provides field: %r' % (dist.name, p))
version = version[1:-1] # trim off parenthesis
- if not name in provided:
+ if name not in provided:
provided[name] = []
provided[name].append((version, dist))
@@ -174,7 +174,7 @@ def generate_graph(dists):
name = predicate.name
- if not name in provided:
+ if name not in provided:
graph.add_missing(dist, req)
else:
matched = False
@@ -204,8 +204,9 @@ def dependent_dists(dists, dist):
:param dists: a list of distributions
:param dist: a distribution, member of *dists* for which we are interested
"""
- if not dist in dists:
- raise ValueError('The given distribution is not a member of the list')
+ if dist not in dists:
+ raise ValueError('given distribution %r is not a member of the list' %
+ dist.name)
graph = generate_graph(dists)
dep = [dist] # dependent distributions
@@ -215,7 +216,7 @@ def dependent_dists(dists, dist):
node = fringe.pop()
dep.append(node)
for prev in graph.reverse_list[node]:
- if not prev in dep:
+ if prev not in dep:
fringe.append(prev)
dep.pop(0) # remove dist from dep, was there to prevent infinite loops
@@ -236,17 +237,19 @@ def main():
except Exception as e:
tempout.seek(0)
tempout = tempout.read()
- print('Could not generate the graph\n%s\n%s\n' % (tempout, e))
+ print('Could not generate the graph')
+ print(tempout)
+ print(e)
sys.exit(1)
for dist, reqs in graph.missing.items():
if len(reqs) > 0:
- print("Warning: Missing dependencies for %s:" % dist.name,
+ print("Warning: Missing dependencies for %r:" % dist.name,
", ".join(reqs))
# XXX replace with argparse
if len(sys.argv) == 1:
print('Dependency graph:')
- print(' ' + repr(graph).replace('\n', '\n '))
+ print(' ', repr(graph).replace('\n', '\n '))
sys.exit(0)
elif len(sys.argv) > 1 and sys.argv[1] in ('-d', '--dot'):
if len(sys.argv) > 2:
@@ -259,7 +262,7 @@ def main():
tempout.seek(0)
tempout = tempout.read()
print(tempout)
- print('Dot file written at "%s"' % filename)
+ print('Dot file written at %r' % filename)
sys.exit(0)
else:
print('Supported option: -d [filename]')
diff --git a/Lib/packaging/dist.py b/Lib/packaging/dist.py
index 6065e78a6a..5c390ce9d1 100644
--- a/Lib/packaging/dist.py
+++ b/Lib/packaging/dist.py
@@ -509,14 +509,14 @@ Common commands: (see '--help-commands' for more)
options = self.global_options
parser.set_option_table(options)
parser.print_help(self.common_usage + "\nGlobal options:")
- print('')
+ print()
if display_options:
parser.set_option_table(self.display_options)
parser.print_help(
"Information display options (just display " +
"information, ignore any commands)")
- print('')
+ print()
for command in self.commands:
if isinstance(command, type) and issubclass(command, Command):
@@ -529,7 +529,7 @@ Common commands: (see '--help-commands' for more)
else:
parser.set_option_table(cls.user_options)
parser.print_help("Options for %r command:" % cls.__name__)
- print('')
+ print()
print(gen_usage(self.script_name))
@@ -544,7 +544,7 @@ Common commands: (see '--help-commands' for more)
# we ignore "foo bar").
if self.help_commands:
self.print_commands()
- print('')
+ print()
print(gen_usage(self.script_name))
return 1
diff --git a/Lib/packaging/pypi/dist.py b/Lib/packaging/pypi/dist.py
index db04cdaa70..d3824c22e8 100644
--- a/Lib/packaging/pypi/dist.py
+++ b/Lib/packaging/pypi/dist.py
@@ -256,7 +256,7 @@ class DistInfo(IndexReference):
hashlib.new(hashname)
except ValueError:
raise UnsupportedHashName(hashname)
- if not url in [u['url'] for u in self.urls]:
+ if url not in [u['url'] for u in self.urls]:
self.urls.append({
'url': url,
'hashname': hashname,
@@ -329,7 +329,7 @@ class DistInfo(IndexReference):
url param"""
hashname = self.url['hashname']
expected_hashval = self.url['hashval']
- if not None in (expected_hashval, hashname):
+ if None not in (expected_hashval, hashname):
with open(filename, 'rb') as f:
hashval = hashlib.new(hashname)
hashval.update(f.read())
@@ -409,7 +409,7 @@ class ReleasesList(IndexReference):
(release.name, self.name))
version = str(release.version)
- if not version in self.get_versions():
+ if version not in self.get_versions():
# append only if not already exists
self.releases.append(release)
for dist in release.dists.values():
diff --git a/Lib/packaging/pypi/simple.py b/Lib/packaging/pypi/simple.py
index c372c6fe3e..1dcb8ce43a 100644
--- a/Lib/packaging/pypi/simple.py
+++ b/Lib/packaging/pypi/simple.py
@@ -231,7 +231,8 @@ class Crawler(BaseClient):
"""
self._mirrors_used.add(self.index_url)
index_url = self._mirrors.pop()
- if not ("http://" or "https://" or "file://") in index_url:
+ # XXX use urllib.parse for a real check of missing scheme part
+ if not index_url.startswith(("http://", "https://", "file://")):
index_url = "http://%s" % index_url
if not index_url.endswith("/simple"):
@@ -282,7 +283,7 @@ class Crawler(BaseClient):
name = release.name
else:
name = release_info['name']
- if not name.lower() in self._projects:
+ if name.lower() not in self._projects:
self._projects[name.lower()] = ReleasesList(name, index=self._index)
if release:
@@ -320,7 +321,7 @@ class Crawler(BaseClient):
# it's a distribution, so create a dist object
try:
infos = get_infos_from_url(link, project_name,
- is_external=not self.index_url in url)
+ is_external=self.index_url not in url)
except CantParseArchiveName as e:
if self.verbose:
logger.warning(
diff --git a/Lib/packaging/run.py b/Lib/packaging/run.py
index c17ccfdf4b..3e720cf7e8 100644
--- a/Lib/packaging/run.py
+++ b/Lib/packaging/run.py
@@ -286,9 +286,9 @@ def _metadata(dispatcher, args, **kw):
value = metadata[key]
if isinstance(value, list):
for v in value:
- print(' ' + v)
+ print(' ', v)
else:
- print(' ' + value.replace('\n', '\n '))
+ print(' ', value.replace('\n', '\n '))
@action_help(remove_usage)
@@ -366,7 +366,7 @@ def _list(dispatcher, args, **kw):
print('%s %s at %s' % (dist.name, dist.metadata['version'], dist.path))
number += 1
- print('')
+ print()
if number == 0:
print('Nothing seems to be installed.')
else:
@@ -405,7 +405,6 @@ class Dispatcher:
self.verbose = 1
self.dry_run = False
self.help = False
- self.script_name = 'pysetup'
self.cmdclass = {}
self.commands = []
self.command_options = {}
@@ -574,17 +573,17 @@ class Dispatcher:
from packaging.command.cmd import Command
print('Usage: pysetup [options] action [action_options]')
- print('')
+ print()
if global_options_:
self.print_usage(self.parser)
- print('')
+ print()
if display_options_:
parser.set_option_table(display_options)
parser.print_help(
"Information display options (just display " +
"information, ignore any commands)")
- print('')
+ print()
for command in commands:
if isinstance(command, type) and issubclass(command, Command):
@@ -598,15 +597,15 @@ class Dispatcher:
parser.set_option_table(cls.user_options)
parser.print_help("Options for %r command:" % cls.__name__)
- print('')
+ print()
def _show_command_help(self, command):
if isinstance(command, str):
command = get_command_class(command)
desc = getattr(command, 'description', '(no description available)')
- print('Description: %s' % desc)
- print('')
+ print('Description:', desc)
+ print()
if (hasattr(command, 'help_options') and
isinstance(command.help_options, list)):
@@ -616,7 +615,7 @@ class Dispatcher:
self.parser.set_option_table(command.user_options)
self.parser.print_help("Options:")
- print('')
+ print()
def _get_command_groups(self):
"""Helper function to retrieve all the command class names divided
diff --git a/Lib/packaging/tests/test_command_bdist_dumb.py b/Lib/packaging/tests/test_command_bdist_dumb.py
index 41b0dd0dc9..b2357953a6 100644
--- a/Lib/packaging/tests/test_command_bdist_dumb.py
+++ b/Lib/packaging/tests/test_command_bdist_dumb.py
@@ -49,7 +49,6 @@ class BuildDumbTestCase(support.TempdirManager,
'py_modules': ['foo'],
'url': 'xxx', 'author': 'xxx',
'author_email': 'xxx'})
- dist.script_name = 'setup.py'
os.chdir(pkg_dir)
sys.argv[:] = ['setup.py']
diff --git a/Lib/packaging/tests/test_command_build_py.py b/Lib/packaging/tests/test_command_build_py.py
index 49069f51f0..243a863a60 100644
--- a/Lib/packaging/tests/test_command_build_py.py
+++ b/Lib/packaging/tests/test_command_build_py.py
@@ -33,9 +33,7 @@ class BuildPyTestCase(support.TempdirManager,
dist = Distribution({"packages": ["pkg"],
"package_dir": sources})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(sources, "setup.py")
dist.command_obj["build"] = support.DummyCommand(
force=False,
build_lib=destination,
@@ -89,8 +87,6 @@ class BuildPyTestCase(support.TempdirManager,
dist = Distribution({"packages": ["pkg"],
"package_dir": sources,
"package_data": {"pkg": ["doc/*"]}})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(sources, "setup.py")
dist.script_args = ["build"]
dist.parse_command_line()
diff --git a/Lib/packaging/tests/test_command_install_dist.py b/Lib/packaging/tests/test_command_install_dist.py
index 1974a2fc09..7821a3afde 100644
--- a/Lib/packaging/tests/test_command_install_dist.py
+++ b/Lib/packaging/tests/test_command_install_dist.py
@@ -30,8 +30,6 @@ class InstallTestCase(support.TempdirManager,
destination = os.path.join(builddir, "installation")
dist = Distribution({"name": "foopkg"})
- # script_name need not exist, it just need to be initialized
- dist.script_name = os.path.join(builddir, "setup.py")
dist.command_obj["build"] = support.DummyCommand(
build_base=builddir,
build_lib=os.path.join(builddir, "lib"),
diff --git a/Lib/packaging/tests/test_command_install_lib.py b/Lib/packaging/tests/test_command_install_lib.py
index 96749e3bf3..b46f3bd2bb 100644
--- a/Lib/packaging/tests/test_command_install_lib.py
+++ b/Lib/packaging/tests/test_command_install_lib.py
@@ -65,7 +65,6 @@ class InstallLibTestCase(support.TempdirManager,
self.write_file(f, '# python package')
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
cmd.distribution.packages = [pkg_dir]
- cmd.distribution.script_name = 'setup.py'
# make sure the build_lib is set the temp dir
build_dir = os.path.split(pkg_dir)[0]
@@ -86,7 +85,6 @@ class InstallLibTestCase(support.TempdirManager,
self.write_file(f, '# python package')
cmd.distribution.ext_modules = [Extension('foo', ['xxx'])]
cmd.distribution.packages = [pkg_dir]
- cmd.distribution.script_name = 'setup.py'
# get_input should return 2 elements
self.assertEqual(len(cmd.get_inputs()), 2)
diff --git a/Lib/packaging/tests/test_command_sdist.py b/Lib/packaging/tests/test_command_sdist.py
index 7be349f1ec..bcaa63087a 100644
--- a/Lib/packaging/tests/test_command_sdist.py
+++ b/Lib/packaging/tests/test_command_sdist.py
@@ -24,12 +24,6 @@ from packaging.util import find_executable
from packaging.tests import support
from shutil import get_archive_formats
-SETUP_PY = """
-from packaging.core import setup
-import somecode
-
-setup(name='fake')
-"""
MANIFEST = """\
# file GENERATED by packaging, do NOT edit
@@ -57,8 +51,6 @@ class SDistTestCase(support.TempdirManager,
restore_environ = ['HOME']
def setUp(self):
- # PyPIRCCommandTestCase creates a temp dir already
- # and put it in self.tmp_dir
super(SDistTestCase, self).setUp()
self.tmp_dir = self.mkdtemp()
os.environ['HOME'] = self.tmp_dir
@@ -69,7 +61,6 @@ class SDistTestCase(support.TempdirManager,
# a package, and a README
self.write_file((self.tmp_dir, 'README'), 'xxx')
self.write_file((self.tmp_dir, 'somecode', '__init__.py'), '#')
- self.write_file((self.tmp_dir, 'setup.py'), SETUP_PY)
os.chdir(self.tmp_dir)
def tearDown(self):
@@ -84,7 +75,6 @@ class SDistTestCase(support.TempdirManager,
'url': 'xxx', 'author': 'xxx',
'author_email': 'xxx'}
dist = Distribution(metadata)
- dist.script_name = 'setup.py'
dist.packages = ['somecode']
dist.include_package_data = True
cmd = sdist(dist)
diff --git a/Lib/packaging/tests/test_config.py b/Lib/packaging/tests/test_config.py
index a27673014a..9198ead131 100644
--- a/Lib/packaging/tests/test_config.py
+++ b/Lib/packaging/tests/test_config.py
@@ -114,7 +114,7 @@ libraries = gecodeint gecodekernel -- sys.platform != 'win32'
GecodeInt GecodeKernel -- sys.platform == 'win32'
[extension=fast_taunt]
-name = three.fast_taunt
+name = two.fast_taunt
sources = cxx_src/utils_taunt.cxx
cxx_src/python_module.cxx
include_dirs = /usr/include/gecode
@@ -305,7 +305,7 @@ class ConfigTestCase(support.TempdirManager,
self.assertEqual(ext.extra_link_args,
['`gcc -print-file-name=libgcc.a`', '-shared'])
- ext = ext_modules.get('three.fast_taunt')
+ ext = ext_modules.get('two.fast_taunt')
self.assertEqual(ext.sources,
['cxx_src/utils_taunt.cxx', 'cxx_src/python_module.cxx'])
self.assertEqual(ext.include_dirs,
diff --git a/Lib/packaging/util.py b/Lib/packaging/util.py
index d4aae418dd..812dbe3c29 100644
--- a/Lib/packaging/util.py
+++ b/Lib/packaging/util.py
@@ -1099,7 +1099,7 @@ def ask(message, options):
response = input(message)
response = response.strip().lower()
if response not in options:
- print('invalid response: %r' % response)
+ print('invalid response:', repr(response))
print('choose one of', ', '.join(repr(o) for o in options))
else:
return response
diff --git a/setup.py b/setup.py
index 39751c3b0a..2426aad100 100644
--- a/setup.py
+++ b/setup.py
@@ -1780,6 +1780,13 @@ class PyBuildInstall(install):
install.initialize_options(self)
self.warn_dir=0
+ # Customize subcommands to not install an egg-info file for Python
+ sub_commands = [('install_lib', install.has_lib),
+ ('install_headers', install.has_headers),
+ ('install_scripts', install.has_scripts),
+ ('install_data', install.has_data)]
+
+
class PyBuildInstallLib(install_lib):
# Do exactly what install_lib does but make sure correct access modes get
# set on installed directories and files. All installed files with get