dist: trusty
-sudo: false
language: python
-python:
-- &latest_py2 2.7
-- 3.4
-- 3.5
-- &latest_py3 3.6
-- nightly
-- pypy
-- pypy3
jobs:
fast_finish: true
include:
- - python: *latest_py3
+ - &latest_py2
+ python: 2.7
+ - <<: *latest_py2
env: LANG=C
- - python: *latest_py2
+ - python: pypy
+ env: DISABLE_COVERAGE=1 # Don't run coverage on pypy (too slow).
+ - python: pypy3
+ env: DISABLE_COVERAGE=1
+ - python: 3.4
+ - python: 3.5
+ - &default_py
+ python: 3.6
+ - &latest_py3
+ python: 3.7
+ dist: xenial
+ - <<: *latest_py3
env: LANG=C
- - stage: deploy (to PyPI for tagged commits)
+ - python: 3.8-dev
+ dist: xenial
+ env: DISABLE_COVERAGE=1 # Ignore invalid coverage data.
+ - <<: *default_py
+ stage: deploy (to PyPI for tagged commits)
if: tag IS present
- python: *latest_py3
install: skip
script: skip
after_success: true
cache: pip
install:
-# ensure we have recent pip/setuptools
-- pip install --upgrade pip setuptools
+
+# ensure we have recent pip/setuptools/wheel
+- pip install --disable-pip-version-check --upgrade pip setuptools wheel
# need tox to get started
-- pip install tox tox-venv
+- pip install --upgrade tox tox-venv
# Output the env, to verify behavior
+- pip freeze --all
- env
# update egg_info based on setup.py in checkout
script:
- |
( # Run testsuite.
- set -ex
- case $TRAVIS_PYTHON_VERSION in
- pypy*)
- # Don't run coverage on pypy (too slow).
- tox
- ;;
- *)
+ if [ -z "$DISABLE_COVERAGE" ]
+ then
tox -- --cov
- ;;
- esac
+ else
+ tox
+ fi
)
after_success:
- |
( # Upload coverage data.
- set -ex
- case $TRAVIS_PYTHON_VERSION in
- pypy*)
- ;;
- *)
+ if [ -z "$DISABLE_COVERAGE" ]
+ then
export TRAVIS_JOB_NAME="${TRAVIS_PYTHON_VERSION} (LANG=$LANG)" CODECOV_ENV=TRAVIS_JOB_NAME
tox -e coverage,codecov
- ;;
- esac
+ fi
)
+v40.5.0
+-------
+
+* #1335: In ``pkg_resources.normalize_path``, fix issue on Cygwin when cwd contains symlinks.
+* #1502: Deprecated support for downloads from Subversion in package_index/easy_install.
+* #1517: Dropped use of six.u in favor of `u""` literals.
+* #1520: Added support for ``data_files`` in ``setup.cfg``.
+* #1525: Fixed rendering of the deprecation warning in easy_install doc.
+
+
v40.4.3
-------
+clone_depth: 50
+
environment:
APPVEYOR: True
- '%LOCALAPPDATA%\pip\Cache'
test_script:
- - "python bootstrap.py"
- - "python -m pip install tox"
- - "tox -- --cov"
+ - python --version
+ - python -m pip install --disable-pip-version-check --upgrade pip setuptools wheel
+ - pip install --upgrade tox tox-venv
+ - pip freeze --all
+ - python bootstrap.py
+ - tox -- --cov
after_test:
- tox -e coverage,codecov
Easy Install
============
-..warning::
+.. warning::
Easy Install is deprecated. Do not use it. Instead use pip. If
you think you need Easy Install, please reach out to the PyPA
team (a ticket to pip or setuptools is fine), describing your
src.subpackage1
src.subpackage2
+ [options.data_files]
+ /etc/my_package =
+ site.d/00_default.conf
+ host.d/00_default.conf
+ data = data/img/logo.png, data/svg/icon.svg
Metadata and options are set in the config sections of the same name.
def normalize_path(filename):
"""Normalize a file/dir name for comparison purposes"""
- return os.path.normcase(os.path.realpath(filename))
+ return os.path.normcase(os.path.realpath(_cygwin_patch(filename)))
+
+
+def _cygwin_patch(filename): # pragma: nocover
+ """
+ Contrary to POSIX 2008, on Cygwin, getcwd (3) contains
+ symlink components. Using
+ os.path.abspath() works around this limitation. A fix in os.getcwd()
+ would probably better, in Cygwin even more so, except
+ that this seems to be by design...
+ """
+ return os.path.abspath(filename) if sys.platform == 'cygwin' else filename
def _normalize_cached(filename, _cache={}):
[bumpversion]
-current_version = 40.4.3
+current_version = 40.5.0
commit = True
tag = True
setup_params = dict(
name="setuptools",
- version="40.4.3",
+ version="40.5.0",
description=(
"Easily download, build, install, upgrade, and uninstall "
"Python packages"
@contextlib.contextmanager
def _tmpdir(self):
- tmpdir = tempfile.mkdtemp(prefix=six.u("easy_install-"))
+ tmpdir = tempfile.mkdtemp(prefix=u"easy_install-")
try:
# cast to str as workaround for #709 and #710 and #712
yield str(tmpdir)
@classmethod
def get_script_header(cls, script_text, executable=None, wininst=False):
# for backward compatibility
- warnings.warn("Use get_header", DeprecationWarning)
+ warnings.warn("Use get_header", DeprecationWarning, stacklevel=2)
if wininst:
executable = "python.exe"
- cmd = cls.command_spec_class.best().from_param(executable)
- cmd.install_options(script_text)
- return cmd.as_header()
+ return cls.get_header(script_text, executable)
@classmethod
def get_args(cls, dist, header=None):
parse_list = partial(self._parse_list, separator=';')
self['extras_require'] = self._parse_section_to_dict(
section_options, parse_list)
+
+ def parse_section_data_files(self, section_options):
+ """Parses `data_files` configuration file section.
+
+ :param dict section_options:
+ """
+ parsed = self._parse_section_to_dict(section_options, self._parse_list)
+ self['data_files'] = [(k, v) for k, v in parsed.items()]
import base64
import hashlib
import itertools
+import warnings
from functools import wraps
from setuptools.extern import six
raise DistutilsError("Unexpected HTML page found at " + url)
def _download_svn(self, url, filename):
+ warnings.warn("SVN download support is deprecated", UserWarning)
url = url.split('#', 1)[0] # remove any fragment for svn's sake
creds = ''
if url.lower().startswith('svn:') and '@' in url:
auth_s = urllib.parse.unquote(auth)
# convert to bytes
auth_bytes = auth_s.encode()
- # use the legacy interface for Python 2.3 support
- encoded_bytes = base64.encodestring(auth_bytes)
+ encoded_bytes = base64.b64encode(auth_bytes)
# convert back to a string
encoded = encoded_bytes.decode()
# strip the trailing carriage return
with get_dist(tmpdir) as dist:
assert dist.entry_points == expected
+ def test_data_files(self, tmpdir):
+ fake_env(
+ tmpdir,
+ '[options.data_files]\n'
+ 'cfg =\n'
+ ' a/b.conf\n'
+ ' c/d.conf\n'
+ 'data = e/f.dat, g/h.dat\n'
+ )
+
+ with get_dist(tmpdir) as dist:
+ expected = [
+ ('cfg', ['a/b.conf', 'c/d.conf']),
+ ('data', ['e/f.dat', 'g/h.dat']),
+ ]
+ assert sorted(dist.data_files) == sorted(expected)
+
saved_dist_init = _Distribution.__init__
class TestExternalSetters:
# During creation of the setuptools Distribution() object, we call
assert (target / 'mypkg_script').exists()
+@pytest.mark.filterwarnings('ignore:Unbuilt egg')
class TestPTHFileWriter:
def test_add_from_cwd_site_sets_dirty(self):
'''a pth file manager should set dirty
def test_get_script_header(self):
expected = '#!%s\n' % ei.nt_quote_arg(os.path.normpath(sys.executable))
- actual = ei.ScriptWriter.get_script_header('#!/usr/local/bin/python')
+ actual = ei.ScriptWriter.get_header('#!/usr/local/bin/python')
assert actual == expected
def test_get_script_header_args(self):
expected = '#!%s -x\n' % ei.nt_quote_arg(
os.path.normpath(sys.executable))
- actual = ei.ScriptWriter.get_script_header('#!/usr/bin/python -x')
+ actual = ei.ScriptWriter.get_header('#!/usr/bin/python -x')
assert actual == expected
def test_get_script_header_non_ascii_exe(self):
- actual = ei.ScriptWriter.get_script_header(
+ actual = ei.ScriptWriter.get_header(
'#!/usr/bin/python',
executable=self.non_ascii_exe)
expected = str('#!%s -x\n') % self.non_ascii_exe
assert actual == expected
def test_get_script_header_exe_with_spaces(self):
- actual = ei.ScriptWriter.get_script_header(
+ actual = ei.ScriptWriter.get_header(
'#!/usr/bin/python',
executable='"' + self.exe_with_spaces + '"')
expected = '#!"%s"\n' % self.exe_with_spaces
class TestWindowsScriptWriter:
def test_header(self):
- hdr = ei.WindowsScriptWriter.get_script_header('')
+ hdr = ei.WindowsScriptWriter.get_header('')
assert hdr.startswith('#!')
assert hdr.endswith('\n')
hdr = hdr.lstrip('#!')
import sys
+import pytest
from mock import patch
from setuptools import pep425tags
with patch('setuptools.pep425tags.sysconfig.get_config_var',
raises_ioerror):
- assert len(pep425tags.get_supported())
+ with pytest.warns(RuntimeWarning):
+ assert len(pep425tags.get_supported())
def test_no_hyphen_tag(self):
"""
self.dist.exclude(package_dir=['q'])
+@pytest.mark.filterwarnings('ignore:Features are deprecated')
class TestFeatures:
def setup_method(self, method):
self.req = Require('Distutils', '1.0.3', 'distutils')
description=[Only run on CI]: Upload coverage data to codecov
deps=codecov
skip_install=True
-commands=codecov --file {toxworkdir}/coverage.xml
+commands=codecov -X gcov --file {toxworkdir}/coverage.xml
[testenv:docs]
deps = -r{toxinidir}/docs/requirements.txt