--- /dev/null
+comment: false
*~
.hg*
.cache
+.pytest_cache/
python: *latest_py3
install: skip
script: skip
+ after_success: true
before_deploy: python bootstrap.py
deploy:
provider: pypi
# update egg_info based on setup.py in checkout
- python bootstrap.py
-script: tox
+script:
+ - |
+ ( # Run testsuite.
+ set -ex
+ case $TRAVIS_PYTHON_VERSION in
+ pypy*)
+ # Don't run coverage on pypy (too slow).
+ tox
+ ;;
+ *)
+ tox -- --cov
+ ;;
+ esac
+ )
+
+after_success:
+ - |
+ ( # Upload coverage data.
+ set -ex
+ case $TRAVIS_PYTHON_VERSION in
+ pypy*)
+ ;;
+ *)
+ export TRAVIS_JOB_NAME="${TRAVIS_PYTHON_VERSION} (LANG=$LANG)" CODECOV_ENV=TRAVIS_JOB_NAME
+ tox -e coverage,codecov
+ ;;
+ esac
+ )
+v39.1.0
+-------
+
+* #1340: Update all PyPI URLs to reflect the switch to the
+ new Warehouse codebase.
+* #1337: In ``pkg_resources``, now support loading resources
+ for modules loaded by the ``SourcelessFileLoader``.
+* #1332: Silence spurious wheel related warnings on Windows.
+
v39.0.1
-------
* Issue #313: Removed built-in support for subversion. Projects wishing to
retain support for subversion will need to use a third party library. The
extant implementation is being ported to `setuptools_svn
- <https://pypi.python.org/pypi/setuptools_svn>`_.
+ <https://pypi.org/project/setuptools_svn/>`_.
* Issue #315: Updated setuptools to hide its own loaded modules during
installation of another package. This change will enable setuptools to
upgrade (or downgrade) itself even when its own metadata and implementation
* Address security vulnerability in SSL match_hostname check as reported in
Python #17997.
* Prefer `backports.ssl_match_hostname
- <https://pypi.python.org/pypi/backports.ssl_match_hostname>`_ for backport
+ <https://pypi.org/project/backports.ssl_match_hostname/>`_ for backport
implementation if present.
* Correct NameError in ``ssl_support`` module (``socket.error``).
environment:
- APPVEYOR: true
+ APPVEYOR: True
+ CODECOV_ENV: APPVEYOR_JOB_NAME
matrix:
- - PYTHON: "C:\\Python35-x64"
- - PYTHON: "C:\\Python27-x64"
+ - APPVEYOR_JOB_NAME: "python35-x64"
+ PYTHON: "C:\\Python35-x64"
+ - APPVEYOR_JOB_NAME: "python27-x64"
+ PYTHON: "C:\\Python27-x64"
install:
# symlink python from a directory with a space
test_script:
- "python bootstrap.py"
- "python -m pip install tox"
- - "tox"
+ - "tox -- --cov"
+
+after_test:
+ - tox -e coverage,codecov
version: '{build}'
<h3>Download</h3>
<p>Current version: <b>{{ version }}</b></p>
-<p>Get Setuptools from the <a href="https://pypi.python.org/pypi/setuptools"> Python Package Index</a>
+<p>Get Setuptools from the <a href="https://pypi.org/project/setuptools/"> Python Package Index</a>
<h3>Questions? Suggestions? Contributions?</h3>
Installing "Easy Install"
-------------------------
-Please see the `setuptools PyPI page <https://pypi.python.org/pypi/setuptools>`_
+Please see the `setuptools PyPI page <https://pypi.org/project/setuptools/>`_
for download links and basic installation instructions for each of the
supported platforms.
``--index-url=URL, -i URL`` (New in 0.4a1; default changed in 0.6c7)
Specifies the base URL of the Python Package Index. The default is
- https://pypi.python.org/simple if not specified. When a package is requested
+ https://pypi.org/simple/ if not specified. When a package is requested
that is not locally available or linked from a ``--find-links`` download
page, the package index will be searched for download pages for the needed
package, and those download pages will be searched for links to download
Please refer to the `virtualenv`_ documentation for more details.
-.. _virtualenv: https://pypi.python.org/pypi/virtualenv
+.. _virtualenv: https://pypi.org/project/virtualenv/
* Signature checking? SSL? Ability to suppress PyPI search?
* Display byte progress meter when downloading distributions and long pages?
* Redirect stdout/stderr to log during run_setup?
-
Setuptools provides a facility to invoke 2to3 on the code as a part of the
build process, by setting the keyword parameter ``use_2to3`` to True, but
the Setuptools strongly recommends instead developing a unified codebase
-using `six <https://pypi.python.org/pypi/six>`_,
-`future <https://pypi.python.org/pypi/future>`_, or another compatibility
+using `six <https://pypi.org/project/six/>`_,
+`future <https://pypi.org/project/future/>`_, or another compatibility
library.
in distutils.
Setuptools augments the ``upload`` command with support
-for `keyring <https://pypi.python.org/pypi/keyring>`_,
+for `keyring <https://pypi.org/project/keyring/>`_,
allowing the password to be stored in a secure
location and not in plaintext in the .pypirc file. To use
keyring, first install keyring and set the password for
If the files you want to include in the source distribution are tracked using
Git, Mercurial or SVN, you can use the following packages to achieve that:
-- Git and Mercurial: `setuptools_scm <https://pypi.python.org/pypi/setuptools_scm>`_
-- SVN: `setuptools_svn <https://pypi.python.org/pypi/setuptools_svn>`_
+- Git and Mercurial: `setuptools_scm <https://pypi.org/project/setuptools_scm/>`_
+- SVN: `setuptools_svn <https://pypi.org/project/setuptools_svn/>`_
If you would like to create a plugin for ``setuptools`` to find files tracked
by another revision control system, you can do so by adding an entry point to
@classmethod
def _register(cls):
- loader_cls = getattr(
- importlib_machinery,
- 'SourceFileLoader',
- type(None),
- )
- register_loader_type(loader_cls, cls)
+ loader_names = 'SourceFileLoader', 'SourcelessFileLoader',
+ for name in loader_names:
+ loader_cls = getattr(importlib_machinery, name, type(None))
+ register_loader_type(loader_cls, cls)
DefaultProvider._register()
[bumpversion]
-current_version = 39.0.1
+current_version = 39.1.0
commit = True
tag = True
setup_params = dict(
name="setuptools",
- version="39.0.1",
+ version="39.1.0",
description=(
"Easily download, build, install, upgrade, and uninstall "
"Python packages"
self.all_site_dirs.append(normalize_path(d))
if not self.editable:
self.check_site_dir()
- self.index_url = self.index_url or "https://pypi.python.org/simple"
+ self.index_url = self.index_url or "https://pypi.org/simple/"
self.shadow_path = self.all_site_dirs[:]
for path_item in self.install_dir, normalize_path(self.script_dir):
if path_item not in self.shadow_path:
file.write('Provides-Extra: %s\n' % extra)
-# from Python 3.4
-def write_pkg_info(self, base_dir):
- """Write the PKG-INFO file into the release tree.
- """
- with open(os.path.join(base_dir, 'PKG-INFO'), 'w',
- encoding='UTF-8') as pkg_info:
- self.write_pkg_file(pkg_info)
-
-
sequence = tuple, list
distutils.config.PyPIRCCommand.DEFAULT_REPOSITORY = warehouse
_patch_distribution_metadata_write_pkg_file()
- _patch_distribution_metadata_write_pkg_info()
# Install Distribution throughout the distutils
for module in distutils.dist, distutils.core, distutils.cmd:
)
-def _patch_distribution_metadata_write_pkg_info():
- """
- Workaround issue #197 - Python 3 prior to 3.2.2 uses an environment-local
- encoding to save the pkg_info. Monkey-patch its write_pkg_info method to
- correct this undesirable behavior.
- """
- environment_local = (3,) <= sys.version_info[:3] < (3, 2, 2)
- if not environment_local:
- return
-
- distutils.dist.DistributionMetadata.write_pkg_info = (
- setuptools.dist.write_pkg_info
- )
-
-
def patch_func(replacement, target_mod, func_name):
"""
Patch func_name in target_mod with replacement
"""A distribution index that scans web pages for download URLs"""
def __init__(
- self, index_url="https://pypi.python.org/simple", hosts=('*',),
+ self, index_url="https://pypi.org/simple/", hosts=('*',),
ca_bundle=None, verify_ssl=True, *args, **kw
):
Environment.__init__(self, *args, **kw)
from __future__ import absolute_import
import distutils.util
+from distutils import log
import platform
import re
import sys
val = get_config_var(var)
if val is None:
if warn:
- warnings.warn("Config variable '{0}' is unset, Python ABI tag may "
- "be incorrect".format(var), RuntimeWarning, 2)
+ log.debug("Config variable '%s' is unset, Python ABI tag may "
+ "be incorrect", var)
return fallback()
return val == expected
pytz
''',
+ '''
+ install_requires_ordered
+
+ install_requires=["fake-factory>=1.12.3,!=2.0"]
+
+ [options]
+ install_requires =
+ fake-factory>=1.12.3,!=2.0
+
+ fake-factory!=2.0,>=1.12.3
+ ''',
+
'''
install_requires_with_marker
with pypirc.open('w') as strm:
strm.write(DALS("""
[pypi]
- repository=https://pypi.python.org
+ repository=https://pypi.org
username=jaraco
password=pity%
"""))
cfg = setuptools.package_index.PyPIConfig()
- cred = cfg.creds_by_repository['https://pypi.python.org']
+ cred = cfg.creds_by_repository['https://pypi.org']
assert cred.username == 'jaraco'
assert cred.password == 'pity%'
yield glob.glob(os.path.join(source_dir, 'dist', '*.whl'))[0]
-def tree(root):
- def depth(path):
- return len(path.split(os.path.sep))
- def prefix(path_depth):
- if not path_depth:
- return ''
- return '| ' * (path_depth - 1) + '|-- '
- lines = []
- root_depth = depth(root)
+def tree_set(root):
+ contents = set()
for dirpath, dirnames, filenames in os.walk(root):
- dirnames.sort()
- filenames.sort()
- dir_depth = depth(dirpath) - root_depth
- if dir_depth > 0:
- lines.append('%s%s/' % (prefix(dir_depth - 1),
- os.path.basename(dirpath)))
- for f in filenames:
- lines.append('%s%s' % (prefix(dir_depth), f))
- return '\n'.join(lines) + '\n'
-
-
-def _check_wheel_install(filename, install_dir, install_tree,
+ for filename in filenames:
+ contents.add(os.path.join(os.path.relpath(dirpath, root),
+ filename))
+ return contents
+
+
+def flatten_tree(tree):
+ """Flatten nested dicts and lists into a full list of paths"""
+ output = set()
+ for node, contents in tree.items():
+ if isinstance(contents, dict):
+ contents = flatten_tree(contents)
+
+ for elem in contents:
+ if isinstance(elem, dict):
+ output |= {os.path.join(node, val)
+ for val in flatten_tree(elem)}
+ else:
+ output.add(os.path.join(node, elem))
+ return output
+
+
+def format_install_tree(tree):
+ return {x.format(
+ py_version=PY_MAJOR,
+ platform=get_platform(),
+ shlib_ext=get_config_var('EXT_SUFFIX') or get_config_var('SO'))
+ for x in tree}
+
+
+def _check_wheel_install(filename, install_dir, install_tree_includes,
project_name, version, requires_txt):
w = Wheel(filename)
egg_path = os.path.join(install_dir, w.egg_name())
w.install_as_egg(egg_path)
- if install_tree is not None:
- install_tree = install_tree.format(
- py_version=PY_MAJOR,
- platform=get_platform(),
- shlib_ext=get_config_var('EXT_SUFFIX') or get_config_var('SO')
- )
- assert install_tree == tree(install_dir)
+ if install_tree_includes is not None:
+ install_tree = format_install_tree(install_tree_includes)
+ exp = tree_set(install_dir)
+ assert install_tree.issubset(exp), (install_tree - exp)
+
metadata = PathMetadata(egg_path, os.path.join(egg_path, 'EGG-INFO'))
dist = Distribution.from_filename(egg_path, metadata=metadata)
assert dist.project_name == project_name
setup_kwargs=dict(
packages=['foo'],
),
- install_tree=DALS(
- '''
- foo-1.0-py{py_version}.egg/
- |-- EGG-INFO/
- | |-- DESCRIPTION.rst
- | |-- PKG-INFO
- | |-- RECORD
- | |-- WHEEL
- | |-- metadata.json
- | |-- top_level.txt
- |-- foo/
- | |-- __init__.py
- '''
- ),
+ install_tree=flatten_tree({
+ 'foo-1.0-py{py_version}.egg': {
+ 'EGG-INFO': [
+ 'PKG-INFO',
+ 'RECORD',
+ 'WHEEL',
+ 'top_level.txt'
+ ],
+ 'foo': ['__init__.py']
+ }
+ }),
),
dict(
setup_kwargs=dict(
data_files=[('data_dir', ['data.txt'])],
),
- install_tree=DALS(
- '''
- foo-1.0-py{py_version}.egg/
- |-- EGG-INFO/
- | |-- DESCRIPTION.rst
- | |-- PKG-INFO
- | |-- RECORD
- | |-- WHEEL
- | |-- metadata.json
- | |-- top_level.txt
- |-- data_dir/
- | |-- data.txt
- '''
- ),
+ install_tree=flatten_tree({
+ 'foo-1.0-py{py_version}.egg': {
+ 'EGG-INFO': [
+ 'PKG-INFO',
+ 'RECORD',
+ 'WHEEL',
+ 'top_level.txt'
+ ],
+ 'data_dir': [
+ 'data.txt'
+ ]
+ }
+ }),
),
dict(
sources=['extension.c'])
],
),
- install_tree=DALS(
- '''
- foo-1.0-py{py_version}-{platform}.egg/
- |-- extension{shlib_ext}
- |-- EGG-INFO/
- | |-- DESCRIPTION.rst
- | |-- PKG-INFO
- | |-- RECORD
- | |-- WHEEL
- | |-- metadata.json
- | |-- top_level.txt
- '''
- ),
+ install_tree=flatten_tree({
+ 'foo-1.0-py{py_version}-{platform}.egg': [
+ 'extension{shlib_ext}',
+ {'EGG-INFO': [
+ 'PKG-INFO',
+ 'RECORD',
+ 'WHEEL',
+ 'top_level.txt',
+ ]},
+ ]
+ }),
),
dict(
setup_kwargs=dict(
headers=['header.h'],
),
- install_tree=DALS(
- '''
- foo-1.0-py{py_version}.egg/
- |-- header.h
- |-- EGG-INFO/
- | |-- DESCRIPTION.rst
- | |-- PKG-INFO
- | |-- RECORD
- | |-- WHEEL
- | |-- metadata.json
- | |-- top_level.txt
- '''
- ),
+ install_tree=flatten_tree({
+ 'foo-1.0-py{py_version}.egg': [
+ 'header.h',
+ {'EGG-INFO': [
+ 'PKG-INFO',
+ 'RECORD',
+ 'WHEEL',
+ 'top_level.txt',
+ ]},
+ ]
+ }),
),
dict(
setup_kwargs=dict(
scripts=['script.py', 'script.sh'],
),
- install_tree=DALS(
- '''
- foo-1.0-py{py_version}.egg/
- |-- EGG-INFO/
- | |-- DESCRIPTION.rst
- | |-- PKG-INFO
- | |-- RECORD
- | |-- WHEEL
- | |-- metadata.json
- | |-- top_level.txt
- | |-- scripts/
- | | |-- script.py
- | | |-- script.sh
- '''
- ),
+ install_tree=flatten_tree({
+ 'foo-1.0-py{py_version}.egg': {
+ 'EGG-INFO': [
+ 'PKG-INFO',
+ 'RECORD',
+ 'WHEEL',
+ 'top_level.txt',
+ {'scripts': [
+ 'script.py',
+ 'script.sh'
+ ]}
+
+ ]
+ }
+ })
),
dict(
id='requires1',
install_requires='foobar==2.0',
- install_tree=DALS(
- '''
- foo-1.0-py{py_version}.egg/
- |-- EGG-INFO/
- | |-- DESCRIPTION.rst
- | |-- PKG-INFO
- | |-- RECORD
- | |-- WHEEL
- | |-- metadata.json
- | |-- requires.txt
- | |-- top_level.txt
- '''),
+ install_tree=flatten_tree({
+ 'foo-1.0-py{py_version}.egg': {
+ 'EGG-INFO': [
+ 'PKG-INFO',
+ 'RECORD',
+ 'WHEEL',
+ 'requires.txt',
+ 'top_level.txt',
+ ]
+ }
+ }),
requires_txt=DALS(
'''
foobar==2.0
namespace_packages=['foo'],
packages=['foo.bar'],
),
- install_tree=DALS(
- '''
- foo-1.0-py{py_version}.egg/
- |-- foo-1.0-py{py_version}-nspkg.pth
- |-- EGG-INFO/
- | |-- DESCRIPTION.rst
- | |-- PKG-INFO
- | |-- RECORD
- | |-- WHEEL
- | |-- metadata.json
- | |-- namespace_packages.txt
- | |-- top_level.txt
- |-- foo/
- | |-- __init__.py
- | |-- bar/
- | | |-- __init__.py
- '''),
+ install_tree=flatten_tree({
+ 'foo-1.0-py{py_version}.egg': [
+ 'foo-1.0-py{py_version}-nspkg.pth',
+ {'EGG-INFO': [
+ 'PKG-INFO',
+ 'RECORD',
+ 'WHEEL',
+ 'namespace_packages.txt',
+ 'top_level.txt',
+ ]},
+ {'foo': [
+ '__init__.py',
+ {'bar': ['__init__.py']},
+ ]},
+ ]
+ }),
),
dict(
packages=['foo'],
data_files=[('foo/data_dir', ['foo/data_dir/data.txt'])],
),
- install_tree=DALS(
- '''
- foo-1.0-py{py_version}.egg/
- |-- EGG-INFO/
- | |-- DESCRIPTION.rst
- | |-- PKG-INFO
- | |-- RECORD
- | |-- WHEEL
- | |-- metadata.json
- | |-- top_level.txt
- |-- foo/
- | |-- __init__.py
- | |-- data_dir/
- | | |-- data.txt
- '''
- ),
+ install_tree=flatten_tree({
+ 'foo-1.0-py{py_version}.egg': {
+ 'EGG-INFO': [
+ 'PKG-INFO',
+ 'RECORD',
+ 'WHEEL',
+ 'top_level.txt',
+ ],
+ 'foo': [
+ '__init__.py',
+ {'data_dir': [
+ 'data.txt',
+ ]}
+ ]
+ }
+ }),
),
)
pytest-virtualenv>=1.2.7
pytest>=3.0.2
wheel
+coverage>=4.5.1
+pytest-cov>=2.5.1
#
# export TOXENV='py27,py3{3,4,5,6},pypy,pypy3'
+[tox]
+envlist=python
+
[testenv]
deps=-rtests/requirements.txt
-passenv=APPDATA USERPROFILE HOMEDRIVE HOMEPATH windir APPVEYOR
-commands=py.test {posargs}
+setenv=COVERAGE_FILE={toxworkdir}/.coverage.{envname}
+# TODO: The passed environment variables came from copying other tox.ini files
+# These should probably be individually annotated to explain what needs them.
+passenv=APPDATA HOMEDRIVE HOMEPATH windir APPVEYOR APPVEYOR_* CI CODECOV_* TRAVIS TRAVIS_*
+commands=pytest --cov-config={toxinidir}/tox.ini --cov-report= {posargs}
usedevelop=True
+
+
+[testenv:coverage]
+description=Combine coverage data and create report
+deps=coverage
+skip_install=True
+changedir={toxworkdir}
+setenv=COVERAGE_FILE=.coverage
+commands=coverage erase
+ coverage combine
+ coverage {posargs:xml}
+
+[testenv:codecov]
+description=[Only run on CI]: Upload coverage data to codecov
+deps=codecov
+skip_install=True
+commands=codecov --file {toxworkdir}/coverage.xml
+
+[coverage:run]
+source=
+ pkg_resources
+ setuptools
+omit=
+ */_vendor/*