Allow multiple setup hooks in packaging’s setup.cfg files (#12240).

Original patch by Erik Bray.
This commit is contained in:
Éric Araujo 2011-06-11 00:33:38 +02:00
parent 8474f2901b
commit 643cb7345f
5 changed files with 61 additions and 31 deletions

View File

@ -176,15 +176,19 @@ compilers
compilers =
hotcompiler.SmartCCompiler
setup_hook
defines a callable that will be called right after the
:file:`setup.cfg` file is read. The callable receives the configuration
in form of a mapping and can make some changes to it. *optional*
setup_hooks
Defines a list of callables to be called right after the :file:`setup.cfg`
file is read, before any other processing. The callables are executed in the
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::
[global]
setup_hook = package.setup.customize_dist
setup_hooks = package.setup.customize_dist
Metadata

View File

@ -61,17 +61,15 @@ def get_resources_dests(resources_root, rules):
class Config:
"""Reads configuration files and work with the Distribution instance
"""
"""Class used to work with configuration files"""
def __init__(self, dist):
self.dist = dist
self.setup_hook = None
self.setup_hooks = []
def run_hook(self, config):
if self.setup_hook is None:
return
# the hook gets only the config
self.setup_hook(config)
def run_hooks(self, config):
"""Run setup hooks in the order defined in the spec."""
for hook in self.setup_hooks:
hook(config)
def find_config_files(self):
"""Find as many configuration files as should be processed for this
@ -131,17 +129,20 @@ class Config:
for section in parser.sections():
content[section] = dict(parser.items(section))
# global:setup_hook is called *first*
# global setup hooks are called first
if 'global' in content:
if 'setup_hook' in content['global']:
setup_hook = content['global']['setup_hook']
try:
self.setup_hook = resolve_name(setup_hook)
except ImportError as e:
logger.warning('could not import setup_hook: %s',
e.args[0])
else:
self.run_hook(content)
if 'setup_hooks' in content['global']:
setup_hooks = split_multiline(content['global']['setup_hooks'])
for line in setup_hooks:
try:
hook = resolve_name(line)
except ImportError as e:
logger.warning('cannot find setup hook: %s', e.args[0])
else:
self.setup_hooks.append(hook)
self.run_hooks(content)
metadata = self.dist.metadata

View File

@ -90,7 +90,7 @@ commands =
compilers =
packaging.tests.test_config.DCompiler
setup_hook = %(setup-hook)s
setup_hooks = %(setup-hooks)s
@ -135,8 +135,16 @@ class DCompiler:
pass
def hook(content):
content['metadata']['version'] += '.dev1'
def version_hook(config):
config['metadata']['version'] += '.dev1'
def first_hook(config):
config['files']['modules'] += '\n first'
def third_hook(config):
config['files']['modules'] += '\n third'
class FooBarBazTest:
@ -186,7 +194,7 @@ class ConfigTestCase(support.TempdirManager,
def write_setup(self, kwargs=None):
opts = {'description-file': 'README', 'extra-files': '',
'setup-hook': 'packaging.tests.test_config.hook'}
'setup-hooks': 'packaging.tests.test_config.version_hook'}
if kwargs:
opts.update(kwargs)
self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8')
@ -318,13 +326,27 @@ class ConfigTestCase(support.TempdirManager,
self.assertEqual(ext.extra_compile_args, cargs)
self.assertEqual(ext.language, 'cxx')
def test_missing_setuphook_warns(self):
self.write_setup({'setup-hook': 'this.does._not.exist'})
def test_missing_setup_hook_warns(self):
self.write_setup({'setup-hooks': 'this.does._not.exist'})
self.write_file('README', 'yeah')
dist = self.get_dist()
logs = self.get_logs(logging.WARNING)
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):
self.write_setup({'description-file': 'README README2'})

View File

@ -495,7 +495,7 @@ class UtilTestCase(support.EnvironRestorer,
def test_cfg_to_args(self):
opts = {'description-file': 'README', 'extra-files': '',
'setup-hook': 'packaging.tests.test_config.hook'}
'setup-hooks': 'packaging.tests.test_config.version_hook'}
self.write_file('setup.cfg', SETUP_CFG % opts)
self.write_file('README', 'loooong description')

View File

@ -187,6 +187,9 @@ Core and Builtins
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.