diff --git a/setuptools/dist.py b/setuptools/dist.py index 6b97ed33c5..653688fdf3 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -352,7 +352,7 @@ def parse_config_files(self, filenames=None): and loads configuration. """ - _Distribution.parse_config_files(self, filenames=filenames) + Distribution_parse_config_files.parse_config_files(self, filenames=filenames) parse_configuration(self, self.command_options) if getattr(self, 'python_requires', None): diff --git a/setuptools/py36compat.py b/setuptools/py36compat.py index f527969645..c657a29c5b 100644 --- a/setuptools/py36compat.py +++ b/setuptools/py36compat.py @@ -1,7 +1,9 @@ +import io import sys from distutils.errors import DistutilsOptionError from distutils.util import strtobool from distutils.debug import DEBUG +from setuptools.extern import six class Distribution_parse_config_files: @@ -13,10 +15,10 @@ class Distribution_parse_config_files: as implemented in distutils. """ def parse_config_files(self, filenames=None): - from configparser import ConfigParser + from setuptools.extern.six.moves.configparser import ConfigParser # Ignore install directory options if we have a venv - if sys.prefix != sys.base_prefix: + if six.PY3 and sys.prefix != sys.base_prefix: ignore_options = [ 'install-base', 'install-platbase', 'install-lib', 'install-platlib', 'install-purelib', 'install-headers', @@ -33,18 +35,22 @@ def parse_config_files(self, filenames=None): if DEBUG: self.announce("Distribution.parse_config_files():") - parser = ConfigParser(interpolation=None) + parser = ConfigParser() for filename in filenames: if DEBUG: self.announce(" reading %s" % filename) - parser.read(filename) + with io.open(filename, encoding='utf-8') as fp: + if six.PY3: + parser.read_file(fp) + else: + parser.readfp(fp) for section in parser.sections(): options = parser.options(section) opt_dict = self.get_option_dict(section) for opt in options: if opt != '__name__' and opt not in ignore_options: - val = parser.get(section,opt) + val = parser.get(section,opt,raw=True) opt = opt.replace('-', '_') opt_dict[opt] = (filename, val) @@ -69,12 +75,6 @@ def parse_config_files(self, filenames=None): raise DistutilsOptionError(msg) -if sys.version_info < (3,): - # Python 2 behavior is sufficient - class Distribution_parse_config_files: - pass - - if False: # When updated behavior is available upstream, # disable override here. diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index 8bd2a49428..063d30e2ca 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -1,8 +1,12 @@ +# -*- coding: UTF-8 -*- +from __future__ import unicode_literals + import contextlib import pytest from distutils.errors import DistutilsOptionError, DistutilsFileError from setuptools.dist import Distribution from setuptools.config import ConfigHandler, read_configuration +from setuptools.tests import is_ascii class ErrConfigHandler(ConfigHandler): @@ -26,7 +30,7 @@ def fake_env(tmpdir, setup_cfg, setup_py=None): tmpdir.join('setup.py').write(setup_py) config = tmpdir.join('setup.cfg') - config.write(setup_cfg) + config.write(setup_cfg.encode('utf-8'), mode='wb') package_dir, init_file = make_package_dir('fake_package', tmpdir) @@ -288,6 +292,27 @@ def test_classifiers(self, tmpdir): with get_dist(tmpdir) as dist: assert set(dist.metadata.classifiers) == expected + def test_no_interpolation(self, tmpdir): + fake_env( + tmpdir, + '[metadata]\n' + 'description = %(message)s\n' + ) + with get_dist(tmpdir) as dist: + assert dist.metadata.description == '%(message)s' + + skip_if_not_ascii = pytest.mark.skipif(not is_ascii, reason='Test not supported with this locale') + + @skip_if_not_ascii + def test_non_ascii(self, tmpdir): + fake_env( + tmpdir, + '[metadata]\n' + 'description = éàïôñ\n' + ) + with get_dist(tmpdir) as dist: + assert dist.metadata.description == 'éàïôñ' + class TestOptions: