Commit 56dea7f0 authored by idle sign's avatar idle sign Committed by Jason R. Coombs

`read_configuration()` now accepts `ignore_option_errors`.

parent ac999764
...@@ -2543,7 +2543,7 @@ zip_safe bool ...@@ -2543,7 +2543,7 @@ zip_safe bool
setup_requires list-semi setup_requires list-semi
install_requires list-semi install_requires list-semi
extras_require section extras_require section
entry_points file, section entry_points file:, section
use_2to3 bool use_2to3 bool
use_2to3_fixers list-comma use_2to3_fixers list-comma
use_2to3_exclude_fixers list-comma use_2to3_exclude_fixers list-comma
...@@ -2582,6 +2582,12 @@ in the first argument. To include values from other configuration files ...@@ -2582,6 +2582,12 @@ in the first argument. To include values from other configuration files
which could be in various places set `find_others` function argument which could be in various places set `find_others` function argument
to ``True``. to ``True``.
If you have only a configuration file but not the whole package you can still
try to get data out of it with the help of `ignore_option_errors` function
argument. When it is set to ``True`` all options with errors possibly produced
by directives, such as ``attr:`` and others will be silently ignored.
As a consequence the resulting dictionary will include no such options.
-------------------------------- --------------------------------
Extending and Reusing Setuptools Extending and Reusing Setuptools
......
...@@ -10,7 +10,8 @@ from setuptools.py26compat import import_module ...@@ -10,7 +10,8 @@ from setuptools.py26compat import import_module
from setuptools.extern.six import string_types from setuptools.extern.six import string_types
def read_configuration(filepath, find_others=False): def read_configuration(
filepath, find_others=False, ignore_option_errors=False):
"""Read given configuration file and returns options from it as a dict. """Read given configuration file and returns options from it as a dict.
:param str|unicode filepath: Path to configuration file :param str|unicode filepath: Path to configuration file
...@@ -19,6 +20,11 @@ def read_configuration(filepath, find_others=False): ...@@ -19,6 +20,11 @@ def read_configuration(filepath, find_others=False):
:param bool find_others: Whether to search for other configuration files :param bool find_others: Whether to search for other configuration files
which could be on in various places. which could be on in various places.
:param bool ignore_option_errors: Whether to silently ignore
options, values of which could not be resolved (e.g. due to exceptions
in directives such as file:, attr:, etc.).
If False exceptions are propagated as expected.
:rtype: dict :rtype: dict
""" """
from setuptools.dist import Distribution, _Distribution from setuptools.dist import Distribution, _Distribution
...@@ -40,7 +46,9 @@ def read_configuration(filepath, find_others=False): ...@@ -40,7 +46,9 @@ def read_configuration(filepath, find_others=False):
_Distribution.parse_config_files(dist, filenames=filenames) _Distribution.parse_config_files(dist, filenames=filenames)
handlers = parse_configuration(dist, dist.command_options) handlers = parse_configuration(
dist, dist.command_options,
ignore_option_errors=ignore_option_errors)
os.chdir(current_directory) os.chdir(current_directory)
...@@ -76,7 +84,8 @@ def configuration_to_dict(handlers): ...@@ -76,7 +84,8 @@ def configuration_to_dict(handlers):
return config_dict return config_dict
def parse_configuration(distribution, command_options): def parse_configuration(
distribution, command_options, ignore_option_errors=False):
"""Performs additional parsing of configuration options """Performs additional parsing of configuration options
for a distribution. for a distribution.
...@@ -84,12 +93,18 @@ def parse_configuration(distribution, command_options): ...@@ -84,12 +93,18 @@ def parse_configuration(distribution, command_options):
:param Distribution distribution: :param Distribution distribution:
:param dict command_options: :param dict command_options:
:param bool ignore_option_errors: Whether to silently ignore
options, values of which could not be resolved (e.g. due to exceptions
in directives such as file:, attr:, etc.).
If False exceptions are propagated as expected.
:rtype: list :rtype: list
""" """
meta = ConfigMetadataHandler(distribution.metadata, command_options) meta = ConfigMetadataHandler(
distribution.metadata, command_options, ignore_option_errors)
meta.parse() meta.parse()
options = ConfigOptionsHandler(distribution, command_options) options = ConfigOptionsHandler(
distribution, command_options, ignore_option_errors)
options.parse() options.parse()
return [meta, options] return [meta, options]
...@@ -111,7 +126,7 @@ class ConfigHandler(object): ...@@ -111,7 +126,7 @@ class ConfigHandler(object):
""" """
def __init__(self, target_obj, options): def __init__(self, target_obj, options, ignore_option_errors=False):
sections = {} sections = {}
section_prefix = self.section_prefix section_prefix = self.section_prefix
...@@ -122,6 +137,7 @@ class ConfigHandler(object): ...@@ -122,6 +137,7 @@ class ConfigHandler(object):
section_name = section_name.replace(section_prefix, '').strip('.') section_name = section_name.replace(section_prefix, '').strip('.')
sections[section_name] = section_options sections[section_name] = section_options
self.ignore_option_errors = ignore_option_errors
self.target_obj = target_obj self.target_obj = target_obj
self.sections = sections self.sections = sections
self.set_options = [] self.set_options = []
...@@ -148,9 +164,19 @@ class ConfigHandler(object): ...@@ -148,9 +164,19 @@ class ConfigHandler(object):
# Already inhabited. Skipping. # Already inhabited. Skipping.
return return
skip_option = False
parser = self.parsers.get(option_name) parser = self.parsers.get(option_name)
if parser: if parser:
value = parser(value) try:
value = parser(value)
except Exception:
skip_option = True
if not self.ignore_option_errors:
raise
if skip_option:
return
setter = getattr(target_obj, 'set_%s' % option_name, None) setter = getattr(target_obj, 'set_%s' % option_name, None)
if setter is None: if setter is None:
......
...@@ -73,6 +73,22 @@ class TestConfigurationReader: ...@@ -73,6 +73,22 @@ class TestConfigurationReader:
with pytest.raises(DistutilsFileError): with pytest.raises(DistutilsFileError):
read_configuration('%s' % tmpdir.join('setup.cfg')) read_configuration('%s' % tmpdir.join('setup.cfg'))
def test_ignore_errors(self, tmpdir):
fake_env(
tmpdir,
'[metadata]\n'
'version = attr: none.VERSION\n'
'keywords = one, two\n'
)
with pytest.raises(ImportError):
read_configuration('%s' % tmpdir.join('setup.cfg'))
config_dict = read_configuration(
'%s' % tmpdir.join('setup.cfg'), ignore_option_errors=True)
assert config_dict['metadata']['keywords'] == ['one', 'two']
assert 'version' not in config_dict['metadata']
class TestMetadata: class TestMetadata:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment