Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
benoit-pierre committed Jun 15, 2017
1 parent eba6ed4 commit 8683dba
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 16 deletions.
2 changes: 1 addition & 1 deletion setuptools/dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
39 changes: 26 additions & 13 deletions setuptools/py36compat.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import io
import re
import sys
from distutils.errors import DistutilsOptionError
from distutils.util import strtobool
from distutils.debug import DEBUG
from setuptools.extern import six


CODING_RE = re.compile(br'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)')

def detect_encoding(fp):
first_line = fp.readline()
fp.seek(0)
m = CODING_RE.match(first_line)
if m is None:
return None
return m.group(1).decode('ascii')


class Distribution_parse_config_files:
Expand All @@ -13,10 +27,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',
Expand All @@ -33,18 +47,23 @@ 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, 'rb') as fp:
encoding = detect_encoding(fp)
if DEBUG:
self.announce(" reading %s [%s]" % (
filename, encoding or 'locale')
)
reader = io.TextIOWrapper(fp, encoding=encoding)
(parser.read_file if six.PY3 else parser.readfp)(reader)
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)

Expand All @@ -69,12 +88,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.
Expand Down
73 changes: 71 additions & 2 deletions setuptools/tests/test_config.py
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -16,7 +20,7 @@ def make_package_dir(name, base_dir):
return dir_package, init_file


def fake_env(tmpdir, setup_cfg, setup_py=None):
def fake_env(tmpdir, setup_cfg, setup_py=None, encoding='ascii'):

if setup_py is None:
setup_py = (
Expand All @@ -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(encoding), mode='wb')

package_dir, init_file = make_package_dir('fake_package', tmpdir)

Expand Down Expand Up @@ -288,6 +292,71 @@ 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_1(self, tmpdir):
fake_env(
tmpdir,
'[metadata]\n'
'description = éàïôñ\n',
encoding='utf-8'
)
with pytest.raises(UnicodeDecodeError):
with get_dist(tmpdir):
pass

def test_non_ascii_2(self, tmpdir):
fake_env(
tmpdir,
'# -*- coding: invalid\n'
)
with pytest.raises(LookupError):
with get_dist(tmpdir):
pass

def test_non_ascii_3(self, tmpdir):
fake_env(
tmpdir,
'\n'
'# -*- coding: invalid\n'
)
with get_dist(tmpdir):
pass

@skip_if_not_ascii
def test_non_ascii_4(self, tmpdir):
fake_env(
tmpdir,
'# -*- coding: utf-8\n'
'[metadata]\n'
'description = éàïôñ\n',
encoding='utf-8'
)
with get_dist(tmpdir) as dist:
assert dist.metadata.description == 'éàïôñ'

@skip_if_not_ascii
def test_non_ascii_5(self, tmpdir):
fake_env(
tmpdir,
'# vim: set fileencoding=iso-8859-15 :\n'
'[metadata]\n'
'description = éàïôñ\n',
encoding='iso-8859-15'
)
with get_dist(tmpdir) as dist:
assert dist.metadata.description == 'éàïôñ'


class TestOptions:

Expand Down

0 comments on commit 8683dba

Please sign in to comment.