mirror of
https://github.com/python/cpython.git
synced 2025-09-27 18:59:43 +00:00
Branch merge
This commit is contained in:
commit
bc18532eee
8 changed files with 156 additions and 77 deletions
|
@ -83,7 +83,7 @@ The class can be used to simulate nested scopes and is useful in templating.
|
||||||
creating subcontexts that can be updated without altering values in any
|
creating subcontexts that can be updated without altering values in any
|
||||||
of the parent mappings.
|
of the parent mappings.
|
||||||
|
|
||||||
.. attribute:: parents()
|
.. method:: parents()
|
||||||
|
|
||||||
Returns a new :class:`ChainMap` containing all of the maps in the current
|
Returns a new :class:`ChainMap` containing all of the maps in the current
|
||||||
instance except the first one. This is useful for skipping the first map
|
instance except the first one. This is useful for skipping the first map
|
||||||
|
|
|
@ -176,15 +176,19 @@ compilers
|
||||||
compilers =
|
compilers =
|
||||||
hotcompiler.SmartCCompiler
|
hotcompiler.SmartCCompiler
|
||||||
|
|
||||||
setup_hook
|
setup_hooks
|
||||||
defines a callable that will be called right after the
|
Defines a list of callables to be called right after the :file:`setup.cfg`
|
||||||
:file:`setup.cfg` file is read. The callable receives the configuration
|
file is read, before any other processing. The callables are executed in the
|
||||||
in form of a mapping and can make some changes to it. *optional*
|
order they're found in the file; if one of them cannot be found, tools should
|
||||||
|
not stop, but for example produce a warning and continue with the next line.
|
||||||
|
Each callable receives the configuration as a dictionary (keys are
|
||||||
|
:file:`setup.cfg` sections, values are dictionaries of fields) and can make
|
||||||
|
any changes to it. *optional*, *multi*
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
[global]
|
[global]
|
||||||
setup_hook = package.setup.customize_dist
|
setup_hooks = package.setup.customize_dist
|
||||||
|
|
||||||
|
|
||||||
Metadata
|
Metadata
|
||||||
|
@ -285,6 +289,7 @@ One extra field not present in PEP 345 is supported:
|
||||||
|
|
||||||
description-file
|
description-file
|
||||||
Path to a text file that will be used to fill the ``description`` field.
|
Path to a text file that will be used to fill the ``description`` field.
|
||||||
|
Multiple values are accepted; they must be separated by whitespace.
|
||||||
``description-file`` and ``description`` are mutually exclusive. *optional*
|
``description-file`` and ``description`` are mutually exclusive. *optional*
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@ from configparser import RawConfigParser
|
||||||
from packaging import logger
|
from packaging import logger
|
||||||
from packaging.errors import PackagingOptionError
|
from packaging.errors import PackagingOptionError
|
||||||
from packaging.compiler.extension import Extension
|
from packaging.compiler.extension import Extension
|
||||||
from packaging.util import check_environ, iglob, resolve_name, strtobool
|
from packaging.util import (check_environ, iglob, resolve_name, strtobool,
|
||||||
|
split_multiline)
|
||||||
from packaging.compiler import set_compiler
|
from packaging.compiler import set_compiler
|
||||||
from packaging.command import set_command
|
from packaging.command import set_command
|
||||||
from packaging.markers import interpret
|
from packaging.markers import interpret
|
||||||
|
@ -60,17 +61,15 @@ def get_resources_dests(resources_root, rules):
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
"""Reads configuration files and work with the Distribution instance
|
"""Class used to work with configuration files"""
|
||||||
"""
|
|
||||||
def __init__(self, dist):
|
def __init__(self, dist):
|
||||||
self.dist = dist
|
self.dist = dist
|
||||||
self.setup_hook = None
|
self.setup_hooks = []
|
||||||
|
|
||||||
def run_hook(self, config):
|
def run_hooks(self, config):
|
||||||
if self.setup_hook is None:
|
"""Run setup hooks in the order defined in the spec."""
|
||||||
return
|
for hook in self.setup_hooks:
|
||||||
# the hook gets only the config
|
hook(config)
|
||||||
self.setup_hook(config)
|
|
||||||
|
|
||||||
def find_config_files(self):
|
def find_config_files(self):
|
||||||
"""Find as many configuration files as should be processed for this
|
"""Find as many configuration files as should be processed for this
|
||||||
|
@ -124,29 +123,26 @@ class Config:
|
||||||
# XXX
|
# XXX
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _multiline(self, value):
|
|
||||||
value = [v for v in
|
|
||||||
[v.strip() for v in value.split('\n')]
|
|
||||||
if v != '']
|
|
||||||
return value
|
|
||||||
|
|
||||||
def _read_setup_cfg(self, parser, cfg_filename):
|
def _read_setup_cfg(self, parser, cfg_filename):
|
||||||
cfg_directory = os.path.dirname(os.path.abspath(cfg_filename))
|
cfg_directory = os.path.dirname(os.path.abspath(cfg_filename))
|
||||||
content = {}
|
content = {}
|
||||||
for section in parser.sections():
|
for section in parser.sections():
|
||||||
content[section] = dict(parser.items(section))
|
content[section] = dict(parser.items(section))
|
||||||
|
|
||||||
# global:setup_hook is called *first*
|
# global setup hooks are called first
|
||||||
if 'global' in content:
|
if 'global' in content:
|
||||||
if 'setup_hook' in content['global']:
|
if 'setup_hooks' in content['global']:
|
||||||
setup_hook = content['global']['setup_hook']
|
setup_hooks = split_multiline(content['global']['setup_hooks'])
|
||||||
try:
|
|
||||||
self.setup_hook = resolve_name(setup_hook)
|
for line in setup_hooks:
|
||||||
except ImportError as e:
|
try:
|
||||||
logger.warning('could not import setup_hook: %s',
|
hook = resolve_name(line)
|
||||||
e.args[0])
|
except ImportError as e:
|
||||||
else:
|
logger.warning('cannot find setup hook: %s', e.args[0])
|
||||||
self.run_hook(content)
|
else:
|
||||||
|
self.setup_hooks.append(hook)
|
||||||
|
|
||||||
|
self.run_hooks(content)
|
||||||
|
|
||||||
metadata = self.dist.metadata
|
metadata = self.dist.metadata
|
||||||
|
|
||||||
|
@ -155,7 +151,7 @@ class Config:
|
||||||
for key, value in content['metadata'].items():
|
for key, value in content['metadata'].items():
|
||||||
key = key.replace('_', '-')
|
key = key.replace('_', '-')
|
||||||
if metadata.is_multi_field(key):
|
if metadata.is_multi_field(key):
|
||||||
value = self._multiline(value)
|
value = split_multiline(value)
|
||||||
|
|
||||||
if key == 'project-url':
|
if key == 'project-url':
|
||||||
value = [(label.strip(), url.strip())
|
value = [(label.strip(), url.strip())
|
||||||
|
@ -168,21 +164,18 @@ class Config:
|
||||||
"mutually exclusive")
|
"mutually exclusive")
|
||||||
raise PackagingOptionError(msg)
|
raise PackagingOptionError(msg)
|
||||||
|
|
||||||
if isinstance(value, list):
|
filenames = value.split()
|
||||||
filenames = value
|
|
||||||
else:
|
|
||||||
filenames = value.split()
|
|
||||||
|
|
||||||
# concatenate each files
|
# concatenate all files
|
||||||
value = ''
|
value = []
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
# will raise if file not found
|
# will raise if file not found
|
||||||
with open(filename) as description_file:
|
with open(filename) as description_file:
|
||||||
value += description_file.read().strip() + '\n'
|
value.append(description_file.read().strip())
|
||||||
# add filename as a required file
|
# add filename as a required file
|
||||||
if filename not in metadata.requires_files:
|
if filename not in metadata.requires_files:
|
||||||
metadata.requires_files.append(filename)
|
metadata.requires_files.append(filename)
|
||||||
value = value.strip()
|
value = '\n'.join(value).strip()
|
||||||
key = 'description'
|
key = 'description'
|
||||||
|
|
||||||
if metadata.is_metadata_field(key):
|
if metadata.is_metadata_field(key):
|
||||||
|
@ -192,7 +185,7 @@ class Config:
|
||||||
files = content['files']
|
files = content['files']
|
||||||
self.dist.package_dir = files.pop('packages_root', None)
|
self.dist.package_dir = files.pop('packages_root', None)
|
||||||
|
|
||||||
files = dict((key, self._multiline(value)) for key, value in
|
files = dict((key, split_multiline(value)) for key, value in
|
||||||
files.items())
|
files.items())
|
||||||
|
|
||||||
self.dist.packages = []
|
self.dist.packages = []
|
||||||
|
@ -310,7 +303,7 @@ class Config:
|
||||||
opt = opt.replace('-', '_')
|
opt = opt.replace('-', '_')
|
||||||
|
|
||||||
if opt == 'sub_commands':
|
if opt == 'sub_commands':
|
||||||
val = self._multiline(val)
|
val = split_multiline(val)
|
||||||
if isinstance(val, str):
|
if isinstance(val, str):
|
||||||
val = [val]
|
val = [val]
|
||||||
|
|
||||||
|
@ -348,14 +341,14 @@ class Config:
|
||||||
raise PackagingOptionError(msg)
|
raise PackagingOptionError(msg)
|
||||||
|
|
||||||
def _load_compilers(self, compilers):
|
def _load_compilers(self, compilers):
|
||||||
compilers = self._multiline(compilers)
|
compilers = split_multiline(compilers)
|
||||||
if isinstance(compilers, str):
|
if isinstance(compilers, str):
|
||||||
compilers = [compilers]
|
compilers = [compilers]
|
||||||
for compiler in compilers:
|
for compiler in compilers:
|
||||||
set_compiler(compiler.strip())
|
set_compiler(compiler.strip())
|
||||||
|
|
||||||
def _load_commands(self, commands):
|
def _load_commands(self, commands):
|
||||||
commands = self._multiline(commands)
|
commands = split_multiline(commands)
|
||||||
if isinstance(commands, str):
|
if isinstance(commands, str):
|
||||||
commands = [commands]
|
commands = [commands]
|
||||||
for command in commands:
|
for command in commands:
|
||||||
|
|
|
@ -90,7 +90,7 @@ commands =
|
||||||
compilers =
|
compilers =
|
||||||
packaging.tests.test_config.DCompiler
|
packaging.tests.test_config.DCompiler
|
||||||
|
|
||||||
setup_hook = %(setup-hook)s
|
setup_hooks = %(setup-hooks)s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,8 +135,16 @@ class DCompiler:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def hook(content):
|
def version_hook(config):
|
||||||
content['metadata']['version'] += '.dev1'
|
config['metadata']['version'] += '.dev1'
|
||||||
|
|
||||||
|
|
||||||
|
def first_hook(config):
|
||||||
|
config['files']['modules'] += '\n first'
|
||||||
|
|
||||||
|
|
||||||
|
def third_hook(config):
|
||||||
|
config['files']['modules'] += '\n third'
|
||||||
|
|
||||||
|
|
||||||
class FooBarBazTest:
|
class FooBarBazTest:
|
||||||
|
@ -186,7 +194,7 @@ class ConfigTestCase(support.TempdirManager,
|
||||||
|
|
||||||
def write_setup(self, kwargs=None):
|
def write_setup(self, kwargs=None):
|
||||||
opts = {'description-file': 'README', 'extra-files': '',
|
opts = {'description-file': 'README', 'extra-files': '',
|
||||||
'setup-hook': 'packaging.tests.test_config.hook'}
|
'setup-hooks': 'packaging.tests.test_config.version_hook'}
|
||||||
if kwargs:
|
if kwargs:
|
||||||
opts.update(kwargs)
|
opts.update(kwargs)
|
||||||
self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8')
|
self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8')
|
||||||
|
@ -318,16 +326,30 @@ class ConfigTestCase(support.TempdirManager,
|
||||||
self.assertEqual(ext.extra_compile_args, cargs)
|
self.assertEqual(ext.extra_compile_args, cargs)
|
||||||
self.assertEqual(ext.language, 'cxx')
|
self.assertEqual(ext.language, 'cxx')
|
||||||
|
|
||||||
def test_missing_setuphook_warns(self):
|
def test_missing_setup_hook_warns(self):
|
||||||
self.write_setup({'setup-hook': 'this.does._not.exist'})
|
self.write_setup({'setup-hooks': 'this.does._not.exist'})
|
||||||
self.write_file('README', 'yeah')
|
self.write_file('README', 'yeah')
|
||||||
dist = self.get_dist()
|
dist = self.get_dist()
|
||||||
logs = self.get_logs(logging.WARNING)
|
logs = self.get_logs(logging.WARNING)
|
||||||
self.assertEqual(1, len(logs))
|
self.assertEqual(1, len(logs))
|
||||||
self.assertIn('could not import setup_hook', logs[0])
|
self.assertIn('cannot find setup hook', logs[0])
|
||||||
|
|
||||||
|
def test_multiple_setup_hooks(self):
|
||||||
|
self.write_setup({
|
||||||
|
'setup-hooks': '\n packaging.tests.test_config.first_hook'
|
||||||
|
'\n packaging.tests.test_config.missing_hook'
|
||||||
|
'\n packaging.tests.test_config.third_hook'
|
||||||
|
})
|
||||||
|
self.write_file('README', 'yeah')
|
||||||
|
dist = self.get_dist()
|
||||||
|
|
||||||
|
self.assertEqual(['haven', 'first', 'third'], dist.py_modules)
|
||||||
|
logs = self.get_logs(logging.WARNING)
|
||||||
|
self.assertEqual(1, len(logs))
|
||||||
|
self.assertIn('cannot find setup hook', logs[0])
|
||||||
|
|
||||||
def test_metadata_requires_description_files_missing(self):
|
def test_metadata_requires_description_files_missing(self):
|
||||||
self.write_setup({'description-file': 'README\n README2'})
|
self.write_setup({'description-file': 'README README2'})
|
||||||
self.write_file('README', 'yeah')
|
self.write_file('README', 'yeah')
|
||||||
self.write_file('README2', 'yeah')
|
self.write_file('README2', 'yeah')
|
||||||
os.mkdir('src')
|
os.mkdir('src')
|
||||||
|
|
|
@ -8,16 +8,18 @@ import subprocess
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
from packaging.tests import support, unittest
|
from packaging.tests import support, unittest
|
||||||
|
from packaging.tests.test_config import SETUP_CFG
|
||||||
from packaging.errors import (
|
from packaging.errors import (
|
||||||
PackagingPlatformError, PackagingByteCompileError, PackagingFileError,
|
PackagingPlatformError, PackagingByteCompileError, PackagingFileError,
|
||||||
PackagingExecError, InstallationException)
|
PackagingExecError, InstallationException)
|
||||||
from packaging import util
|
from packaging import util
|
||||||
|
from packaging.dist import Distribution
|
||||||
from packaging.util import (
|
from packaging.util import (
|
||||||
convert_path, change_root, split_quoted, strtobool, rfc822_escape,
|
convert_path, change_root, split_quoted, strtobool, rfc822_escape,
|
||||||
get_compiler_versions, _MAC_OS_X_LD_VERSION, byte_compile, find_packages,
|
get_compiler_versions, _MAC_OS_X_LD_VERSION, byte_compile, find_packages,
|
||||||
spawn, get_pypirc_path, generate_pypirc, read_pypirc, resolve_name, iglob,
|
spawn, get_pypirc_path, generate_pypirc, read_pypirc, resolve_name, iglob,
|
||||||
RICH_GLOB, egginfo_to_distinfo, is_setuptools, is_distutils, is_packaging,
|
RICH_GLOB, egginfo_to_distinfo, is_setuptools, is_distutils, is_packaging,
|
||||||
get_install_method)
|
get_install_method, cfg_to_args)
|
||||||
|
|
||||||
|
|
||||||
PYPIRC = """\
|
PYPIRC = """\
|
||||||
|
@ -88,13 +90,15 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
support.LoggingCatcher,
|
support.LoggingCatcher,
|
||||||
unittest.TestCase):
|
unittest.TestCase):
|
||||||
|
|
||||||
restore_environ = ['HOME']
|
restore_environ = ['HOME', 'PLAT']
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(UtilTestCase, self).setUp()
|
super(UtilTestCase, self).setUp()
|
||||||
self.tmp_dir = self.mkdtemp()
|
self.addCleanup(os.chdir, os.getcwd())
|
||||||
self.rc = os.path.join(self.tmp_dir, '.pypirc')
|
tempdir = self.mkdtemp()
|
||||||
os.environ['HOME'] = self.tmp_dir
|
self.rc = os.path.join(tempdir, '.pypirc')
|
||||||
|
os.environ['HOME'] = tempdir
|
||||||
|
os.chdir(tempdir)
|
||||||
# saving the environment
|
# saving the environment
|
||||||
self.name = os.name
|
self.name = os.name
|
||||||
self.platform = sys.platform
|
self.platform = sys.platform
|
||||||
|
@ -103,7 +107,6 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
self.join = os.path.join
|
self.join = os.path.join
|
||||||
self.isabs = os.path.isabs
|
self.isabs = os.path.isabs
|
||||||
self.splitdrive = os.path.splitdrive
|
self.splitdrive = os.path.splitdrive
|
||||||
#self._config_vars = copy(sysconfig._config_vars)
|
|
||||||
|
|
||||||
# patching os.uname
|
# patching os.uname
|
||||||
if hasattr(os, 'uname'):
|
if hasattr(os, 'uname'):
|
||||||
|
@ -137,7 +140,6 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
os.uname = self.uname
|
os.uname = self.uname
|
||||||
else:
|
else:
|
||||||
del os.uname
|
del os.uname
|
||||||
#sysconfig._config_vars = copy(self._config_vars)
|
|
||||||
util.find_executable = self.old_find_executable
|
util.find_executable = self.old_find_executable
|
||||||
subprocess.Popen = self.old_popen
|
subprocess.Popen = self.old_popen
|
||||||
sys.old_stdout = self.old_stdout
|
sys.old_stdout = self.old_stdout
|
||||||
|
@ -491,6 +493,38 @@ class UtilTestCase(support.EnvironRestorer,
|
||||||
content = f.read()
|
content = f.read()
|
||||||
self.assertEqual(content, WANTED)
|
self.assertEqual(content, WANTED)
|
||||||
|
|
||||||
|
def test_cfg_to_args(self):
|
||||||
|
opts = {'description-file': 'README', 'extra-files': '',
|
||||||
|
'setup-hooks': 'packaging.tests.test_config.version_hook'}
|
||||||
|
self.write_file('setup.cfg', SETUP_CFG % opts)
|
||||||
|
self.write_file('README', 'loooong description')
|
||||||
|
|
||||||
|
args = cfg_to_args()
|
||||||
|
# use Distribution to get the contents of the setup.cfg file
|
||||||
|
dist = Distribution()
|
||||||
|
dist.parse_config_files()
|
||||||
|
metadata = dist.metadata
|
||||||
|
|
||||||
|
self.assertEqual(args['name'], metadata['Name'])
|
||||||
|
# + .dev1 because the test SETUP_CFG also tests a hook function in
|
||||||
|
# test_config.py for appending to the version string
|
||||||
|
self.assertEqual(args['version'] + '.dev1', metadata['Version'])
|
||||||
|
self.assertEqual(args['author'], metadata['Author'])
|
||||||
|
self.assertEqual(args['author_email'], metadata['Author-Email'])
|
||||||
|
self.assertEqual(args['maintainer'], metadata['Maintainer'])
|
||||||
|
self.assertEqual(args['maintainer_email'],
|
||||||
|
metadata['Maintainer-Email'])
|
||||||
|
self.assertEqual(args['description'], metadata['Summary'])
|
||||||
|
self.assertEqual(args['long_description'], metadata['Description'])
|
||||||
|
self.assertEqual(args['classifiers'], metadata['Classifier'])
|
||||||
|
self.assertEqual(args['requires'], metadata['Requires-Dist'])
|
||||||
|
self.assertEqual(args['provides'], metadata['Provides-Dist'])
|
||||||
|
|
||||||
|
self.assertEqual(args['package_dir'].get(''), dist.package_dir)
|
||||||
|
self.assertEqual(args['packages'], dist.packages)
|
||||||
|
self.assertEqual(args['scripts'], dist.scripts)
|
||||||
|
self.assertEqual(args['py_modules'], dist.py_modules)
|
||||||
|
|
||||||
|
|
||||||
class GlobTestCaseBase(support.TempdirManager,
|
class GlobTestCaseBase(support.TempdirManager,
|
||||||
support.LoggingCatcher,
|
support.LoggingCatcher,
|
||||||
|
|
|
@ -250,6 +250,14 @@ def split_quoted(s):
|
||||||
return words
|
return words
|
||||||
|
|
||||||
|
|
||||||
|
def split_multiline(value):
|
||||||
|
"""Split a multiline string into a list, excluding blank lines."""
|
||||||
|
|
||||||
|
return [element for element in
|
||||||
|
(line.strip() for line in value.split('\n'))
|
||||||
|
if element]
|
||||||
|
|
||||||
|
|
||||||
def execute(func, args, msg=None, verbose=0, dry_run=False):
|
def execute(func, args, msg=None, verbose=0, dry_run=False):
|
||||||
"""Perform some action that affects the outside world.
|
"""Perform some action that affects the outside world.
|
||||||
|
|
||||||
|
@ -542,18 +550,15 @@ def write_file(filename, contents):
|
||||||
|
|
||||||
|
|
||||||
def _is_package(path):
|
def _is_package(path):
|
||||||
if not os.path.isdir(path):
|
return os.path.isdir(path) and os.path.isfile(
|
||||||
return False
|
os.path.join(path, '__init__.py'))
|
||||||
return os.path.isfile(os.path.join(path, '__init__.py'))
|
|
||||||
|
|
||||||
|
|
||||||
# Code taken from the pip project
|
# Code taken from the pip project
|
||||||
def _is_archive_file(name):
|
def _is_archive_file(name):
|
||||||
archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar')
|
archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar')
|
||||||
ext = splitext(name)[1].lower()
|
ext = splitext(name)[1].lower()
|
||||||
if ext in archives:
|
return ext in archives
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def _under(path, root):
|
def _under(path, root):
|
||||||
|
@ -772,12 +777,13 @@ def spawn(cmd, search_path=True, verbose=0, dry_run=False, env=None):
|
||||||
Raise PackagingExecError if running the program fails in any way; just
|
Raise PackagingExecError if running the program fails in any way; just
|
||||||
return on success.
|
return on success.
|
||||||
"""
|
"""
|
||||||
logger.info(' '.join(cmd))
|
logger.debug('spawn: running %r', cmd)
|
||||||
if dry_run:
|
if dry_run:
|
||||||
|
logging.debug('dry run, no process actually spawned')
|
||||||
return
|
return
|
||||||
exit_status = subprocess.call(cmd, env=env)
|
exit_status = subprocess.call(cmd, env=env)
|
||||||
if exit_status != 0:
|
if exit_status != 0:
|
||||||
msg = "command '%s' failed with exit status %d"
|
msg = "command %r failed with exit status %d"
|
||||||
raise PackagingExecError(msg % (cmd, exit_status))
|
raise PackagingExecError(msg % (cmd, exit_status))
|
||||||
|
|
||||||
|
|
||||||
|
@ -1010,16 +1016,20 @@ def cfg_to_args(path='setup.cfg'):
|
||||||
"requires": ("metadata", "requires_dist"),
|
"requires": ("metadata", "requires_dist"),
|
||||||
"provides": ("metadata", "provides_dist"), # **
|
"provides": ("metadata", "provides_dist"), # **
|
||||||
"obsoletes": ("metadata", "obsoletes_dist"), # **
|
"obsoletes": ("metadata", "obsoletes_dist"), # **
|
||||||
|
"package_dir": ("files", 'packages_root'),
|
||||||
"packages": ("files",),
|
"packages": ("files",),
|
||||||
"scripts": ("files",),
|
"scripts": ("files",),
|
||||||
"py_modules": ("files", "modules"), # **
|
"py_modules": ("files", "modules"), # **
|
||||||
}
|
}
|
||||||
|
|
||||||
MULTI_FIELDS = ("classifiers",
|
MULTI_FIELDS = ("classifiers",
|
||||||
"requires",
|
|
||||||
"platforms",
|
"platforms",
|
||||||
|
"requires",
|
||||||
|
"provides",
|
||||||
|
"obsoletes",
|
||||||
"packages",
|
"packages",
|
||||||
"scripts")
|
"scripts",
|
||||||
|
"py_modules")
|
||||||
|
|
||||||
def has_get_option(config, section, option):
|
def has_get_option(config, section, option):
|
||||||
if config.has_option(section, option):
|
if config.has_option(section, option):
|
||||||
|
@ -1031,9 +1041,9 @@ def cfg_to_args(path='setup.cfg'):
|
||||||
|
|
||||||
# The real code starts here
|
# The real code starts here
|
||||||
config = RawConfigParser()
|
config = RawConfigParser()
|
||||||
if not os.path.exists(file):
|
if not os.path.exists(path):
|
||||||
raise PackagingFileError("file '%s' does not exist" %
|
raise PackagingFileError("file '%s' does not exist" %
|
||||||
os.path.abspath(file))
|
os.path.abspath(path))
|
||||||
config.read(path)
|
config.read(path)
|
||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
@ -1050,17 +1060,24 @@ def cfg_to_args(path='setup.cfg'):
|
||||||
in_cfg_value = has_get_option(config, section, option)
|
in_cfg_value = has_get_option(config, section, option)
|
||||||
if not in_cfg_value:
|
if not in_cfg_value:
|
||||||
# There is no such option in the setup.cfg
|
# There is no such option in the setup.cfg
|
||||||
if arg == "long_description":
|
if arg == 'long_description':
|
||||||
filename = has_get_option(config, section, "description_file")
|
filenames = has_get_option(config, section, 'description-file')
|
||||||
if filename:
|
if filenames:
|
||||||
with open(filename) as fp:
|
filenames = split_multiline(filenames)
|
||||||
in_cfg_value = fp.read()
|
in_cfg_value = []
|
||||||
|
for filename in filenames:
|
||||||
|
with open(filename) as fp:
|
||||||
|
in_cfg_value.append(fp.read())
|
||||||
|
in_cfg_value = '\n\n'.join(in_cfg_value)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if arg == 'package_dir' and in_cfg_value:
|
||||||
|
in_cfg_value = {'': in_cfg_value}
|
||||||
|
|
||||||
if arg in MULTI_FIELDS:
|
if arg in MULTI_FIELDS:
|
||||||
# support multiline options
|
# support multiline options
|
||||||
in_cfg_value = in_cfg_value.strip().split('\n')
|
in_cfg_value = split_multiline(in_cfg_value)
|
||||||
|
|
||||||
kwargs[arg] = in_cfg_value
|
kwargs[arg] = in_cfg_value
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,7 @@ Monty Brandenberg
|
||||||
Georg Brandl
|
Georg Brandl
|
||||||
Christopher Brannon
|
Christopher Brannon
|
||||||
Terrence Brannon
|
Terrence Brannon
|
||||||
|
Erik Bray
|
||||||
Brian Brazil
|
Brian Brazil
|
||||||
Dave Brennan
|
Dave Brennan
|
||||||
Tom Bridgman
|
Tom Bridgman
|
||||||
|
|
|
@ -187,6 +187,13 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #12240: Allow multiple setup hooks in packaging's setup.cfg files.
|
||||||
|
Original patch by Erik Bray.
|
||||||
|
|
||||||
|
- Issue #11595: Fix assorted bugs in packaging.util.cfg_to_args, a
|
||||||
|
compatibility helper for the distutils-packaging transition. Original patch
|
||||||
|
by Erik Bray.
|
||||||
|
|
||||||
- Issue #12287: In ossaudiodev, check that the device isn't closed in several
|
- Issue #12287: In ossaudiodev, check that the device isn't closed in several
|
||||||
methods.
|
methods.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue