Hello community,

here is the log from the commit of package python3-setuptools for 
openSUSE:Factory checked in at 2015-12-16 17:42:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python3-setuptools (Old)
 and      /work/SRC/openSUSE:Factory/.python3-setuptools.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python3-setuptools"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python3-setuptools/python3-setuptools.changes    
2015-12-01 09:17:06.000000000 +0100
+++ 
/work/SRC/openSUSE:Factory/.python3-setuptools.new/python3-setuptools.changes   
    2015-12-16 17:42:04.000000000 +0100
@@ -1,0 +2,24 @@
+Sun Dec 13 20:22:01 UTC 2015 - [email protected]
+
+- update to version 18.8.1:
+  * Issue #440: Prevent infinite recursion when a SandboxViolation or
+    other UnpickleableException occurs in a sandbox context with
+    setuptools hidden. Fixes regression introduced in Setuptools 12.0.
+
+- changes from version 18.8:
+  * Deprecated ``egg_info.get_pkg_info_revision``.
+  * Issue #471: Don't rely on repr for an HTML attribute value in
+    package_index.
+  * Issue #419: Avoid errors in FileMetadata when the metadata directory
+    is broken.
+  * Issue #472: Remove deprecated use of 'U' in mode parameter
+    when opening files.
+
+-------------------------------------------------------------------
+Wed Dec  2 07:46:52 UTC 2015 - [email protected]
+
+- update to version 18.7.1:
+  * Issue #469: Refactored logic for Issue #419 fix to re-use metadata
+    loading from Provider.
+
+-------------------------------------------------------------------

Old:
----
  setuptools-18.7.tar.gz

New:
----
  setuptools-18.8.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python3-setuptools.spec ++++++
--- /var/tmp/diff_new_pack.E4Lmnh/_old  2015-12-16 17:42:06.000000000 +0100
+++ /var/tmp/diff_new_pack.E4Lmnh/_new  2015-12-16 17:42:06.000000000 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           python3-setuptools
-Version:        18.7
+Version:        18.8.1
 Release:        0
 Url:            http://pypi.python.org/pypi/setuptools
 Summary:        Easily download, build, install, upgrade, and uninstall Python 
packages

++++++ setuptools-18.7.tar.gz -> setuptools-18.8.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/CHANGES.txt 
new/setuptools-18.8.1/CHANGES.txt
--- old/setuptools-18.7/CHANGES.txt     2015-11-28 20:17:50.000000000 +0100
+++ new/setuptools-18.8.1/CHANGES.txt   2015-12-13 16:47:39.000000000 +0100
@@ -3,6 +3,34 @@
 =======
 
 
+------
+18.8.1
+------
+
+* Issue #440: Prevent infinite recursion when a SandboxViolation
+  or other UnpickleableException occurs in a sandbox context
+  with setuptools hidden. Fixes regression introduced in Setuptools
+  12.0.
+
+----
+18.8
+----
+
+* Deprecated ``egg_info.get_pkg_info_revision``.
+* Issue #471: Don't rely on repr for an HTML attribute value in
+  package_index.
+* Issue #419: Avoid errors in FileMetadata when the metadata directory
+  is broken.
+* Issue #472: Remove deprecated use of 'U' in mode parameter
+  when opening files.
+
+------
+18.7.1
+------
+
+* Issue #469: Refactored logic for Issue #419 fix to re-use metadata
+  loading from Provider.
+
 ----
 18.7
 ----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/PKG-INFO 
new/setuptools-18.8.1/PKG-INFO
--- old/setuptools-18.7/PKG-INFO        2015-11-28 23:57:49.000000000 +0100
+++ new/setuptools-18.8.1/PKG-INFO      2015-12-13 17:57:44.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: setuptools
-Version: 18.7
+Version: 18.8.1
 Summary: Easily download, build, install, upgrade, and uninstall Python 
packages
 Home-page: https://bitbucket.org/pypa/setuptools
 Author: Python Packaging Authority
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/ez_setup.py 
new/setuptools-18.8.1/ez_setup.py
--- old/setuptools-18.7/ez_setup.py     2015-11-28 23:57:43.000000000 +0100
+++ new/setuptools-18.8.1/ez_setup.py   2015-12-13 17:57:40.000000000 +0100
@@ -30,7 +30,7 @@
 except ImportError:
     USER_SITE = None
 
-DEFAULT_VERSION = "18.7"
+DEFAULT_VERSION = "18.8.1"
 DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/";
 DEFAULT_SAVE_DIR = os.curdir
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/pkg_resources/__init__.py 
new/setuptools-18.8.1/pkg_resources/__init__.py
--- old/setuptools-18.7/pkg_resources/__init__.py       2015-11-28 
20:13:44.000000000 +0100
+++ new/setuptools-18.8.1/pkg_resources/__init__.py     2015-12-09 
08:34:40.000000000 +0100
@@ -37,6 +37,7 @@
 import email.parser
 import tempfile
 import textwrap
+import itertools
 from pkgutil import get_importer
 
 try:
@@ -53,6 +54,8 @@
 
 if PY2:
     from urlparse import urlparse, urlunparse
+    filter = itertools.ifilter
+    map = itertools.imap
 
 if PY3:
     string_types = str,
@@ -2014,11 +2017,11 @@
         self.path = path
 
     def has_metadata(self, name):
-        return name=='PKG-INFO'
+        return name=='PKG-INFO' and os.path.isfile(self.path)
 
     def get_metadata(self, name):
         if name=='PKG-INFO':
-            with open(self.path,'rU') as f:
+            with io.open(self.path, encoding='utf-8') as f:
                 metadata = f.read()
             return metadata
         raise KeyError("No metadata except PKG-INFO is available")
@@ -2504,7 +2507,6 @@
     @classmethod
     def from_location(cls, location, basename, metadata=None, **kw):
         project_name, version, py_version, platform = [None]*4
-        dist_path = os.path.join(location, basename)
         basename, ext = os.path.splitext(basename)
         if ext.lower() in _distributionImpl:
             cls = _distributionImpl[ext.lower()]
@@ -2514,16 +2516,13 @@
                 project_name, version, py_version, platform = match.group(
                     'name', 'ver', 'pyver', 'plat'
                 )
-
-            version = cls._version_from_metadata(dist_path) or version
         return cls(
             location, metadata, project_name=project_name, version=version,
             py_version=py_version, platform=platform, **kw
-        )
+        )._reload_version()
 
-    @staticmethod
-    def _version_from_metadata(dist_path):
-        pass
+    def _reload_version(self):
+        return self
 
     @property
     def hashcmp(self):
@@ -2821,8 +2820,7 @@
 
 class EggInfoDistribution(Distribution):
 
-    @staticmethod
-    def _version_from_metadata(dist_path):
+    def _reload_version(self):
         """
         Packages installed by distutils (e.g. numpy or scipy),
         which uses an old safe_version, and so
@@ -2834,13 +2832,10 @@
         take an extra step and try to get the version number from
         the metadata file itself instead of the filename.
         """
-        if not os.path.isfile(dist_path):
-            return
-        try:
-            with open(dist_path) as strm:
-                return _version_from_file(strm)
-        except IOError:
-            pass
+        md_version = _version_from_file(self._get_metadata(self.PKG_INFO))
+        if md_version:
+            self._version = md_version
+        return self
 
 
 class DistInfoDistribution(Distribution):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/setuptools-18.7/pkg_resources/tests/test_pkg_resources.py 
new/setuptools-18.8.1/pkg_resources/tests/test_pkg_resources.py
--- old/setuptools-18.7/pkg_resources/tests/test_pkg_resources.py       
2015-11-28 20:13:44.000000000 +0100
+++ new/setuptools-18.8.1/pkg_resources/tests/test_pkg_resources.py     
2015-12-01 18:10:47.000000000 +0100
@@ -1,3 +1,6 @@
+# coding: utf-8
+from __future__ import unicode_literals
+
 import sys
 import tempfile
 import os
@@ -144,7 +147,8 @@
         Create a foo package installed (distutils-style) to env.paths['lib']
         as version.
         """
-        attrs = dict(name='foo', version=version)
+        ld = "This package has unicode metadata! ❄"
+        attrs = dict(name='foo', version=version, long_description=ld)
         dist = distutils.dist.Distribution(attrs)
         iei_cmd = distutils.command.install_egg_info.install_egg_info(dist)
         iei_cmd.initialize_options()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setup.cfg 
new/setuptools-18.8.1/setup.cfg
--- old/setuptools-18.7/setup.cfg       2015-11-28 23:57:49.000000000 +0100
+++ new/setuptools-18.8.1/setup.cfg     2015-12-13 17:57:44.000000000 +0100
@@ -1,7 +1,7 @@
 [egg_info]
 tag_build = 
-tag_svn_revision = 0
 tag_date = 0
+tag_svn_revision = 0
 
 [aliases]
 release = egg_info -RDb ''
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setup.py 
new/setuptools-18.8.1/setup.py
--- old/setuptools-18.7/setup.py        2015-11-28 20:13:40.000000000 +0100
+++ new/setuptools-18.8.1/setup.py      2015-12-01 19:05:27.000000000 +0100
@@ -159,7 +159,7 @@
     scripts=[],
     tests_require=[
         'setuptools[ssl]',
-        'pytest',
+        'pytest>=2.8',
     ] + (['mock'] if sys.version_info[:2] < (3, 3) else []),
     setup_requires=[
     ] + sphinx + pytest_runner,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/command/build_py.py 
new/setuptools-18.8.1/setuptools/command/build_py.py
--- old/setuptools-18.7/setuptools/command/build_py.py  2015-11-28 
04:43:42.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/command/build_py.py        2015-12-09 
09:59:21.000000000 +0100
@@ -2,9 +2,13 @@
 from distutils.util import convert_path
 import distutils.command.build_py as orig
 import os
-import sys
 import fnmatch
 import textwrap
+import io
+import distutils.errors
+import collections
+import itertools
+
 
 try:
     from setuptools.lib2to3_ex import Mixin2to3
@@ -157,17 +161,15 @@
         else:
             return init_py
 
-        f = open(init_py, 'rbU')
-        if 'declare_namespace'.encode() not in f.read():
-            from distutils.errors import DistutilsError
-
-            raise DistutilsError(
+        with io.open(init_py, 'rb') as f:
+            contents = f.read()
+        if b'declare_namespace' not in contents:
+            raise distutils.errors.DistutilsError(
                 "Namespace package problem: %s is a namespace package, but "
                 "its\n__init__.py does not call declare_namespace()! Please "
                 'fix it.\n(See the setuptools manual under '
                 '"Namespace Packages" for details.)\n"' % (package,)
             )
-        f.close()
         return init_py
 
     def initialize_options(self):
@@ -182,20 +184,25 @@
 
     def exclude_data_files(self, package, src_dir, files):
         """Filter filenames for package's data files in 'src_dir'"""
