aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.hgtags5
-rw-r--r--.travis.yml3
-rw-r--r--CHANGES.txt34
-rwxr-xr-xREADME.txt14
-rw-r--r--bootstrap.py51
-rw-r--r--docs/setuptools.txt2
-rw-r--r--docs/using.txt3
-rw-r--r--ez_setup.py2
-rw-r--r--pkg_resources.py19
-rw-r--r--setuptools.egg-info/dependency_links.txt2
-rw-r--r--setuptools.egg-info/entry_points.txt64
-rw-r--r--setuptools.egg-info/requires.txt7
-rw-r--r--setuptools/__init__.py6
-rwxr-xr-xsetuptools/command/easy_install.py4
-rwxr-xr-xsetuptools/command/install_egg_info.py2
-rw-r--r--setuptools/dist.py19
-rw-r--r--setuptools/svn_utils.py2
-rw-r--r--setuptools/tests/environment.py65
-rw-r--r--setuptools/version.py2
-rw-r--r--setuptools/windows_support.py29
-rw-r--r--tox.ini2
21 files changed, 185 insertions, 152 deletions
diff --git a/.hgtags b/.hgtags
index d3538875..7e995132 100644
--- a/.hgtags
+++ b/.hgtags
@@ -156,4 +156,7 @@ a1fc0220bfa3581158688789f6dfdc00672eb99b 5.6
67550a8ed9f4ef49ee5a31f433adbf5a0eaeccf9 5.8
755cbfd3743ffb186cdf7e20be8e61dbdaa22503 6.0
bc6655b4acf205dd9f25c702955645656077398a 6.0.1
-8b8a52665803abf0bc2d2e892fc59ce5416f4bf7 7.0b1
+1ae2a75724bbba56373784f185a7f235ed0f24a4 6.0.2b1
+01271e84e5125fcc4f0f368a6e21116a5722953c 6.0.2
+7ea80190d494a766c6356fce85c844703964b6cc 6.1
+df26609c2f614f5fc9110342e4003ee8bd95cf84 7.0
diff --git a/.travis.yml b/.travis.yml
index bc387f46..22541671 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,8 +8,7 @@ python:
- pypy
# command to run tests
script:
- # testing fix for https://bitbucket.org/hpk42/pytest/issue/555
- - pip install --pre -i https://devpi.net/hpk/dev/ --upgrade pytest
+ - python setup.py egg_info
- python setup.py test
- python setup.py ptr
- python ez_setup.py --version 5.4.1
diff --git a/CHANGES.txt b/CHANGES.txt
index 19d8095f..f4d8019a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -3,7 +3,7 @@ CHANGES
=======
---
-7.0
+8.0
---
* Implement `PEP 440 <http://legacy.python.org/dev/peps/pep-0440/>`_ within
@@ -15,6 +15,38 @@ CHANGES
supported. Setuptools now "vendors" the `packaging
<https://github.com/pypa/packaging>`_ library.
+---
+7.0
+---
+
+* Issue #80, Issue #209: Eggs that are downloaded for ``setup_requires``,
+ ``test_requires``, etc. are now placed in a ``./.eggs`` directory instead of
+ directly in the current directory. This choice of location means the files
+ can be readily managed (removed, ignored). Additionally,
+ later phases or invocations of setuptools will not detect the package as
+ already installed and ignore it for permanent install (See #209).
+
+ This change is indicated as backward-incompatible as installations that
+ depend on the installation in the current directory will need to account for
+ the new location. Systems that ignore ``*.egg`` will probably need to be
+ adapted to ignore ``.eggs``. The files will need to be manually moved or
+ will be retrieved again. Most use cases will require no attention.
+
+---
+6.1
+---
+
+* Issue #268: When resolving package versions, a VersionConflict now reports
+ which package previously required the conflicting version.
+
+-----
+6.0.2
+-----
+
+* Issue #262: Fixed regression in pip install due to egg-info directories
+ being omitted. Re-opens Issue #118.
+>>>>>>> master
+
-----
6.0.1
-----
diff --git a/README.txt b/README.txt
index 9a142bf7..c6973298 100755
--- a/README.txt
+++ b/README.txt
@@ -83,6 +83,18 @@ Alternatively, Setuptools may be installed to a user-local path::
> wget https://bootstrap.pypa.io/ez_setup.py -O - | python - --user
+Note that on some older systems (noted on Debian 6 and CentOS 5 installations),
+`wget` may refuse to download `ez_setup.py`, complaining that the certificate common name `*.c.ssl.fastly.net`
+does not match the host name `bootstrap.pypa.io`. In addition, the `ez_setup.py` script may then encounter similar problems using
+`wget` internally to download `setuptools-x.y.zip`, complaining that the certificate common name of `www.python.org` does not match the
+host name `pypi.python.org`. Those are known issues, related to a bug in the older versions of `wget`
+(see `Issue 59 <https://bitbucket.org/pypa/pypi/issue/59#comment-5881915>`_). If you happen to encounter them,
+install Setuptools as follows::
+
+ > wget --no-check-certificate https://bootstrap.pypa.io/ez_setup.py
+ > python ez_setup.py --insecure
+
+
Unix including Mac OS X (curl)
==============================
@@ -153,7 +165,6 @@ learning about Setuptools, Python Eggs, and EasyInstall:
* `The EasyInstall user's guide and reference manual`_
* `The setuptools Developer's Guide`_
* `The pkg_resources API reference`_
-* `Package Compatibility Notes`_ (user-maintained)
* `The Internal Structure of Python Eggs`_
Questions, comments, and bug reports should be directed to the `distutils-sig
@@ -164,7 +175,6 @@ them there, so this reference list can be updated. If you have working,
the `setuptools bug tracker`_.
.. _setuptools bug tracker: https://bitbucket.org/pypa/setuptools/issues
-.. _Package Compatibility Notes: https://pythonhosted.org/setuptools/PackageNotes
.. _The Internal Structure of Python Eggs: https://pythonhosted.org/setuptools/formats.html
.. _The setuptools Developer's Guide: https://pythonhosted.org/setuptools/setuptools.html
.. _The pkg_resources API reference: https://pythonhosted.org/setuptools/pkg_resources.html
diff --git a/bootstrap.py b/bootstrap.py
new file mode 100644
index 00000000..cbc1ca9d
--- /dev/null
+++ b/bootstrap.py
@@ -0,0 +1,51 @@
+"""
+If setuptools is not already installed in the environment, it's not possible
+to invoke setuptools' own commands. This routine will bootstrap this local
+environment by creating a minimal egg-info directory and then invoking the
+egg-info command to flesh out the egg-info directory.
+"""
+
+import os
+import sys
+import textwrap
+import subprocess
+
+
+minimal_egg_info = textwrap.dedent("""
+ [distutils.commands]
+ egg_info = setuptools.command.egg_info:egg_info
+
+ [distutils.setup_keywords]
+ include_package_data = setuptools.dist:assert_bool
+ install_requires = setuptools.dist:check_requirements
+ extras_require = setuptools.dist:check_extras
+ entry_points = setuptools.dist:check_entry_points
+
+ [egg_info.writers]
+ dependency_links.txt = setuptools.command.egg_info:overwrite_arg
+ entry_points.txt = setuptools.command.egg_info:write_entries
+ requires.txt = setuptools.command.egg_info:write_requirements
+ """)
+
+def ensure_egg_info():
+ if not os.path.exists('setuptools.egg-info'):
+ build_egg_info()
+
+
+def build_egg_info():
+ """
+ Build a minimal egg-info, enough to invoke egg_info
+ """
+
+ os.mkdir('setuptools.egg-info')
+ with open('setuptools.egg-info/entry_points.txt', 'w') as ep:
+ ep.write(minimal_egg_info)
+
+
+def run_egg_info():
+ subprocess.check_call([sys.executable, 'setup.py', 'egg_info'])
+
+
+if __name__ == '__main__':
+ ensure_egg_info()
+ run_egg_info()
diff --git a/docs/setuptools.txt b/docs/setuptools.txt
index c3844cf2..a34ec304 100644
--- a/docs/setuptools.txt
+++ b/docs/setuptools.txt
@@ -473,7 +473,7 @@ script called ``baz``, you might do something like this::
setup(
# other arguments here...
- entry_points = {
+ entry_points={
'console_scripts': [
'foo = my_package.some_module:main_func',
'bar = other_module:some_func',
diff --git a/docs/using.txt b/docs/using.txt
index e44847d6..bd80893d 100644
--- a/docs/using.txt
+++ b/docs/using.txt
@@ -8,3 +8,6 @@ it at the very beginning of `setup.py` like this::
from ez_setup import use_setuptools
use_setuptools()
+
+More info on `ez_setup.py` can be found at `the project home page
+<https://pypy.python.org/pypi/setuptools>`_.
diff --git a/ez_setup.py b/ez_setup.py
index a523401e..f6361e8e 100644
--- a/ez_setup.py
+++ b/ez_setup.py
@@ -36,7 +36,7 @@ try:
except ImportError:
USER_SITE = None
-DEFAULT_VERSION = "7.0"
+DEFAULT_VERSION = "8.0"
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
def _python_cmd(*args):
diff --git a/pkg_resources.py b/pkg_resources.py
index 6f21b0bf..daf7732c 100644
--- a/pkg_resources.py
+++ b/pkg_resources.py
@@ -602,6 +602,10 @@ class WorkingSet(object):
best = {}
to_activate = []
+ # Mapping of requirement to set of distributions that required it;
+ # useful for reporting info about conflicts.
+ required_by = collections.defaultdict(set)
+
while requirements:
# process dependencies breadth-first
req = requirements.pop(0)
@@ -635,9 +639,18 @@ class WorkingSet(object):
to_activate.append(dist)
if dist not in req:
# Oops, the "best" so far conflicts with a dependency
- # XXX put more info here
- raise VersionConflict(dist, req)
- requirements.extend(dist.requires(req.extras)[::-1])
+ tmpl = "%s is installed but %s is required by %s"
+ args = dist, req, list(required_by.get(req, []))
+ raise VersionConflict(tmpl % args)
+
+ # push the new requirements onto the stack
+ new_requirements = dist.requires(req.extras)[::-1]
+ requirements.extend(new_requirements)
+
+ # Register the new requirements needed by req
+ for new_requirement in new_requirements:
+ required_by[new_requirement].add(req.project_name)
+
processed[req] = True
# return list of distros to activate
diff --git a/setuptools.egg-info/dependency_links.txt b/setuptools.egg-info/dependency_links.txt
deleted file mode 100644
index b454c168..00000000
--- a/setuptools.egg-info/dependency_links.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-https://pypi.python.org/packages/source/c/certifi/certifi-1.0.1.tar.gz#md5=45f5cb94b8af9e1df0f9450a8f61b790
-https://pypi.python.org/packages/source/w/wincertstore/wincertstore-0.2.zip#md5=ae728f2f007185648d0c7a8679b361e2
diff --git a/setuptools.egg-info/entry_points.txt b/setuptools.egg-info/entry_points.txt
deleted file mode 100644
index 72a5ffe0..00000000
--- a/setuptools.egg-info/entry_points.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-[console_scripts]
-easy_install = setuptools.command.easy_install:main
-easy_install-3.4 = setuptools.command.easy_install:main
-
-[distutils.commands]
-alias = setuptools.command.alias:alias
-bdist_egg = setuptools.command.bdist_egg:bdist_egg
-bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm
-bdist_wininst = setuptools.command.bdist_wininst:bdist_wininst
-build_ext = setuptools.command.build_ext:build_ext
-build_py = setuptools.command.build_py:build_py
-develop = setuptools.command.develop:develop
-easy_install = setuptools.command.easy_install:easy_install
-egg_info = setuptools.command.egg_info:egg_info
-install = setuptools.command.install:install
-install_egg_info = setuptools.command.install_egg_info:install_egg_info
-install_lib = setuptools.command.install_lib:install_lib
-install_scripts = setuptools.command.install_scripts:install_scripts
-register = setuptools.command.register:register
-rotate = setuptools.command.rotate:rotate
-saveopts = setuptools.command.saveopts:saveopts
-sdist = setuptools.command.sdist:sdist
-setopt = setuptools.command.setopt:setopt
-test = setuptools.command.test:test
-upload_docs = setuptools.command.upload_docs:upload_docs
-
-[distutils.setup_keywords]
-convert_2to3_doctests = setuptools.dist:assert_string_list
-dependency_links = setuptools.dist:assert_string_list
-eager_resources = setuptools.dist:assert_string_list
-entry_points = setuptools.dist:check_entry_points
-exclude_package_data = setuptools.dist:check_package_data
-extras_require = setuptools.dist:check_extras
-include_package_data = setuptools.dist:assert_bool
-install_requires = setuptools.dist:check_requirements
-namespace_packages = setuptools.dist:check_nsp
-package_data = setuptools.dist:check_package_data
-packages = setuptools.dist:check_packages
-setup_requires = setuptools.dist:check_requirements
-test_loader = setuptools.dist:check_importable
-test_runner = setuptools.dist:check_importable
-test_suite = setuptools.dist:check_test_suite
-tests_require = setuptools.dist:check_requirements
-use_2to3 = setuptools.dist:assert_bool
-use_2to3_exclude_fixers = setuptools.dist:assert_string_list
-use_2to3_fixers = setuptools.dist:assert_string_list
-zip_safe = setuptools.dist:assert_bool
-
-[egg_info.writers]
-PKG-INFO = setuptools.command.egg_info:write_pkg_info
-dependency_links.txt = setuptools.command.egg_info:overwrite_arg
-depends.txt = setuptools.command.egg_info:warn_depends_obsolete
-eager_resources.txt = setuptools.command.egg_info:overwrite_arg
-entry_points.txt = setuptools.command.egg_info:write_entries
-namespace_packages.txt = setuptools.command.egg_info:overwrite_arg
-requires.txt = setuptools.command.egg_info:write_requirements
-top_level.txt = setuptools.command.egg_info:write_toplevel_names
-
-[setuptools.file_finders]
-svn_cvs = setuptools.command.sdist:_default_revctrl
-
-[setuptools.installation]
-eggsecutable = setuptools.command.easy_install:bootstrap
-
diff --git a/setuptools.egg-info/requires.txt b/setuptools.egg-info/requires.txt
deleted file mode 100644
index f3f4471e..00000000
--- a/setuptools.egg-info/requires.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-packaging>=14.2,<15.0.dev0
-
-[certs]
-certifi==1.0.1
-
-[ssl:sys_platform=='win32']
-wincertstore==0.2
diff --git a/setuptools/__init__.py b/setuptools/__init__.py
index d99ab2a6..ca025c30 100644
--- a/setuptools/__init__.py
+++ b/setuptools/__init__.py
@@ -139,7 +139,7 @@ def findall(dir = os.curdir):
(relative to 'dir').
"""
all_files = []
- for base, dirs, files in os.walk(dir):
+ for base, dirs, files in os.walk(dir, followlinks=True):
if base==os.curdir or base.startswith(os.curdir+os.sep):
base = base[2:]
if base:
@@ -148,7 +148,3 @@ def findall(dir = os.curdir):
return all_files
distutils.filelist.findall = findall # fix findall bug in distutils.
-
-# sys.dont_write_bytecode was introduced in Python 2.6.
-_dont_write_bytecode = getattr(sys, 'dont_write_bytecode',
- bool(os.environ.get("PYTHONDONTWRITEBYTECODE")))
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
index 68548272..2e00b996 100755
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -35,7 +35,7 @@ import warnings
import site
import struct
-from setuptools import Command, _dont_write_bytecode
+from setuptools import Command
from setuptools.sandbox import run_setup
from setuptools.py31compat import get_path, get_config_vars
from setuptools.command import setopt
@@ -1152,7 +1152,7 @@ See the setuptools documentation for the "develop" command for more info.
chmod(f, mode)
def byte_compile(self, to_compile):
- if _dont_write_bytecode:
+ if sys.dont_write_bytecode:
self.warn('byte-compiling is disabled, skipping.')
return
diff --git a/setuptools/command/install_egg_info.py b/setuptools/command/install_egg_info.py
index 992709f1..fd0f118b 100755
--- a/setuptools/command/install_egg_info.py
+++ b/setuptools/command/install_egg_info.py
@@ -27,7 +27,7 @@ class install_egg_info(Command):
).egg_name() + '.egg-info'
self.source = ei_cmd.egg_info
self.target = os.path.join(self.install_dir, basename)
- self.outputs = []
+ self.outputs = [self.target]
def run(self):
self.run_command('egg_info')
diff --git a/setuptools/dist.py b/setuptools/dist.py
index a3a37ee4..e44796fd 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -22,6 +22,7 @@ except ImportError:
from setuptools.depends import Require
from setuptools.compat import basestring, PY2
+from setuptools import windows_support
import pkg_resources
@@ -334,6 +335,21 @@ class Distribution(_Distribution):
else:
self.convert_2to3_doctests = []
+ def get_egg_cache_dir(self):
+ egg_cache_dir = os.path.join(os.curdir, '.eggs')
+ if not os.path.exists(egg_cache_dir):
+ os.mkdir(egg_cache_dir)
+ windows_support.hide_file(egg_cache_dir)
+ readme_txt_filename = os.path.join(egg_cache_dir, 'README.txt')
+ with open(readme_txt_filename, 'w') as f:
+ f.write('This directory contains eggs that were downloaded '
+ 'by setuptools to build, test, and run plug-ins.\n\n')
+ f.write('This directory caches those eggs to prevent '
+ 'repeated downloads.\n\n')
+ f.write('However, it is safe to delete this directory.\n\n')
+
+ return egg_cache_dir
+
def fetch_build_egg(self, req):
"""Fetch an egg needed for building"""
@@ -357,8 +373,9 @@ class Distribution(_Distribution):
if 'find_links' in opts:
links = opts['find_links'][1].split() + links
opts['find_links'] = ('setup', links)
+ install_dir = self.get_egg_cache_dir()
cmd = easy_install(
- dist, args=["x"], install_dir=os.curdir, exclude_scripts=True,
+ dist, args=["x"], install_dir=install_dir, exclude_scripts=True,
always_copy=False, build_directory=None, editable=False,
upgrade=False, multi_version=True, no_report=True, user=False
)
diff --git a/setuptools/svn_utils.py b/setuptools/svn_utils.py
index dadb682a..6502fc98 100644
--- a/setuptools/svn_utils.py
+++ b/setuptools/svn_utils.py
@@ -302,7 +302,7 @@ class SvnInfo(object):
self._externals = None
def get_revision(self):
- 'Retrieve the directory revision informatino using svnversion'
+ 'Retrieve the directory revision information using svnversion'
code, data = _run_command(['svnversion', '-c', self.path])
if code:
log.warn("svnversion failed")
diff --git a/setuptools/tests/environment.py b/setuptools/tests/environment.py
index 476d280a..c8d0e669 100644
--- a/setuptools/tests/environment.py
+++ b/setuptools/tests/environment.py
@@ -10,57 +10,6 @@ import unicodedata
from subprocess import Popen as _Popen, PIPE as _PIPE
-def _extract(self, member, path=None, pwd=None):
- """for zipfile py2.5 borrowed from cpython"""
- if not isinstance(member, zipfile.ZipInfo):
- member = self.getinfo(member)
-
- if path is None:
- path = os.getcwd()
-
- return _extract_member(self, member, path, pwd)
-
-
-def _extract_from_zip(self, name, dest_path):
- dest_file = open(dest_path, 'wb')
- try:
- dest_file.write(self.read(name))
- finally:
- dest_file.close()
-
-
-def _extract_member(self, member, targetpath, pwd):
- """for zipfile py2.5 borrowed from cpython"""
- # build the destination pathname, replacing
- # forward slashes to platform specific separators.
- # Strip trailing path separator, unless it represents the root.
- if (targetpath[-1:] in (os.path.sep, os.path.altsep)
- and len(os.path.splitdrive(targetpath)[1]) > 1):
- targetpath = targetpath[:-1]
-
- # don't include leading "/" from file name if present
- if member.filename[0] == '/':
- targetpath = os.path.join(targetpath, member.filename[1:])
- else:
- targetpath = os.path.join(targetpath, member.filename)
-
- targetpath = os.path.normpath(targetpath)
-
- # Create all upper directories if necessary.
- upperdirs = os.path.dirname(targetpath)
- if upperdirs and not os.path.exists(upperdirs):
- os.makedirs(upperdirs)
-
- if member.filename[-1] == '/':
- if not os.path.isdir(targetpath):
- os.mkdir(targetpath)
- return targetpath
-
- _extract_from_zip(self, member.filename, targetpath)
-
- return targetpath
-
-
def _remove_dir(target):
#on windows this seems to a problem
@@ -92,7 +41,7 @@ class ZippedEnvironment(unittest.TestCase):
try:
zip_file = zipfile.ZipFile(self.datafile)
for files in zip_file.namelist():
- _extract(zip_file, files, self.temp_dir)
+ zip_file.extract(files, self.temp_dir)
finally:
if zip_file:
zip_file.close()
@@ -147,10 +96,13 @@ def run_setup_py(cmd, pypath=None, path=None,
cmd = [sys.executable, "setup.py"] + list(cmd)
- #regarding the shell argument, see: http://bugs.python.org/issue8557
+ # http://bugs.python.org/issue8557
+ shell = sys.platform == 'win32'
+
try:
- proc = _Popen(cmd, stdout=_PIPE, stderr=_PIPE,
- shell=(sys.platform == 'win32'), env=env)
+ proc = _Popen(
+ cmd, stdout=_PIPE, stderr=_PIPE, shell=shell, env=env,
+ )
data = proc.communicate()[data_stream]
except OSError:
@@ -158,7 +110,8 @@ def run_setup_py(cmd, pypath=None, path=None,
#decode the console string if needed
if hasattr(data, "decode"):
- data = data.decode() # should use the preffered encoding
+ # use the default encoding
+ data = data.decode()
data = unicodedata.normalize('NFC', data)
#communciate calls wait()
diff --git a/setuptools/version.py b/setuptools/version.py
index 29524eba..4ca9d5df 100644
--- a/setuptools/version.py
+++ b/setuptools/version.py
@@ -1 +1 @@
-__version__ = '7.0'
+__version__ = '8.0'
diff --git a/setuptools/windows_support.py b/setuptools/windows_support.py
new file mode 100644
index 00000000..cb977cff
--- /dev/null
+++ b/setuptools/windows_support.py
@@ -0,0 +1,29 @@
+import platform
+import ctypes
+
+
+def windows_only(func):
+ if platform.system() != 'Windows':
+ return lambda *args, **kwargs: None
+ return func
+
+
+@windows_only
+def hide_file(path):
+ """
+ Set the hidden attribute on a file or directory.
+
+ From http://stackoverflow.com/questions/19622133/
+
+ `path` must be text.
+ """
+ __import__('ctypes.wintypes')
+ SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW
+ SetFileAttributes.argtypes = ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD
+ SetFileAttributes.restype = ctypes.wintypes.BOOL
+
+ FILE_ATTRIBUTE_HIDDEN = 0x02
+
+ ret = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN)
+ if not ret:
+ raise ctypes.WinError()
diff --git a/tox.ini b/tox.ini
index 06421a73..1ac46202 100644
--- a/tox.ini
+++ b/tox.ini
@@ -2,4 +2,4 @@
envlist = py26,py27,py31,py32,py33,py34
[testenv]
deps=pytest
-commands=py.test
+commands=py.test {posargs}