-        globs = (self.exclude_package_data.get('', [])
-                 + self.exclude_package_data.get(package, []))
-        bad = []
-        for pattern in globs:
-            bad.extend(
-                fnmatch.filter(
-                    files, os.path.join(src_dir, convert_path(pattern))
-                )
+        globs = (
+            self.exclude_package_data.get('', [])
+            + self.exclude_package_data.get(package, [])
+        )
+        bad = set(
+            item
+            for pattern in globs
+            for item in fnmatch.filter(
+                files,
+                os.path.join(src_dir, convert_path(pattern)),
             )
-        bad = dict.fromkeys(bad)
-        seen = {}
+        )
+        seen = collections.defaultdict(itertools.count)
         return [
-            f for f in files if f not in bad
-            and f not in seen and seen.setdefault(f, 1)  # ditch dupes
+            fn
+            for fn in files
+            if fn not in bad
+            # ditch dupes
+            and not next(seen[fn])
         ]
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/command/develop.py 
new/setuptools-18.8.1/setuptools/command/develop.py
--- old/setuptools-18.7/setuptools/command/develop.py   2015-11-28 
20:13:40.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/command/develop.py 2015-12-11 
16:06:26.000000000 +0100
@@ -3,6 +3,7 @@
 from distutils.errors import DistutilsError, DistutilsOptionError
 import os
 import glob
+import io
 
 from pkg_resources import Distribution, PathMetadata, normalize_path
 from setuptools.command.easy_install import easy_install
@@ -53,8 +54,8 @@
         # pick up setup-dir .egg files only: no .egg-info
         self.package_index.scan(glob.glob('*.egg'))
 
-        self.egg_link = os.path.join(self.install_dir, ei.egg_name +
-                                     '.egg-link')
+        egg_link_fn = ei.egg_name + '.egg-link'
+        self.egg_link = os.path.join(self.install_dir, egg_link_fn)
         self.egg_base = ei.egg_base
         if self.egg_path is None:
             self.egg_path = os.path.abspath(ei.egg_base)
@@ -124,9 +125,8 @@
         # create an .egg-link in the installation dir, pointing to our egg
         log.info("Creating %s (link to %s)", self.egg_link, self.egg_base)
         if not self.dry_run:
-            f = open(self.egg_link, "w")
-            f.write(self.egg_path + "\n" + self.setup_path)
-            f.close()
+            with open(self.egg_link, "w") as f:
+                f.write(self.egg_path + "\n" + self.setup_path)
         # postprocess the installed distro, fixing up .pth, installing scripts,
         # and handling requirements
         self.process_distribution(None, self.dist, not self.no_deps)
@@ -163,9 +163,8 @@
         for script_name in self.distribution.scripts or []:
             script_path = os.path.abspath(convert_path(script_name))
             script_name = os.path.basename(script_path)
-            f = open(script_path, 'rU')
-            script_text = f.read()
-            f.close()
+            with io.open(script_path) as strm:
+                script_text = strm.read()
             self.install_script(dist, script_name, script_text, script_path)
 
     def install_wrapper_scripts(self, dist):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/command/easy_install.py 
new/setuptools-18.8.1/setuptools/command/easy_install.py
--- old/setuptools-18.7/setuptools/command/easy_install.py      2015-11-28 
20:13:40.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/command/easy_install.py    2015-12-02 
04:00:35.000000000 +0100
@@ -772,8 +772,8 @@
         is_script = is_python_script(script_text, script_name)
 
         if is_script:
-            script_text = (ScriptWriter.get_header(script_text) +
-                           self._load_template(dev_path) % locals())
+            body = self._load_template(dev_path) % locals()
+            script_text = ScriptWriter.get_header(script_text) + body
         self.write_script(script_name, _to_ascii(script_text), 'b')
 
     @staticmethod
@@ -805,9 +805,8 @@
             ensure_directory(target)
             if os.path.exists(target):
                 os.unlink(target)
-            f = open(target, "w" + mode)
-            f.write(contents)
-            f.close()
+            with open(target, "w" + mode) as f:
+                f.write(contents)
             chmod(target, 0o777 - mask)
 
     def install_eggs(self, spec, dist_filename, tmpdir):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/command/egg_info.py 
new/setuptools-18.8.1/setuptools/command/egg_info.py
--- old/setuptools-18.7/setuptools/command/egg_info.py  2015-11-28 
04:43:42.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/command/egg_info.py        2015-12-09 
10:00:56.000000000 +0100
@@ -10,16 +10,17 @@
 import os
 import re
 import sys
+import io
+import warnings
+import time
 
-try:
-    from setuptools_svn import svn_utils
-except ImportError:
-    pass
+from setuptools.compat import basestring, PY3, StringIO
 
 from setuptools import Command
 from setuptools.command.sdist import sdist
-from setuptools.compat import basestring, PY3, StringIO
 from setuptools.command.sdist import walk_revctrl
+from setuptools.command.setopt import edit_config
+from setuptools.command import bdist_egg
 from pkg_resources import (
     parse_requirements, safe_name, parse_version,
     safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename)
@@ -27,6 +28,12 @@
 
 from pkg_resources import packaging
 
+try:
+    from setuptools_svn import svn_utils
+except ImportError:
+    pass
+
+
 class egg_info(Command):
     description = "create a distribution's .egg-info directory"
 
@@ -58,8 +65,6 @@
         self.vtags = None
 
     def save_version_info(self, filename):
-        from setuptools.command.setopt import edit_config
-
         values = dict(
             egg_info=dict(
                 tag_svn_revision=0,
@@ -184,12 +189,8 @@
         if self.tag_build:
             version += self.tag_build
         if self.tag_svn_revision:
-            rev = self.get_svn_revision()
-            if rev:     # is 0 if it's not an svn working copy
-                version += '-r%s' % rev
+            version += '-r%s' % self.get_svn_revision()
         if self.tag_date:
-            import time
-
             version += time.strftime("-%Y%m%d")
         return version
 
@@ -390,7 +391,6 @@
             metadata.name, metadata.version = oldname, oldver
 
         safe = getattr(cmd.distribution, 'zip_safe', None)
-        from setuptools.command import bdist_egg
 
         bdist_egg.write_safety_flag(cmd.egg_info, safe)
 
@@ -467,14 +467,15 @@
 
 
 def get_pkg_info_revision():
-    # See if we can get a -r### off of PKG-INFO, in case this is an sdist of
-    # a subversion revision
-    #
+    """
+    Get a -r### off of PKG-INFO Version in case this is an sdist of
+    a subversion revision.
+    """
+    warnings.warn("get_pkg_info_revision is deprecated.", DeprecationWarning)
     if os.path.exists('PKG-INFO'):
-        f = open('PKG-INFO', 'rU')
-        for line in f:
-            match = re.match(r"Version:.*-r(\d+)\s*$", line)
-            if match:
-                return int(match.group(1))
-        f.close()
+        with io.open('PKG-INFO') as f:
+            for line in f:
+                match = re.match(r"Version:.*-r(\d+)\s*$", line)
+                if match:
+                    return int(match.group(1))
     return 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/command/sdist.py 
new/setuptools-18.8.1/setuptools/command/sdist.py
--- old/setuptools-18.7/setuptools/command/sdist.py     2015-11-28 
04:43:42.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/command/sdist.py   2015-12-09 
09:59:21.000000000 +0100
@@ -3,6 +3,7 @@
 import distutils.command.sdist as orig
 import os
 import sys
+import io
 
 from setuptools.compat import PY3
 from setuptools.utils import cs_path_exists
@@ -166,11 +167,8 @@
         if not os.path.isfile(self.manifest):
             return False
 
-        fp = open(self.manifest, 'rbU')
-        try:
+        with io.open(self.manifest, 'rb') as fp:
             first_line = fp.readline()
-        finally:
-            fp.close()
         return (first_line !=
                 '# file GENERATED by distutils, do NOT edit\n'.encode())
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/compat.py 
new/setuptools-18.8.1/setuptools/compat.py
--- old/setuptools-18.7/setuptools/compat.py    2015-11-28 04:43:42.000000000 
+0100
+++ new/setuptools-18.8.1/setuptools/compat.py  2015-12-11 16:27:39.000000000 
+0100
@@ -29,6 +29,8 @@
     from urllib2 import urlopen, HTTPError, URLError, unquote, splituser
     from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit
     filterfalse = itertools.ifilterfalse
+    filter = itertools.ifilter
+    map = itertools.imap
 
     exec("""def reraise(tp, value, tb=None):
     raise tp, value, tb""")
@@ -59,6 +61,8 @@
         urlunsplit, splittag,
     )
     filterfalse = itertools.filterfalse
+    filter = filter
+    map = map
 
     def reraise(tp, value, tb=None):
         if value.__traceback__ is not tb:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/package_index.py 
new/setuptools-18.8.1/setuptools/package_index.py
--- old/setuptools-18.7/setuptools/package_index.py     2015-11-28 
04:43:42.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/package_index.py   2015-12-11 
16:37:00.000000000 +0100
@@ -6,6 +6,7 @@
 import socket
 import base64
 import hashlib
+import itertools
 from functools import wraps
 
 from pkg_resources import (
@@ -16,11 +17,11 @@
 from setuptools import ssl_support
 from distutils import log
 from distutils.errors import DistutilsError
-from setuptools.compat import (urllib2, httplib, StringIO, HTTPError,
-                               urlparse, urlunparse, unquote, splituser,
-                               url2pathname, name2codepoint,
-                               unichr, urljoin, urlsplit, urlunsplit,
-                               ConfigParser)
+from setuptools.compat import (
+    urllib2, httplib, StringIO, HTTPError, urlparse, urlunparse, unquote,
+    splituser, url2pathname, name2codepoint, unichr, urljoin, urlsplit,
+    urlunsplit, ConfigParser, filter, map,
+)
 from setuptools.compat import filterfalse
 from fnmatch import translate
 from setuptools.py26compat import strip_fragment
@@ -352,20 +353,30 @@
             self.warn(msg, url)
 
     def scan_egg_links(self, search_path):
-        for item in search_path:
-            if os.path.isdir(item):
-                for entry in os.listdir(item):
-                    if entry.endswith('.egg-link'):
-                        self.scan_egg_link(item, entry)
+        dirs = filter(os.path.isdir, search_path)
+        egg_links = (
+            (path, entry)
+            for path in dirs
+            for entry in os.listdir(path)
+            if entry.endswith('.egg-link')
+        )
+        list(itertools.starmap(self.scan_egg_link, egg_links))
 
     def scan_egg_link(self, path, entry):
-        lines = [_f for _f in map(str.strip,
-                                  open(os.path.join(path, entry))) if _f]
-        if len(lines)==2:
-            for dist in find_distributions(os.path.join(path, lines[0])):
-                dist.location = os.path.join(path, *lines)
-                dist.precedence = SOURCE_DIST
-                self.add(dist)
+        with open(os.path.join(path, entry)) as raw_lines:
+            # filter non-empty lines
+            lines = list(filter(None, map(str.strip, raw_lines)))
+
+        if len(lines) != 2:
+            # format is not recognized; punt
+            return
+
+        egg_path, setup_path = lines
+
+        for dist in find_distributions(os.path.join(path, egg_path)):
+            dist.location = os.path.join(path, *lines)
+            dist.precedence = SOURCE_DIST
+            self.add(dist)
 
     def process_index(self,url,page):
         """Process the contents of a PyPI page"""
@@ -1031,16 +1042,18 @@
     elif path.endswith('/') and os.path.isdir(filename):
         files = []
         for f in os.listdir(filename):
-            if f=='index.html':
-                with open(os.path.join(filename,f),'r') as fp:
+            filepath = os.path.join(filename, f)
+            if f == 'index.html':
+                with open(filepath, 'r') as fp:
                     body = fp.read()
                 break
-            elif os.path.isdir(os.path.join(filename,f)):
-                f+='/'
-            files.append("<a href=%r>%s</a>" % (f,f))
+            elif os.path.isdir(filepath):
+                f += '/'
+            files.append('<a href="{name}">{name}</a>'.format(name=f))
         else:
-            body = ("<html><head><title>%s</title>" % url) + \
-                "</head><body>%s</body></html>" % '\n'.join(files)
+            tmpl = ("<html><head><title>{url}</title>"
+                "</head><body>{files}</body></html>")
+            body = tmpl.format(url=url, files='\n'.join(files))
         status, message = 200, "OK"
     else:
         status, message, body = 404, "Path not found", "Not found"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/sandbox.py 
new/setuptools-18.8.1/setuptools/sandbox.py
--- old/setuptools-18.7/setuptools/sandbox.py   2015-11-28 04:43:42.000000000 
+0100
+++ new/setuptools-18.8.1/setuptools/sandbox.py 2015-12-13 17:18:24.000000000 
+0100
@@ -98,8 +98,8 @@
     """
     An exception representing another Exception that could not be pickled.
     """
-    @classmethod
-    def dump(cls, type, exc):
+    @staticmethod
+    def dump(type, exc):
         """
         Always return a dumped (pickled) type and exc. If exc can't be pickled,
         wrap it in UnpickleableException first.
@@ -107,6 +107,8 @@
         try:
             return pickle.dumps(type), pickle.dumps(exc)
         except Exception:
+            # get UnpickleableException inside the sandbox
+            from setuptools.sandbox import UnpickleableException as cls
             return cls.dump(cls, cls(repr(exc)))
 
 
@@ -382,6 +384,7 @@
         AbstractSandbox.__init__(self)
 
     def _violation(self, operation, *args, **kw):
+        from setuptools.sandbox import SandboxViolation
         raise SandboxViolation(operation, args, kw)
 
     if _file:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/tests/__init__.py 
new/setuptools-18.8.1/setuptools/tests/__init__.py
--- old/setuptools-18.7/setuptools/tests/__init__.py    2015-11-28 
04:43:42.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/tests/__init__.py  2015-12-01 
20:04:24.000000000 +0100
@@ -16,6 +16,11 @@
 from setuptools import Feature
 from setuptools.depends import Require
 
+c_type = os.environ.get("LC_CTYPE", os.environ.get("LC_ALL"))
+is_ascii = c_type in ("C", "POSIX")
+fail_on_ascii = pytest.mark.xfail(is_ascii, reason="Test fails in this locale")
+
+
 def makeSetup(**args):
     """Return distribution from 'setup(**args)', without executing commands"""
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/setuptools-18.7/setuptools/tests/test_easy_install.py 
new/setuptools-18.8.1/setuptools/tests/test_easy_install.py
--- old/setuptools-18.7/setuptools/tests/test_easy_install.py   2015-11-28 
04:43:42.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/tests/test_easy_install.py 2015-12-01 
20:04:42.000000000 +0100
@@ -35,7 +35,7 @@
 import pkg_resources
 
 from .py26compat import tarfile_open
-from . import contexts
+from . import contexts, is_ascii
 from .textwrap import DALS
 
 
@@ -431,7 +431,7 @@
         assert actual == expected
 
     @pytest.mark.xfail(
-        compat.PY3 and os.environ.get("LC_CTYPE") in ("C", "POSIX"),
+        compat.PY3 and is_ascii,
         reason="Test fails in this locale on Python 3"
     )
     @mock.patch.dict(sys.modules, java=mock.Mock(lang=mock.Mock(System=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/tests/test_sandbox.py 
new/setuptools-18.8.1/setuptools/tests/test_sandbox.py
--- old/setuptools-18.7/setuptools/tests/test_sandbox.py        2015-11-28 
04:43:42.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/tests/test_sandbox.py      2015-12-13 
17:12:13.000000000 +0100
@@ -100,3 +100,42 @@
             saved_exc.resume()
 
         assert str(caught.value) == "CantPickleThis('detail',)"
+
+    def test_unpickleable_exception_when_hiding_setuptools(self):
+        """
+        As revealed in #440, an infinite recursion can occur if an unpickleable
+        exception while setuptools is hidden. Ensure this doesn't happen.
+        """
+        class ExceptionUnderTest(Exception):
+            """
+            An unpickleable exception (not in globals).
+            """
+
+        with pytest.raises(setuptools.sandbox.UnpickleableException) as caught:
+            with setuptools.sandbox.save_modules():
+                setuptools.sandbox.hide_setuptools()
+                raise ExceptionUnderTest()
+
+        msg, = caught.value.args
+        assert msg == 'ExceptionUnderTest()'
+
+    def test_sandbox_violation_raised_hiding_setuptools(self, tmpdir):
+        """
+        When in a sandbox with setuptools hidden, a SandboxViolation
+        should reflect a proper exception and not be wrapped in
+        an UnpickleableException.
+        """
+        def write_file():
+            "Trigger a SandboxViolation by writing outside the sandbox"
+            with open('/etc/foo', 'w'):
+                pass
+        sandbox = DirectorySandbox(str(tmpdir))
+        with pytest.raises(setuptools.sandbox.SandboxViolation) as caught:
+            with setuptools.sandbox.save_modules():
+                setuptools.sandbox.hide_setuptools()
+                sandbox.run(write_file)
+
+        cmd, args, kwargs = caught.value.args
+        assert cmd == 'open'
+        assert args == ('/etc/foo', 'w')
+        assert kwargs == {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/tests/test_sdist.py 
new/setuptools-18.8.1/setuptools/tests/test_sdist.py
--- old/setuptools-18.7/setuptools/tests/test_sdist.py  2015-11-28 
04:43:42.000000000 +0100
+++ new/setuptools-18.8.1/setuptools/tests/test_sdist.py        2015-12-09 
10:00:26.000000000 +0100
@@ -1,13 +1,13 @@
 # -*- coding: utf-8 -*-
 """sdist tests"""
 
-import locale
 import os
 import shutil
 import sys
 import tempfile
 import unicodedata
 import contextlib
+import io
 
 import pytest
 
@@ -16,6 +16,11 @@
 from setuptools.command.sdist import sdist
 from setuptools.command.egg_info import manifest_maker
 from setuptools.dist import Distribution
+from setuptools.tests import fail_on_ascii
+
+
+py3_only = pytest.mark.xfail(PY2, reason="Test runs on Python 3 only")
+
 
 SETUP_ATTRS = {
     'name': 'sdist_test',
@@ -77,6 +82,11 @@
     return path
 
 
+def read_all_bytes(filename):
+    with io.open(filename, 'rb') as fp:
+        return fp.read()
+
+
 class TestSdistTest:
 
     def setup_method(self, method):
@@ -147,6 +157,7 @@
         assert 'setup.py' not in manifest, manifest
         assert 'setup.cfg' not in manifest, manifest
 
+    @fail_on_ascii
     def test_manifest_is_written_with_utf8_encoding(self):
         # Test for #303.
         dist = Distribution(SETUP_ATTRS)
@@ -167,9 +178,7 @@
             mm.filelist.append(filename)
             mm.write_manifest()
 
-        manifest = open(mm.manifest, 'rbU')
-        contents = manifest.read()
-        manifest.close()
+        contents = read_all_bytes(mm.manifest)
 
         # The manifest should be UTF-8 encoded
         u_contents = contents.decode('UTF-8')
@@ -181,81 +190,78 @@
 
         assert posix(filename) in u_contents
 
-    # Python 3 only
-    if PY3:
+    @py3_only
+    @fail_on_ascii
+    def test_write_manifest_allows_utf8_filenames(self):
+        # Test for #303.
+        dist = Distribution(SETUP_ATTRS)
+        dist.script_name = 'setup.py'
+        mm = manifest_maker(dist)
+        mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+        os.mkdir('sdist_test.egg-info')
 
-        def test_write_manifest_allows_utf8_filenames(self):
-            # Test for #303.
-            dist = Distribution(SETUP_ATTRS)
-            dist.script_name = 'setup.py'
-            mm = manifest_maker(dist)
-            mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
-            os.mkdir('sdist_test.egg-info')
-
-            # UTF-8 filename
-            filename = os.path.join(b('sdist_test'), b('smörbröd.py'))
-
-            # Must touch the file or risk removal
-            open(filename, "w").close()
-
-            # Add filename and write manifest
-            with quiet():
-                mm.run()
-                u_filename = filename.decode('utf-8')
-                mm.filelist.files.append(u_filename)
-                # Re-write manifest
-                mm.write_manifest()
-
-            manifest = open(mm.manifest, 'rbU')
-            contents = manifest.read()
-            manifest.close()
-
-            # The manifest should be UTF-8 encoded
-            contents.decode('UTF-8')
-
-            # The manifest should contain the UTF-8 filename
-            assert posix(filename) in contents
-
-            # The filelist should have been updated as well
-            assert u_filename in mm.filelist.files
-
-        def test_write_manifest_skips_non_utf8_filenames(self):
-            """
-            Files that cannot be encoded to UTF-8 (specifically, those that
-            weren't originally successfully decoded and have surrogate
-            escapes) should be omitted from the manifest.
-            See https://bitbucket.org/tarek/distribute/issue/303 for history.
-            """
-            dist = Distribution(SETUP_ATTRS)
-            dist.script_name = 'setup.py'
-            mm = manifest_maker(dist)
-            mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
-            os.mkdir('sdist_test.egg-info')
-
-            # Latin-1 filename
-            filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
-
-            # Add filename with surrogates and write manifest
-            with quiet():
-                mm.run()
-                u_filename = filename.decode('utf-8', 'surrogateescape')
-                mm.filelist.append(u_filename)
-                # Re-write manifest
-                mm.write_manifest()
-
-            manifest = open(mm.manifest, 'rbU')
-            contents = manifest.read()
-            manifest.close()
+        # UTF-8 filename
+        filename = os.path.join(b('sdist_test'), b('smörbröd.py'))
 
-            # The manifest should be UTF-8 encoded
-            contents.decode('UTF-8')
+        # Must touch the file or risk removal
+        open(filename, "w").close()
 
-            # The Latin-1 filename should have been skipped
-            assert posix(filename) not in contents
+        # Add filename and write manifest
+        with quiet():
+            mm.run()
+            u_filename = filename.decode('utf-8')
+            mm.filelist.files.append(u_filename)
+            # Re-write manifest
+            mm.write_manifest()
+
+        contents = read_all_bytes(mm.manifest)
+
+        # The manifest should be UTF-8 encoded
+        contents.decode('UTF-8')
+
+        # The manifest should contain the UTF-8 filename
+        assert posix(filename) in contents
+
+        # The filelist should have been updated as well
+        assert u_filename in mm.filelist.files
+
+    @py3_only
+    def test_write_manifest_skips_non_utf8_filenames(self):
+        """
+        Files that cannot be encoded to UTF-8 (specifically, those that
+        weren't originally successfully decoded and have surrogate
+        escapes) should be omitted from the manifest.
+        See https://bitbucket.org/tarek/distribute/issue/303 for history.
+        """
+        dist = Distribution(SETUP_ATTRS)
+        dist.script_name = 'setup.py'
+        mm = manifest_maker(dist)
+        mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+        os.mkdir('sdist_test.egg-info')
 
-            # The filelist should have been updated as well
-            assert u_filename not in mm.filelist.files
+        # Latin-1 filename
+        filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
 
+        # Add filename with surrogates and write manifest
+        with quiet():
+            mm.run()
+            u_filename = filename.decode('utf-8', 'surrogateescape')
+            mm.filelist.append(u_filename)
+            # Re-write manifest
+            mm.write_manifest()
+
+        contents = read_all_bytes(mm.manifest)
+
+        # The manifest should be UTF-8 encoded
+        contents.decode('UTF-8')
+
+        # The Latin-1 filename should have been skipped
+        assert posix(filename) not in contents
+
+        # The filelist should have been updated as well
+        assert u_filename not in mm.filelist.files
+
+    @fail_on_ascii
     def test_manifest_is_read_with_utf8_encoding(self):
         # Test for #303.
         dist = Distribution(SETUP_ATTRS)
@@ -287,42 +293,38 @@
             filename = filename.decode('utf-8')
         assert filename in cmd.filelist.files
 
-    # Python 3 only
-    if PY3:
+    @py3_only
+    def test_read_manifest_skips_non_utf8_filenames(self):
+        # Test for #303.
+        dist = Distribution(SETUP_ATTRS)
+        dist.script_name = 'setup.py'
+        cmd = sdist(dist)
+        cmd.ensure_finalized()
+
+        # Create manifest
+        with quiet():
+            cmd.run()
+
+        # Add Latin-1 filename to manifest
+        filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
+        cmd.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+        manifest = open(cmd.manifest, 'ab')
+        manifest.write(b('\n') + filename)
+        manifest.close()
+
+        # The file must exist to be included in the filelist
+        open(filename, 'w').close()
+
+        # Re-read manifest
+        cmd.filelist.files = []
+        with quiet():
+            cmd.read_manifest()
+
+        # The Latin-1 filename should have been skipped
+        filename = filename.decode('latin-1')
+        assert filename not in cmd.filelist.files
 
-        def test_read_manifest_skips_non_utf8_filenames(self):
-            # Test for #303.
-            dist = Distribution(SETUP_ATTRS)
-            dist.script_name = 'setup.py'
-            cmd = sdist(dist)
-            cmd.ensure_finalized()
-
-            # Create manifest
-            with quiet():
-                cmd.run()
-
-            # Add Latin-1 filename to manifest
-            filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
-            cmd.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
-            manifest = open(cmd.manifest, 'ab')
-            manifest.write(b('\n') + filename)
-            manifest.close()
-
-            # The file must exist to be included in the filelist
-            open(filename, 'w').close()
-
-            # Re-read manifest
-            cmd.filelist.files = []
-            with quiet():
-                cmd.read_manifest()
-
-            # The Latin-1 filename should have been skipped
-            filename = filename.decode('latin-1')
-            assert filename not in cmd.filelist.files
-
-    @pytest.mark.skipif(PY3 and locale.getpreferredencoding() != 'UTF-8',
-        reason='Unittest fails if locale is not utf-8 but the manifests is '
-            'recorded correctly')
+    @fail_on_ascii
     def test_sdist_with_utf8_encoded_filename(self):
         # Test for #303.
         dist = Distribution(SETUP_ATTRS)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools/version.py 
new/setuptools-18.8.1/setuptools/version.py
--- old/setuptools-18.7/setuptools/version.py   2015-11-28 23:57:43.000000000 
+0100
+++ new/setuptools-18.8.1/setuptools/version.py 2015-12-13 17:57:40.000000000 
+0100
@@ -1 +1 @@
-__version__ = '18.7'
+__version__ = '18.8.1'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/setuptools-18.7/setuptools.egg-info/PKG-INFO 
new/setuptools-18.8.1/setuptools.egg-info/PKG-INFO
--- old/setuptools-18.7/setuptools.egg-info/PKG-INFO    2015-11-28 
23:57:47.000000000 +0100
+++ new/setuptools-18.8.1/setuptools.egg-info/PKG-INFO  2015-12-13 
17:57:43.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: setuptools
-Version: 18.7
+Version: 18.8.1
 Summary: Easily download, build, install, upgrade, and uninstall Python 
packages
 Home-page: https://bitbucket.org/pypa/setuptools
 Author: Python Packaging Authority


Reply via email to