From 41f634812f1ee6b734e7d5fb25486b66ab351d0a Mon Sep 17 00:00:00 2001 From: matej Date: Tue, 18 Nov 2014 14:38:56 +0100 Subject: Different treatment of --user option to easy_install (refs #285) --- setuptools/command/easy_install.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 2e00b996..d0bae2b2 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -148,12 +148,9 @@ class easy_install(Command): create_index = PackageIndex def initialize_options(self): - if site.ENABLE_USER_SITE: - whereami = os.path.abspath(__file__) - self.user = whereami.startswith(site.USER_SITE) - else: - self.user = 0 - + # the --user option seemst to be an opt-in one, + # so the default should be False. + self.user = 0 self.zip_ok = self.local_snapshots_ok = None self.install_dir = self.script_dir = self.exclude_scripts = None self.index_url = None -- cgit v1.2.1 From 9d6a6e5927ae0e67164383e419f3145fc154467e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 11:35:16 -0500 Subject: Use except/as, now supported by Python 2.6 --- pkg_resources/__init__.py | 10 ++++------ setuptools/command/easy_install.py | 12 ++++-------- setuptools/command/sdist.py | 3 ++- setuptools/command/upload_docs.py | 3 +-- setuptools/dist.py | 3 +-- setuptools/msvc9_support.py | 3 +-- setuptools/package_index.py | 15 +++++---------- setuptools/sandbox.py | 3 +-- setuptools/tests/test_packageindex.py | 12 ++++-------- setuptools/tests/test_sdist.py | 12 ++++-------- 10 files changed, 27 insertions(+), 49 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index f004315a..41d3eb38 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -843,8 +843,7 @@ class WorkingSet(object): try: resolvees = shadow_set.resolve(req, env, installer) - except ResolutionError: - v = sys.exc_info()[1] + except ResolutionError as v: # save error info error_info[dist] = v if fallback: @@ -1340,8 +1339,8 @@ class MarkerEvaluation(object): """ try: cls.evaluate_marker(text) - except SyntaxError: - return cls.normalize_exception(sys.exc_info()[1]) + except SyntaxError as e: + return cls.normalize_exception(e) return False @staticmethod @@ -1456,8 +1455,7 @@ class MarkerEvaluation(object): env[new_key] = env.pop(key) try: result = _markerlib.interpret(text, env) - except NameError: - e = sys.exc_info()[1] + except NameError as e: raise SyntaxError(e.args[0]) return result diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 1a2f56ae..02ce7636 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -698,13 +698,11 @@ Please make the appropriate changes for your system and try again. distros = WorkingSet([]).resolve( [requirement], self.local_index, self.easy_install ) - except DistributionNotFound: - e = sys.exc_info()[1] + except DistributionNotFound as e: raise DistutilsError( "Could not find required distribution %s" % e.args ) - except VersionConflict: - e = sys.exc_info()[1] + except VersionConflict as e: raise DistutilsError( "Installed distribution %s conflicts with requirement %s" % e.args @@ -1044,8 +1042,7 @@ See the setuptools documentation for the "develop" command for more info. ) try: run_setup(setup_script, args) - except SystemExit: - v = sys.exc_info()[1] + except SystemExit as v: raise DistutilsError("Setup script exited with %s" % (v.args[0],)) def build_and_install(self, setup_script, setup_base): @@ -1889,8 +1886,7 @@ def chmod(path, mode): log.debug("changing mode of %s to %o", path, mode) try: _chmod(path, mode) - except os.error: - e = sys.exc_info()[1] + except os.error as e: log.debug("chmod failed: %s", e) diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index 3d33df80..851a1775 100755 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -70,7 +70,8 @@ class sdist(orig.sdist): try: orig.sdist.read_template(self) except: - sys.exc_info()[2].tb_next.tb_frame.f_locals['template'].close() + _, _, tb = sys.exc_info() + tb.tb_next.tb_frame.f_locals['template'].close() raise # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle diff --git a/setuptools/command/upload_docs.py b/setuptools/command/upload_docs.py index cd6c300c..001ee936 100644 --- a/setuptools/command/upload_docs.py +++ b/setuptools/command/upload_docs.py @@ -169,8 +169,7 @@ class upload_docs(upload): conn.putheader('Authorization', auth) conn.endheaders() conn.send(body) - except socket.error: - e = sys.exc_info()[1] + except socket.error as e: self.announce(str(e), log.ERROR) return diff --git a/setuptools/dist.py b/setuptools/dist.py index eb146444..1917a610 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -131,8 +131,7 @@ def check_entry_points(dist, attr, value): """Verify that entry_points map is parseable""" try: pkg_resources.EntryPoint.parse_map(value) - except ValueError: - e = sys.exc_info()[1] + except ValueError as e: raise DistutilsSetupError(e) def check_test_suite(dist, attr, value): diff --git a/setuptools/msvc9_support.py b/setuptools/msvc9_support.py index d0be70e2..e76d70f0 100644 --- a/setuptools/msvc9_support.py +++ b/setuptools/msvc9_support.py @@ -50,8 +50,7 @@ def find_vcvarsall(version): def query_vcvarsall(version, *args, **kwargs): try: return unpatched['query_vcvarsall'](version, *args, **kwargs) - except distutils.errors.DistutilsPlatformError: - exc = sys.exc_info()[1] + except distutils.errors.DistutilsPlatformError as exc: if exc and "vcvarsall.bat" in exc.args[0]: message = 'Microsoft Visual C++ %0.1f is required (%s).' % (version, exc.args[0]) if int(version) == 9: diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 58572ce6..5ed19130 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -699,25 +699,21 @@ class PackageIndex(Environment): return local_open(url) try: return open_with_auth(url, self.opener) - except (ValueError, httplib.InvalidURL): - v = sys.exc_info()[1] + except (ValueError, httplib.InvalidURL) as v: msg = ' '.join([str(arg) for arg in v.args]) if warning: self.warn(warning, msg) else: raise DistutilsError('%s %s' % (url, msg)) - except urllib2.HTTPError: - v = sys.exc_info()[1] + except urllib2.HTTPError as v: return v - except urllib2.URLError: - v = sys.exc_info()[1] + except urllib2.URLError as v: if warning: self.warn(warning, v.reason) else: raise DistutilsError("Download error for %s: %s" % (url, v.reason)) - except httplib.BadStatusLine: - v = sys.exc_info()[1] + except httplib.BadStatusLine as v: if warning: self.warn(warning, v.line) else: @@ -726,8 +722,7 @@ class PackageIndex(Environment): 'down, %s' % (url, v.line) ) - except httplib.HTTPException: - v = sys.exc_info()[1] + except httplib.HTTPException as v: if warning: self.warn(warning, v) else: diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index b90d1e1b..7971f42c 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -199,8 +199,7 @@ def run_setup(setup_script, args): ns = dict(__file__=setup_script, __name__='__main__') _execfile(setup_script, ns) DirectorySandbox(setup_dir).run(runner) - except SystemExit: - v = sys.exc_info()[1] + except SystemExit as v: if v.args and v.args[0]: raise # Normal exit, just return diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index 3e9d1d84..dcd90d6f 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -15,8 +15,7 @@ class TestPackageIndex: url = 'http://127.0.0.1:0/nonesuch/test_package_index' try: v = index.open_url(url) - except Exception: - v = sys.exc_info()[1] + except Exception as v: assert url in str(v) else: assert isinstance(v, HTTPError) @@ -32,8 +31,7 @@ class TestPackageIndex: url = 'url:%20https://svn.plone.org/svn/collective/inquant.contentmirror.plone/trunk' try: v = index.open_url(url) - except Exception: - v = sys.exc_info()[1] + except Exception as v: assert url in str(v) else: assert isinstance(v, HTTPError) @@ -50,8 +48,7 @@ class TestPackageIndex: url = 'http://example.com' try: v = index.open_url(url) - except Exception: - v = sys.exc_info()[1] + except Exception as v: assert 'line' in str(v) else: raise AssertionError('Should have raise here!') @@ -68,8 +65,7 @@ class TestPackageIndex: url = 'http://http://svn.pythonpaste.org/Paste/wphp/trunk' try: index.open_url(url) - except distutils.errors.DistutilsError: - error = sys.exc_info()[1] + except distutils.errors.DistutilsError as error: msg = unicode(error) assert 'nonnumeric port' in msg or 'getaddrinfo failed' in msg or 'Name or service not known' in msg return diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 943a5dee..68f83ca7 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -174,8 +174,7 @@ class TestSdistTest: # The manifest should be UTF-8 encoded try: u_contents = contents.decode('UTF-8') - except UnicodeDecodeError: - e = sys.exc_info()[1] + except UnicodeDecodeError as e: self.fail(e) # The manifest should contain the UTF-8 filename @@ -217,8 +216,7 @@ class TestSdistTest: # The manifest should be UTF-8 encoded try: contents.decode('UTF-8') - except UnicodeDecodeError: - e = sys.exc_info()[1] + except UnicodeDecodeError as e: self.fail(e) # The manifest should contain the UTF-8 filename @@ -258,8 +256,7 @@ class TestSdistTest: # The manifest should be UTF-8 encoded try: contents.decode('UTF-8') - except UnicodeDecodeError: - e = sys.exc_info()[1] + except UnicodeDecodeError as e: self.fail(e) # The Latin-1 filename should have been skipped @@ -328,8 +325,7 @@ class TestSdistTest: with quiet(): try: cmd.read_manifest() - except UnicodeDecodeError: - e = sys.exc_info()[1] + except UnicodeDecodeError as e: self.fail(e) # The Latin-1 filename should have been skipped -- cgit v1.2.1 From 0a8b9a3152c736d8e2f8a01f5a9547546b907de7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 11:55:34 -0500 Subject: And again in doctest --- pkg_resources/api_tests.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg_resources/api_tests.txt b/pkg_resources/api_tests.txt index 50e04b87..a6c25a37 100644 --- a/pkg_resources/api_tests.txt +++ b/pkg_resources/api_tests.txt @@ -210,8 +210,7 @@ working set triggers a ``pkg_resources.VersionConflict`` error: >>> try: ... ws.find(Requirement.parse("Bar==1.0")) - ... except pkg_resources.VersionConflict: - ... exc = sys.exc_info()[1] + ... except pkg_resources.VersionConflict as exc: ... print(str(exc)) ... else: ... raise AssertionError("VersionConflict was not raised") -- cgit v1.2.1 From 3593a64ed6755876702ce362e1dfc87849c0952b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 12:09:27 -0500 Subject: Skip integration tests when one of the packages under test is already installed, as the installation will fail in that case. --- setuptools/tests/test_integration.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/setuptools/tests/test_integration.py b/setuptools/tests/test_integration.py index 3a6abeaa..92a27080 100644 --- a/setuptools/tests/test_integration.py +++ b/setuptools/tests/test_integration.py @@ -14,6 +14,17 @@ from setuptools.command import easy_install as easy_install_pkg from setuptools.dist import Distribution +def setup_module(module): + packages = 'stevedore', 'virtualenvwrapper', 'pbr', 'novaclient' + for pkg in packages: + try: + __import__(pkg) + tmpl = "Integration tests cannot run when {pkg} is installed" + pytest.skip(tmpl.format(**locals())) + except ImportError: + pass + + @pytest.fixture def install_context(request, tmpdir, monkeypatch): """Fixture to set up temporary installation directory. -- cgit v1.2.1 From fba8ee7abecb12726293438e8af19d7c3fa54bb8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 12:22:53 -0500 Subject: Remove try/except/fail - Exceptions are failures by default. --- pkg_resources/tests/test_resources.py | 6 ++---- setuptools/tests/test_easy_install.py | 12 +++--------- setuptools/tests/test_sandbox.py | 6 ++---- setuptools/tests/test_sdist.py | 20 ++++---------------- 4 files changed, 11 insertions(+), 33 deletions(-) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 6cc3de0b..82a987b7 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -593,10 +593,8 @@ class TestNamespaces: pkg2_init.close() import pkg1 assert "pkg1" in pkg_resources._namespace_packages - try: - import pkg1.pkg2 - except ImportError: - self.fail("Setuptools tried to import the parent namespace package") + # attempt to import pkg2 from site-pkgs2 + import pkg1.pkg2 # check the _namespace_packages dict assert "pkg1.pkg2" in pkg_resources._namespace_packages assert pkg_resources._namespace_packages["pkg1"] == ["pkg1.pkg2"] diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 04271178..7baa989a 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -250,8 +250,6 @@ class TestUserInstallTest: with contexts.quiet(): with self.patched_setup_context(): run_setup(test_setup_py, ['install']) - except SandboxViolation: - self.fail('Installation caused SandboxViolation') except IndexError: # Test fails in some cases due to bugs in Python # See https://bitbucket.org/pypa/setuptools/issue/201 @@ -353,13 +351,9 @@ class TestSetupRequires: test_pkg = create_setup_requires_package(temp_dir) test_setup_py = os.path.join(test_pkg, 'setup.py') with contexts.quiet() as (stdout, stderr): - try: - # Don't even need to install the package, just - # running the setup.py at all is sufficient - run_setup(test_setup_py, ['--name']) - except VersionConflict: - self.fail('Installing setup.py requirements ' - 'caused a VersionConflict') + # Don't even need to install the package, just + # running the setup.py at all is sufficient + run_setup(test_setup_py, ['--name']) lines = stdout.readlines() assert len(lines) > 0 diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index 6e5ce04a..cadc4812 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -33,10 +33,8 @@ class TestSandbox: target = os.path.join(gen_py, 'test_write') sandbox = DirectorySandbox(str(tmpdir)) try: - try: - sandbox.run(self._file_writer(target)) - except SandboxViolation: - self.fail("Could not create gen_py file due to SandboxViolation") + # attempt to create gen_py file + sandbox.run(self._file_writer(target)) finally: if os.path.exists(target): os.remove(target) diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 68f83ca7..d3494d7a 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -172,10 +172,7 @@ class TestSdistTest: manifest.close() # The manifest should be UTF-8 encoded - try: - u_contents = contents.decode('UTF-8') - except UnicodeDecodeError as e: - self.fail(e) + u_contents = contents.decode('UTF-8') # The manifest should contain the UTF-8 filename if PY2: @@ -214,10 +211,7 @@ class TestSdistTest: manifest.close() # The manifest should be UTF-8 encoded - try: - contents.decode('UTF-8') - except UnicodeDecodeError as e: - self.fail(e) + contents.decode('UTF-8') # The manifest should contain the UTF-8 filename assert posix(filename) in contents @@ -254,10 +248,7 @@ class TestSdistTest: manifest.close() # The manifest should be UTF-8 encoded - try: - contents.decode('UTF-8') - except UnicodeDecodeError as e: - self.fail(e) + contents.decode('UTF-8') # The Latin-1 filename should have been skipped assert posix(filename) not in contents @@ -323,10 +314,7 @@ class TestSdistTest: # Re-read manifest cmd.filelist.files = [] with quiet(): - try: - cmd.read_manifest() - except UnicodeDecodeError as e: - self.fail(e) + cmd.read_manifest() # The Latin-1 filename should have been skipped filename = filename.decode('latin-1') -- cgit v1.2.1 From db8efa2a8141205c405cd36f8c8a1aa0b1b7defa Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 12:25:38 -0500 Subject: Extract variable --- pkg_resources/tests/test_resources.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 82a987b7..fbb9db62 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -210,10 +210,8 @@ class TestEntryPoints: assert ep.attrs == ("TestEntryPoints",) assert ep.extras == ("x",) assert ep.load() is TestEntryPoints - assert ( - str(ep) == - "foo = pkg_resources.tests.test_resources:TestEntryPoints [x]" - ) + expect = "foo = pkg_resources.tests.test_resources:TestEntryPoints [x]" + assert str(ep) == expect def setup_method(self, method): self.dist = Distribution.from_filename( -- cgit v1.2.1 From d8de6c98d879adbe5b8df731a5b61c06a48b9a2f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 12:43:13 -0500 Subject: Add another assertion on the exception. --- pkg_resources/tests/test_resources.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index fbb9db62..cf16bf03 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -172,9 +172,12 @@ class TestDistro: # Activation list now includes resolved dependency assert list(ws.resolve(parse_requirements("Foo[bar]"), ad)) ==[Foo,Baz] # Requests for conflicting versions produce VersionConflict - with pytest.raises(VersionConflict): + with pytest.raises(VersionConflict) as vc: ws.resolve(parse_requirements("Foo==1.2\nFoo!=1.2"), ad) + msg = 'Foo 0.9 is installed but Foo==1.2 is required by []' + assert str(vc).endswith(msg) + def testDistroDependsOptions(self): d = self.distRequires(""" Twisted>=1.5 -- cgit v1.2.1 From 06b95e98f06916ccbd04b60e9d3866e3d6bf7ae2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 12:44:16 -0500 Subject: Remove unreachable branch --- pkg_resources/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 41d3eb38..bcee9d28 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -627,8 +627,7 @@ class WorkingSet(object): if dist is not None and dist not in req: # XXX add more info raise VersionConflict(dist, req) - else: - return dist + return dist def iter_entry_points(self, group, name=None): """Yield entry point objects from `group` matching `name` -- cgit v1.2.1 From 880ccea0220509bfaf483a50beefc128299a5b03 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 13:00:50 -0500 Subject: Add test for WorkingSet.find() when a conflict occurs. --- pkg_resources/tests/test_resources.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index cf16bf03..79961e6c 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -205,6 +205,22 @@ class TestDistro: d.requires(["foo"]) +class TestWorkingSet: + def test_find_conflicting(self): + ws = WorkingSet([]) + Foo = Distribution.from_filename("/foo_dir/Foo-1.2.egg") + ws.add(Foo) + + # create a requirement that conflicts with Foo 1.2 + req = next(parse_requirements("Foo<1.2")) + + with pytest.raises(VersionConflict) as vc: + ws.find(req) + + msg = 'Foo 1.2 is installed but Foo<1.2 is required' + assert str(vc).endswith(msg) + + class TestEntryPoints: def assertfields(self, ep): -- cgit v1.2.1 From 23d5e4a81a61c5e6617fa69fd0b2bc440fa20c45 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 13:25:28 -0500 Subject: Test the report method --- pkg_resources/__init__.py | 33 +++++++++++++++++++++++++++++---- pkg_resources/tests/test_resources.py | 6 +++--- setuptools/command/easy_install.py | 5 +---- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index bcee9d28..0846c0ac 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -317,8 +317,34 @@ class ResolutionError(Exception): def __repr__(self): return self.__class__.__name__+repr(self.args) + class VersionConflict(ResolutionError): - """An already-installed version conflicts with the requested version""" + """ + An already-installed version conflicts with the requested version. + + Should be initialized with the installed Distribution, the requested + Requirement, and optionally a list of dists that required the installed + Distribution. + """ + + @property + def dist(self): + return self.args[0] + + @property + def req(self): + return self.args[1] + + @property + def required_by(self): + return self.args[2] if len(self.args) > 2 else [] + + def report(self): + template = "{self.dist} is installed but {self.req} is required" + if self.required_by: + template += " by {self.required_by}" + return template.format(**locals()) + class DistributionNotFound(ResolutionError): """A requested distribution was not found""" @@ -763,9 +789,8 @@ class WorkingSet(object): to_activate.append(dist) if dist not in req: # Oops, the "best" so far conflicts with a dependency - tmpl = "%s is installed but %s is required by %s" - args = dist, req, list(required_by.get(req, [])) - raise VersionConflict(tmpl % args) + dependent_req = list(required_by.get(req, [])) + raise VersionConflict(dist, req, dependent_req) # push the new requirements onto the stack new_requirements = dist.requires(req.extras)[::-1] diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 79961e6c..5cf3a657 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -175,8 +175,8 @@ class TestDistro: with pytest.raises(VersionConflict) as vc: ws.resolve(parse_requirements("Foo==1.2\nFoo!=1.2"), ad) - msg = 'Foo 0.9 is installed but Foo==1.2 is required by []' - assert str(vc).endswith(msg) + msg = 'Foo 0.9 is installed but Foo==1.2 is required' + assert vc.value.report() == msg def testDistroDependsOptions(self): d = self.distRequires(""" @@ -218,7 +218,7 @@ class TestWorkingSet: ws.find(req) msg = 'Foo 1.2 is installed but Foo<1.2 is required' - assert str(vc).endswith(msg) + assert vc.value.report() == msg class TestEntryPoints: diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 02ce7636..d05f4c65 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -703,10 +703,7 @@ Please make the appropriate changes for your system and try again. "Could not find required distribution %s" % e.args ) except VersionConflict as e: - raise DistutilsError( - "Installed distribution %s conflicts with requirement %s" - % e.args - ) + raise DistutilsError(e.report()) if self.always_copy or self.always_copy_from: # Force all the relevant distros to be copied or activated for dist in distros: -- cgit v1.2.1 From ddb012669aa26fffd6791283e6405fa34bf9f0e5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 13:39:31 -0500 Subject: Split out ContextualVersionConflict --- pkg_resources/__init__.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 0846c0ac..277da3f9 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -322,11 +322,12 @@ class VersionConflict(ResolutionError): """ An already-installed version conflicts with the requested version. - Should be initialized with the installed Distribution, the requested - Requirement, and optionally a list of dists that required the installed - Distribution. + Should be initialized with the installed Distribution and the requested + Requirement. """ + _template = "{self.dist} is installed but {self.req} is required" + @property def dist(self): return self.args[0] @@ -335,15 +336,21 @@ class VersionConflict(ResolutionError): def req(self): return self.args[1] + def report(self): + return self._template.format(**locals()) + + +class ContextualVersionConflict(VersionConflict): + """ + A VersionConflict that accepts a third parameter, the list of the + requirements that required the installed Distribution. + """ + + _template = VersionConflict._template + ' by {self.required_by}' + @property def required_by(self): - return self.args[2] if len(self.args) > 2 else [] - - def report(self): - template = "{self.dist} is installed but {self.req} is required" - if self.required_by: - template += " by {self.required_by}" - return template.format(**locals()) + return self.args[2] class DistributionNotFound(ResolutionError): @@ -790,7 +797,7 @@ class WorkingSet(object): if dist not in req: # Oops, the "best" so far conflicts with a dependency dependent_req = list(required_by.get(req, [])) - raise VersionConflict(dist, req, dependent_req) + raise ContextualVersionConflict(dist, req, dependent_req) # push the new requirements onto the stack new_requirements = dist.requires(req.extras)[::-1] -- cgit v1.2.1 From a7ae16215eab4487954d546f583e30869696adfc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 13:41:29 -0500 Subject: No need to mutate the set to a list; just use the set. --- pkg_resources/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 277da3f9..522247e0 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -342,7 +342,7 @@ class VersionConflict(ResolutionError): class ContextualVersionConflict(VersionConflict): """ - A VersionConflict that accepts a third parameter, the list of the + A VersionConflict that accepts a third parameter, the set of the requirements that required the installed Distribution. """ @@ -796,7 +796,7 @@ class WorkingSet(object): to_activate.append(dist) if dist not in req: # Oops, the "best" so far conflicts with a dependency - dependent_req = list(required_by.get(req, [])) + dependent_req = required_by[req] raise ContextualVersionConflict(dist, req, dependent_req) # push the new requirements onto the stack -- cgit v1.2.1 From 0529be8ca5487513336da8fd35108c52aa95e582 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 13:58:33 -0500 Subject: Only raise a ContextualVersionConflict when dependent requirements are present. --- pkg_resources/__init__.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 522247e0..d51f301b 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -339,6 +339,16 @@ class VersionConflict(ResolutionError): def report(self): return self._template.format(**locals()) + def with_context(self, required_by): + """ + If required_by is non-empty, return a version of self that is a + ContextualVersionConflict. + """ + if not required_by: + return self + args = self.args + (required_by,) + return ContextualVersionConflict(*args) + class ContextualVersionConflict(VersionConflict): """ @@ -797,7 +807,7 @@ class WorkingSet(object): if dist not in req: # Oops, the "best" so far conflicts with a dependency dependent_req = required_by[req] - raise ContextualVersionConflict(dist, req, dependent_req) + raise VersionConflict(dist, req).with_context(dependent_req) # push the new requirements onto the stack new_requirements = dist.requires(req.extras)[::-1] -- cgit v1.2.1 From 72e3a1ce5986c54fed71da1f65aed4022008511f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 14:13:05 -0500 Subject: Normalize whitespace --- pkg_resources/tests/test_resources.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 5cf3a657..13ed4eb1 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -23,21 +23,23 @@ def safe_repr(obj, short=False): return result return result[:pkg_resources._MAX_LENGTH] + ' [truncated]...' + class Metadata(pkg_resources.EmptyProvider): """Mock object to return metadata as if from an on-disk distribution""" - def __init__(self,*pairs): + def __init__(self, *pairs): self.metadata = dict(pairs) - def has_metadata(self,name): + def has_metadata(self, name): return name in self.metadata - def get_metadata(self,name): + def get_metadata(self, name): return self.metadata[name] - def get_metadata_lines(self,name): + def get_metadata_lines(self, name): return pkg_resources.yield_lines(self.get_metadata(name)) + dist_from_fn = pkg_resources.Distribution.from_filename class TestDistro: -- cgit v1.2.1 From cdb9797a1107afd4d7baf021b2af84946d349a2a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 14:24:22 -0500 Subject: Add test capturing expectation when dependencies conflict during resolve. Fixes #281 --- pkg_resources/tests/test_resources.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 13ed4eb1..7ba65786 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -222,6 +222,31 @@ class TestWorkingSet: msg = 'Foo 1.2 is installed but Foo<1.2 is required' assert vc.value.report() == msg + def test_resolve_conflicts_with_prior(self): + """ + A ContextualVersionConflict should be raised when a requirement + conflicts with a prior requirement for a different package. + """ + # Create installation where Foo depends on Baz 1.0 and Bar depends on + # Baz 2.0. + ws = WorkingSet([]) + md = Metadata(('depends.txt', "Baz==1.0")) + Foo = Distribution.from_filename("/foo_dir/Foo-1.0.egg", metadata=md) + ws.add(Foo) + md = Metadata(('depends.txt', "Baz==2.0")) + Bar = Distribution.from_filename("/foo_dir/Bar-1.0.egg", metadata=md) + ws.add(Bar) + Baz = Distribution.from_filename("/foo_dir/Baz-1.0.egg") + ws.add(Baz) + Baz = Distribution.from_filename("/foo_dir/Baz-2.0.egg") + ws.add(Baz) + + with pytest.raises(VersionConflict) as vc: + ws.resolve(parse_requirements("Foo\nBar\n")) + + msg = "Baz 1.0 is installed but Baz==2.0 is required by {'Bar'}" + assert vc.value.report() == msg + class TestEntryPoints: -- cgit v1.2.1 From 0b7d713f812e7d84f143bd84f0734ae77169bb68 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 14:28:07 -0500 Subject: Fix test failure on Python 2 --- pkg_resources/tests/test_resources.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 7ba65786..f252ddff 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -245,6 +245,8 @@ class TestWorkingSet: ws.resolve(parse_requirements("Foo\nBar\n")) msg = "Baz 1.0 is installed but Baz==2.0 is required by {'Bar'}" + if pkg_resources.PY2: + msg = msg.replace("{'Bar'}", "set(['Bar'])") assert vc.value.report() == msg -- cgit v1.2.1 From 9974d0bd67352392328a3dda07699e80cc90596c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 14:35:30 -0500 Subject: Update changelog --- CHANGES.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 62ab4301..8fc9e981 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,17 @@ CHANGES ======= +---- +11.1 +---- + +* Issue #281: Since Setuptools 6.1 (Issue #268), a ValueError would be raised + in certain cases where VersionConflict was raised with two arguments, which + occurred in ``pkg_resources.WorkingSet.find``. This release adds support + for indicating the dependent packages while maintaining support for + a VersionConflict when no dependent package context is known. New unit tests + now capture the expected interface. + ---- 11.0 ---- -- cgit v1.2.1 From 89591dcd22840ab6e38a484ca5864c8e1d728223 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 14:36:22 -0500 Subject: Added tag 11.1 for changeset 6cd2b18f4be2 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 8594f6ad..021c8ff4 100644 --- a/.hgtags +++ b/.hgtags @@ -182,3 +182,4 @@ fa069bf2411a150c9379d31a04d1c3836e2d3027 9.0.1 651d41db58849d4fc50e466f4dc458d448480c4e 10.2 1f5de53c079d577ead9d80265c9e006503b16457 10.2.1 b4b92805bc0e9802da0b597d00df4fa42b30bc40 11.0 +6cd2b18f4be2a9c188fa505b34505b32f4a4554b 11.1 -- cgit v1.2.1 From 3e33c18af2c26a9b01383647157f4c1da275f67f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 14:36:52 -0500 Subject: Bumped to 11.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 740af722..388ff490 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "11.1" +DEFAULT_VERSION = "11.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index 1b1703fd..a6fd3e36 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '11.1' +__version__ = '11.2' -- cgit v1.2.1 From 371c355c4f8b406e0390bf964bb4d7f4266ba3e8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 14:40:47 -0500 Subject: Remove references to removed files --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index ed60948b..428bbd1e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,5 @@ recursive-include setuptools *.py *.exe *.xml -recursive-include tests *.py *.c *.pyx +recursive-include tests *.py recursive-include setuptools/tests *.html recursive-include docs *.py *.txt *.conf *.css *.css_t Makefile indexsidebar.html recursive-include _markerlib *.py -- cgit v1.2.1 From 76dd319a776b3fb7bc7836eb18429ab407379ea9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 15:35:24 -0500 Subject: Reuse list2cmdline for argument quoting. --- setuptools/command/easy_install.py | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index d05f4c65..c68fe757 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -35,6 +35,7 @@ import warnings import site import struct import contextlib +import subprocess from setuptools import Command from setuptools.sandbox import run_setup @@ -1825,36 +1826,7 @@ def is_sh(executable): def nt_quote_arg(arg): """Quote a command line argument according to Windows parsing rules""" - - result = [] - needquote = False - nb = 0 - - needquote = (" " in arg) or ("\t" in arg) - if needquote: - result.append('"') - - for c in arg: - if c == '\\': - nb += 1 - elif c == '"': - # double preceding backslashes, then add a \" - result.append('\\' * (nb * 2) + '\\"') - nb = 0 - else: - if nb: - result.append('\\' * nb) - nb = 0 - result.append(c) - - if nb: - result.append('\\' * nb) - - if needquote: - result.append('\\' * nb) # double the trailing backslashes - result.append('"') - - return ''.join(result) + return subprocess.list2cmdline([arg]) def is_python_script(script_text, filename): -- cgit v1.2.1 From 4108a12a41f3c413f2ea5e8ede3075d67067cba5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 15:49:50 -0500 Subject: Extract method for getting script args --- setuptools/command/easy_install.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index c68fe757..4e05d670 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1904,15 +1904,19 @@ class ScriptWriter(object): """ Yield write_script() argument tuples for a distribution's entrypoints """ - gen_class = cls.get_writer(wininst) - spec = str(dist.as_requirement()) + writer = cls.get_writer(wininst) header = get_script_header("", executable, wininst) + return cls._gen_args(dist, writer, header) + + @classmethod + def _gen_args(cls, dist, writer, header): + spec = str(dist.as_requirement()) for type_ in 'console', 'gui': group = type_ + '_scripts' for name, ep in dist.get_entry_map(group).items(): - script_text = gen_class.template % locals() - for res in gen_class._get_script_args(type_, name, header, - script_text): + script_text = writer.template % locals() + for res in writer._get_script_args(type_, name, header, + script_text): yield res @classmethod -- cgit v1.2.1 From d7cb597b9697e11d3f13e46d6af787ffc82571d5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 15:56:19 -0500 Subject: No need to pass the writer - just invoke it directly. --- setuptools/command/easy_install.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 4e05d670..d5d518de 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1906,16 +1906,16 @@ class ScriptWriter(object): """ writer = cls.get_writer(wininst) header = get_script_header("", executable, wininst) - return cls._gen_args(dist, writer, header) + return writer._gen_args(dist, header) @classmethod - def _gen_args(cls, dist, writer, header): + def _gen_args(cls, dist, header): spec = str(dist.as_requirement()) for type_ in 'console', 'gui': group = type_ + '_scripts' for name, ep in dist.get_entry_map(group).items(): - script_text = writer.template % locals() - for res in writer._get_script_args(type_, name, header, + script_text = cls.template % locals() + for res in cls._get_script_args(type_, name, header, script_text): yield res -- cgit v1.2.1 From aabff23148950b34d1f956e7d5a63c6cd098662e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 15:59:22 -0500 Subject: Move trailing comment --- setuptools/command/easy_install.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index d5d518de..e52b4736 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -918,7 +918,8 @@ Please make the appropriate changes for your system and try again. f.write('%s: %s\n' % (k.replace('_', '-').title(), v)) f.close() script_dir = os.path.join(_egg_info, 'scripts') - self.delete_blockers( # delete entry-point scripts to avoid duping + # delete entry-point scripts to avoid duping + self.delete_blockers( [os.path.join(script_dir, args[0]) for args in get_script_args(dist)] ) -- cgit v1.2.1 From 2170df350911390a4a9a205763475dc7a7a2fb54 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 16:21:11 -0500 Subject: Move decision logic about windows/header generation closer to install_scripts, as it doesn't appear to be used elsewhere. --- setuptools/command/easy_install.py | 15 +++++++++------ setuptools/command/install_scripts.py | 10 ++++++---- setuptools/tests/test_easy_install.py | 6 +++--- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index e52b4736..d8d11d50 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -745,7 +745,7 @@ Please make the appropriate changes for your system and try again. def install_wrapper_scripts(self, dist): if not self.exclude_scripts: - for args in get_script_args(dist): + for args in ScriptWriter._gen_args(dist): self.write_script(*args) def install_script(self, dist, script_name, script_text, dev_path=None): @@ -921,7 +921,7 @@ Please make the appropriate changes for your system and try again. # delete entry-point scripts to avoid duping self.delete_blockers( [os.path.join(script_dir, args[0]) for args in - get_script_args(dist)] + ScriptWriter._gen_args(dist)] ) # Build .egg file from tmpdir bdist_egg.make_zipfile( @@ -1902,15 +1902,18 @@ class ScriptWriter(object): @classmethod def get_script_args(cls, dist, executable=sys_executable, wininst=False): - """ - Yield write_script() argument tuples for a distribution's entrypoints - """ + # for backward compatibility writer = cls.get_writer(wininst) header = get_script_header("", executable, wininst) return writer._gen_args(dist, header) @classmethod - def _gen_args(cls, dist, header): + def _gen_args(cls, dist, header=None): + """ + Yield write_script() argument tuples for a distribution's entrypoints + """ + if header is None: + header = get_script_header("", sys_executable) spec = str(dist.as_requirement()) for type_ in 'console', 'gui': group = type_ + '_scripts' diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index eb79fa3c..eb5ed0f2 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -13,9 +13,9 @@ class install_scripts(orig.install_scripts): self.no_ep = False def run(self): - from setuptools.command.easy_install import get_script_args - from setuptools.command.easy_install import sys_executable - + from setuptools.command.easy_install import ( + ScriptWriter, sys_executable, get_script_header, + ) self.run_command("egg_info") if self.distribution.scripts: orig.install_scripts.run(self) # run first to set up self.outfiles @@ -35,7 +35,9 @@ class install_scripts(orig.install_scripts): is_wininst = getattr( self.get_finalized_command("bdist_wininst"), '_is_running', False ) - for args in get_script_args(dist, executable, is_wininst): + writer = ScriptWriter.get_writer(force_windows=is_wininst) + header = get_script_header("", executable, wininst=is_wininst) + for args in writer._gen_args(dist, header): self.write_script(*args) def write_script(self, script_name, contents, mode="t", *ignored): diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 7baa989a..bc94b0c4 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -22,8 +22,8 @@ from setuptools import compat from setuptools.compat import StringIO, BytesIO, urlparse from setuptools.sandbox import run_setup, SandboxViolation from setuptools.command.easy_install import ( - easy_install, fix_jython_executable, get_script_args, nt_quote_arg, - get_script_header, is_sh, + easy_install, fix_jython_executable, nt_quote_arg, + get_script_header, is_sh, ScriptWriter, ) from setuptools.command.easy_install import PthDistributions from setuptools.command import easy_install as easy_install_pkg @@ -83,7 +83,7 @@ class TestEasyInstallTest: def test_get_script_args(self): dist = FakeDist() - args = next(get_script_args(dist)) + args = next(ScriptWriter._gen_args(dist)) name, script = itertools.islice(args, 2) assert script == WANTED -- cgit v1.2.1 From ef9c3db451e2f24fc8821287e79a1ef48e0c5cf5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 16:43:55 -0500 Subject: Move get_script_header into ScriptWriter --- setuptools/command/easy_install.py | 50 ++++++++++++++++++----------------- setuptools/command/install_scripts.py | 4 ++- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index d8d11d50..c2928c77 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1593,30 +1593,8 @@ def _first_line_re(): def get_script_header(script_text, executable=sys_executable, wininst=False): - """Create a #! line, getting options (if any) from script_text""" - first = (script_text + '\n').splitlines()[0] - match = _first_line_re().match(first) - options = '' - if match: - options = match.group(1) or '' - if options: - options = ' ' + options - if wininst: - executable = "python.exe" - else: - executable = nt_quote_arg(executable) - hdr = "#!%(executable)s%(options)s\n" % locals() - if not isascii(hdr): - # Non-ascii path to sys.executable, use -x to prevent warnings - if options: - if options.strip().startswith('-'): - options = ' -x' + options.strip()[1:] - # else: punt, we can't do it, let the warning happen anyway - else: - options = ' -x' - executable = fix_jython_executable(executable, options) - hdr = "#!%(executable)s%(options)s\n" % locals() - return hdr + executable = "python.exe" if wininst else nt_quote_arg(executable) + return ScriptWriter.get_header(script_text, executable) def auto_chmod(func, arg, exc): @@ -1903,6 +1881,7 @@ class ScriptWriter(object): @classmethod def get_script_args(cls, dist, executable=sys_executable, wininst=False): # for backward compatibility + warnings.warn("Use _gen_args", DeprecationWarning) writer = cls.get_writer(wininst) header = get_script_header("", executable, wininst) return writer._gen_args(dist, header) @@ -1934,6 +1913,29 @@ class ScriptWriter(object): # Simply write the stub with no extension. yield (name, header + script_text) + @classmethod + def get_header(cls, script_text, executable): + """Create a #! line, getting options (if any) from script_text""" + first = (script_text + '\n').splitlines()[0] + match = _first_line_re().match(first) + options = '' + if match: + options = match.group(1) or '' + if options: + options = ' ' + options + hdr = "#!%(executable)s%(options)s\n" % locals() + if not isascii(hdr): + # Non-ascii path to sys.executable, use -x to prevent warnings + if options: + if options.strip().startswith('-'): + options = ' -x' + options.strip()[1:] + # else: punt, we can't do it, let the warning happen anyway + else: + options = ' -x' + executable = fix_jython_executable(executable, options) + hdr = "#!%(executable)s%(options)s\n" % locals() + return hdr + class WindowsScriptWriter(ScriptWriter): @classmethod diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index eb5ed0f2..de74145f 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -35,8 +35,10 @@ class install_scripts(orig.install_scripts): is_wininst = getattr( self.get_finalized_command("bdist_wininst"), '_is_running', False ) + if is_wininst: + executable = "python.exe" writer = ScriptWriter.get_writer(force_windows=is_wininst) - header = get_script_header("", executable, wininst=is_wininst) + header = get_script_header("", executable) for args in writer._gen_args(dist, header): self.write_script(*args) -- cgit v1.2.1 From db3ee08fdba76c74e3f25ae7d7f56117e68223b0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 16:44:19 -0500 Subject: Remove unused imports --- setuptools/tests/test_easy_install.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index bc94b0c4..b42d2c07 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -20,7 +20,7 @@ import mock from setuptools import sandbox from setuptools import compat from setuptools.compat import StringIO, BytesIO, urlparse -from setuptools.sandbox import run_setup, SandboxViolation +from setuptools.sandbox import run_setup from setuptools.command.easy_install import ( easy_install, fix_jython_executable, nt_quote_arg, get_script_header, is_sh, ScriptWriter, @@ -28,7 +28,7 @@ from setuptools.command.easy_install import ( from setuptools.command.easy_install import PthDistributions from setuptools.command import easy_install as easy_install_pkg from setuptools.dist import Distribution -from pkg_resources import working_set, VersionConflict +from pkg_resources import working_set from pkg_resources import Distribution as PRDistribution import setuptools.tests.server import pkg_resources -- cgit v1.2.1 From 390e64c37fb7dcb57b8e6062192e4c4375be8b78 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 16:56:23 -0500 Subject: Moved get_script_header into ScriptWriter class --- setuptools/command/easy_install.py | 11 ++++++----- setuptools/tests/test_easy_install.py | 28 ++++++++++++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index c2928c77..bf648384 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1592,11 +1592,6 @@ def _first_line_re(): return re.compile(first_line_re.pattern.decode()) -def get_script_header(script_text, executable=sys_executable, wininst=False): - executable = "python.exe" if wininst else nt_quote_arg(executable) - return ScriptWriter.get_header(script_text, executable) - - def auto_chmod(func, arg, exc): if func is os.remove and os.name == 'nt': chmod(arg, stat.S_IWRITE) @@ -1886,6 +1881,11 @@ class ScriptWriter(object): header = get_script_header("", executable, wininst) return writer._gen_args(dist, header) + @classmethod + def get_script_header(cls, script_text, executable=sys_executable, wininst=False): + executable = "python.exe" if wininst else nt_quote_arg(executable) + return cls.get_header(script_text, executable) + @classmethod def _gen_args(cls, dist, header=None): """ @@ -2016,6 +2016,7 @@ class WindowsExecutableLauncherWriter(WindowsScriptWriter): # for backward-compatibility get_script_args = ScriptWriter.get_script_args +get_script_header = ScriptWriter.get_script_header def get_win_launcher(type): diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index b42d2c07..5d1068ea 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -23,7 +23,7 @@ from setuptools.compat import StringIO, BytesIO, urlparse from setuptools.sandbox import run_setup from setuptools.command.easy_install import ( easy_install, fix_jython_executable, nt_quote_arg, - get_script_header, is_sh, ScriptWriter, + is_sh, ScriptWriter, ) from setuptools.command.easy_install import PthDistributions from setuptools.command import easy_install as easy_install_pkg @@ -425,15 +425,22 @@ class TestScriptHeader: ) def test_get_script_header(self): expected = '#!%s\n' % nt_quote_arg(os.path.normpath(sys.executable)) - assert get_script_header('#!/usr/local/bin/python') == expected + actual = ScriptWriter.get_script_header('#!/usr/local/bin/python') + assert actual == expected + expected = '#!%s -x\n' % nt_quote_arg(os.path.normpath(sys.executable)) - assert get_script_header('#!/usr/bin/python -x') == expected - candidate = get_script_header('#!/usr/bin/python', + actual = ScriptWriter.get_script_header('#!/usr/bin/python -x') + assert actual == expected + + actual = ScriptWriter.get_script_header('#!/usr/bin/python', executable=self.non_ascii_exe) - assert candidate == '#!%s -x\n' % self.non_ascii_exe - candidate = get_script_header('#!/usr/bin/python', + expected = '#!%s -x\n' % self.non_ascii_exe + assert actual == expected + + actual = ScriptWriter.get_script_header('#!/usr/bin/python', executable=self.exe_with_spaces) - assert candidate == '#!"%s"\n' % self.exe_with_spaces + expected = '#!"%s"\n' % self.exe_with_spaces + assert actual == expected @pytest.mark.xfail( compat.PY3 and os.environ.get("LC_CTYPE") in ("C", "POSIX"), @@ -453,7 +460,8 @@ class TestScriptHeader: f.write(header) exe = str(exe) - header = get_script_header('#!/usr/local/bin/python', executable=exe) + header = ScriptWriter.get_script_header('#!/usr/local/bin/python', + executable=exe) assert header == '#!/usr/bin/env %s\n' % exe expect_out = 'stdout' if sys.version_info < (2,7) else 'stderr' @@ -461,14 +469,14 @@ class TestScriptHeader: with contexts.quiet() as (stdout, stderr): # When options are included, generate a broken shebang line # with a warning emitted - candidate = get_script_header('#!/usr/bin/python -x', + candidate = ScriptWriter.get_script_header('#!/usr/bin/python -x', executable=exe) assert candidate == '#!%s -x\n' % exe output = locals()[expect_out] assert 'Unable to adapt shebang line' in output.getvalue() with contexts.quiet() as (stdout, stderr): - candidate = get_script_header('#!/usr/bin/python', + candidate = ScriptWriter.get_script_header('#!/usr/bin/python', executable=self.non_ascii_exe) assert candidate == '#!%s -x\n' % self.non_ascii_exe output = locals()[expect_out] -- cgit v1.2.1 From c3beddd034239005c98f7285a2936c513c5a81be Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 17:12:37 -0500 Subject: Deprecate and remove usage of easy_install.get_script_header. --- setuptools/command/easy_install.py | 12 ++++++++---- setuptools/command/install_scripts.py | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index bf648384..9eb74159 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -754,7 +754,7 @@ Please make the appropriate changes for your system and try again. is_script = is_python_script(script_text, script_name) if is_script: - script_text = (get_script_header(script_text) + + script_text = (ScriptWriter.get_header(script_text) + self._load_template(dev_path) % locals()) self.write_script(script_name, _to_ascii(script_text), 'b') @@ -1878,11 +1878,13 @@ class ScriptWriter(object): # for backward compatibility warnings.warn("Use _gen_args", DeprecationWarning) writer = cls.get_writer(wininst) - header = get_script_header("", executable, wininst) + header = cls.get_script_header("", executable, wininst) return writer._gen_args(dist, header) @classmethod def get_script_header(cls, script_text, executable=sys_executable, wininst=False): + # for backward compatibility + warnings.warn("Use get_header", DeprecationWarning) executable = "python.exe" if wininst else nt_quote_arg(executable) return cls.get_header(script_text, executable) @@ -1892,7 +1894,7 @@ class ScriptWriter(object): Yield write_script() argument tuples for a distribution's entrypoints """ if header is None: - header = get_script_header("", sys_executable) + header = cls.get_header() spec = str(dist.as_requirement()) for type_ in 'console', 'gui': group = type_ + '_scripts' @@ -1914,8 +1916,10 @@ class ScriptWriter(object): yield (name, header + script_text) @classmethod - def get_header(cls, script_text, executable): + def get_header(cls, script_text="", executable=None): """Create a #! line, getting options (if any) from script_text""" + if executable is None: + executable = nt_quote_arg(sys_executable) first = (script_text + '\n').splitlines()[0] match = _first_line_re().match(first) options = '' diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index de74145f..138e4ea2 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -14,7 +14,7 @@ class install_scripts(orig.install_scripts): def run(self): from setuptools.command.easy_install import ( - ScriptWriter, sys_executable, get_script_header, + ScriptWriter, sys_executable, nt_quote_arg, ) self.run_command("egg_info") if self.distribution.scripts: @@ -38,7 +38,7 @@ class install_scripts(orig.install_scripts): if is_wininst: executable = "python.exe" writer = ScriptWriter.get_writer(force_windows=is_wininst) - header = get_script_header("", executable) + header = ScriptWriter.get_header("", nt_quote_arg(executable)) for args in writer._gen_args(dist, header): self.write_script(*args) -- cgit v1.2.1 From 261d57232c74954468688a76aab2caea80ed42fc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 17:14:11 -0500 Subject: Rename _gen_args to get_args (for consistency). --- setuptools/command/easy_install.py | 10 +++++----- setuptools/command/install_scripts.py | 2 +- setuptools/tests/test_easy_install.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 9eb74159..5c50dbe2 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -745,7 +745,7 @@ Please make the appropriate changes for your system and try again. def install_wrapper_scripts(self, dist): if not self.exclude_scripts: - for args in ScriptWriter._gen_args(dist): + for args in ScriptWriter.get_args(dist): self.write_script(*args) def install_script(self, dist, script_name, script_text, dev_path=None): @@ -921,7 +921,7 @@ Please make the appropriate changes for your system and try again. # delete entry-point scripts to avoid duping self.delete_blockers( [os.path.join(script_dir, args[0]) for args in - ScriptWriter._gen_args(dist)] + ScriptWriter.get_args(dist)] ) # Build .egg file from tmpdir bdist_egg.make_zipfile( @@ -1876,10 +1876,10 @@ class ScriptWriter(object): @classmethod def get_script_args(cls, dist, executable=sys_executable, wininst=False): # for backward compatibility - warnings.warn("Use _gen_args", DeprecationWarning) + warnings.warn("Use get_args", DeprecationWarning) writer = cls.get_writer(wininst) header = cls.get_script_header("", executable, wininst) - return writer._gen_args(dist, header) + return writer.get_args(dist, header) @classmethod def get_script_header(cls, script_text, executable=sys_executable, wininst=False): @@ -1889,7 +1889,7 @@ class ScriptWriter(object): return cls.get_header(script_text, executable) @classmethod - def _gen_args(cls, dist, header=None): + def get_args(cls, dist, header=None): """ Yield write_script() argument tuples for a distribution's entrypoints """ diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index 138e4ea2..1717e1cf 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -39,7 +39,7 @@ class install_scripts(orig.install_scripts): executable = "python.exe" writer = ScriptWriter.get_writer(force_windows=is_wininst) header = ScriptWriter.get_header("", nt_quote_arg(executable)) - for args in writer._gen_args(dist, header): + for args in writer.get_args(dist, header): self.write_script(*args) def write_script(self, script_name, contents, mode="t", *ignored): diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 5d1068ea..f919ae20 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -83,7 +83,7 @@ class TestEasyInstallTest: def test_get_script_args(self): dist = FakeDist() - args = next(ScriptWriter._gen_args(dist)) + args = next(ScriptWriter.get_args(dist)) name, script = itertools.islice(args, 2) assert script == WANTED -- cgit v1.2.1 From 3c78eb2348dff5d493d0cd5a34aef812db8385ef Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 17:20:15 -0500 Subject: Extract method for parsing options. --- setuptools/command/easy_install.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 5c50dbe2..6ec96564 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1920,13 +1920,9 @@ class ScriptWriter(object): """Create a #! line, getting options (if any) from script_text""" if executable is None: executable = nt_quote_arg(sys_executable) - first = (script_text + '\n').splitlines()[0] - match = _first_line_re().match(first) - options = '' - if match: - options = match.group(1) or '' - if options: - options = ' ' + options + + options = cls._extract_options(script_text) + hdr = "#!%(executable)s%(options)s\n" % locals() if not isascii(hdr): # Non-ascii path to sys.executable, use -x to prevent warnings @@ -1940,6 +1936,20 @@ class ScriptWriter(object): hdr = "#!%(executable)s%(options)s\n" % locals() return hdr + @classmethod + def _extract_options(cls, orig_script): + """ + Extract any options from the first line of the script. + """ + first = (orig_script + '\n').splitlines()[0] + match = _first_line_re().match(first) + options = '' + if match: + options = match.group(1) or '' + if options: + options = ' ' + options + return options + class WindowsScriptWriter(ScriptWriter): @classmethod -- cgit v1.2.1 From efba85513b5c11ddbddf785906b5b4e9b596771a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 17:49:21 -0500 Subject: Extract method for handling non-ascii exe. Strip out excess whitespace from option handling. --- setuptools/command/easy_install.py | 37 +++++++++++++++++++---------------- setuptools/tests/test_easy_install.py | 4 ++-- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 6ec96564..61e242d6 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1922,19 +1922,11 @@ class ScriptWriter(object): executable = nt_quote_arg(sys_executable) options = cls._extract_options(script_text) + options = cls._handle_non_ascii_exe(executable, options) + tmpl = '#!{executable} {options}\n' if options else '#!{executable}\n' - hdr = "#!%(executable)s%(options)s\n" % locals() - if not isascii(hdr): - # Non-ascii path to sys.executable, use -x to prevent warnings - if options: - if options.strip().startswith('-'): - options = ' -x' + options.strip()[1:] - # else: punt, we can't do it, let the warning happen anyway - else: - options = ' -x' executable = fix_jython_executable(executable, options) - hdr = "#!%(executable)s%(options)s\n" % locals() - return hdr + return tmpl.format(**locals()) @classmethod def _extract_options(cls, orig_script): @@ -1943,12 +1935,23 @@ class ScriptWriter(object): """ first = (orig_script + '\n').splitlines()[0] match = _first_line_re().match(first) - options = '' - if match: - options = match.group(1) or '' - if options: - options = ' ' + options - return options + options = match.group(1) or '' if match else '' + return options.strip() + + @classmethod + def _handle_non_ascii_exe(cls, executable, options): + if isascii(executable): + return options + + # Non-ascii path to sys.executable, use -x to prevent warnings + if not options: + return '-x' + + if not options.strip().startswith('-'): + # punt, we can't do it, let the warning happen anyway + return options + + return '-x' + options.strip()[1:] class WindowsScriptWriter(ScriptWriter): diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index f919ae20..86870866 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -428,7 +428,7 @@ class TestScriptHeader: actual = ScriptWriter.get_script_header('#!/usr/local/bin/python') assert actual == expected - expected = '#!%s -x\n' % nt_quote_arg(os.path.normpath(sys.executable)) + expected = '#!%s -x\n' % nt_quote_arg(os.path.normpath(sys.executable)) actual = ScriptWriter.get_script_header('#!/usr/bin/python -x') assert actual == expected @@ -471,7 +471,7 @@ class TestScriptHeader: # with a warning emitted candidate = ScriptWriter.get_script_header('#!/usr/bin/python -x', executable=exe) - assert candidate == '#!%s -x\n' % exe + assert candidate == '#!%s -x\n' % exe output = locals()[expect_out] assert 'Unable to adapt shebang line' in output.getvalue() -- cgit v1.2.1 From bd9d38030cee59eb0e2ef9c8fb98fda5b1ff470f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 21:18:09 -0500 Subject: Added new class CommandSpec, which will be used for abstracting the command handling for script headers. --- setuptools/command/easy_install.py | 95 ++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 8 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 61e242d6..bb0d8694 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -60,10 +60,6 @@ import pkg_resources warnings.filterwarnings("default", category=pkg_resources.PEP440Warning) -sys_executable = os.environ.get('__PYVENV_LAUNCHER__', - os.path.normpath(sys.executable)) - - __all__ = [ 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg', 'main', 'get_exe_prefixes', @@ -1855,6 +1851,88 @@ def fix_jython_executable(executable, options): return executable +class CommandSpec(list): + """ + A command spec for a #! header, specified as a list of arguments akin to + those passed to Popen. + """ + + options = [] + _default = os.path.normpath(sys.executable) + launcher = os.environ.get('__PYVENV_LAUNCHER__', _default) + + @classmethod + def from_environment(cls): + return cls.from_string(cls.launcher) + + @classmethod + def from_string(cls, string): + """ + Construct a command spec from a simple string, assumed to represent + the full name to an executable. + """ + return cls._for_jython(string) or cls([string]) + + def install_options(self, script_text): + self.options.extend(self._extract_options(script_text)) + cmdline = subprocess.list2cmdline(self) + if not isascii(cmdline): + self.options[:0] = ['-x'] + + @staticmethod + def _extract_options(orig_script): + """ + Extract any options from the first line of the script. + """ + first = (orig_script + '\n').splitlines()[0] + match = _first_line_re().match(first) + options = match.group(1) or '' if match else '' + return options.strip() + + def as_header(self): + return self._render(self + list(self.options)) + + @staticmethod + def _render(items): + cmdline = subprocess.list2cmdline(items) + return '#!' + cmdline + '\n' + + +class JythonCommandSpec(CommandSpec): + @classmethod + def from_string(cls, string): + """ + On Jython, construct an instance of this class. + On platforms other than Jython, return None. + """ + needs_jython_spec = ( + sys.platform.startswith('java') + and + __import__('java').lang.System.getProperty('os.name') != 'Linux' + ) + return cls([string]) if needs_jython_spec else None + + def as_header(self): + """ + Workaround Jython's sys.executable being a .sh (an invalid + shebang line interpreter) + """ + if not is_sh(self[0]): + return super(JythonCommandSpec, self).as_header() + + if self.options: + # Can't apply the workaround, leave it broken + log.warn( + "WARNING: Unable to adapt shebang line for Jython," + " the following script is NOT executable\n" + " see http://bugs.jython.org/issue1112 for" + " more information.") + return super(JythonCommandSpec, self).as_header() + + items = ['/usr/bin/env'] + self + list(self.options) + return self._render(items) + + class ScriptWriter(object): """ Encapsulates behavior around writing entry point scripts for console and @@ -1874,17 +1952,19 @@ class ScriptWriter(object): """).lstrip() @classmethod - def get_script_args(cls, dist, executable=sys_executable, wininst=False): + def get_script_args(cls, dist, executable=None, wininst=False): # for backward compatibility warnings.warn("Use get_args", DeprecationWarning) + executable = executable or CommandSpec.launcher writer = cls.get_writer(wininst) header = cls.get_script_header("", executable, wininst) return writer.get_args(dist, header) @classmethod - def get_script_header(cls, script_text, executable=sys_executable, wininst=False): + def get_script_header(cls, script_text, executable=None, wininst=False): # for backward compatibility warnings.warn("Use get_header", DeprecationWarning) + executable = executable or CommandSpec.launcher executable = "python.exe" if wininst else nt_quote_arg(executable) return cls.get_header(script_text, executable) @@ -1918,8 +1998,7 @@ class ScriptWriter(object): @classmethod def get_header(cls, script_text="", executable=None): """Create a #! line, getting options (if any) from script_text""" - if executable is None: - executable = nt_quote_arg(sys_executable) + executable = executable or nt_quote_arg(CommandSpec.launcher) options = cls._extract_options(script_text) options = cls._handle_non_ascii_exe(executable, options) -- cgit v1.2.1 From 3ababa264dc404e9f8eae01045a4531b0b5bd692 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 21:31:05 -0500 Subject: Update install_scripts to use CommandSpec for generating script headers. --- setuptools/command/easy_install.py | 13 +++++++++++++ setuptools/command/install_scripts.py | 12 +++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index bb0d8694..5667864b 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1861,6 +1861,19 @@ class CommandSpec(list): _default = os.path.normpath(sys.executable) launcher = os.environ.get('__PYVENV_LAUNCHER__', _default) + @classmethod + def from_param(cls, param): + """ + Construct a CommandSpec from a parameter to build_scripts, which may + be None. + """ + if isinstance(param, cls): + return param + if param is None: + return cls.from_environment() + # otherwise, assume it's a string. + return cls.from_string(param) + @classmethod def from_environment(cls): return cls.from_string(cls.launcher) diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index 1717e1cf..722b0566 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -13,9 +13,8 @@ class install_scripts(orig.install_scripts): self.no_ep = False def run(self): - from setuptools.command.easy_install import ( - ScriptWriter, sys_executable, nt_quote_arg, - ) + from setuptools.command.easy_install import ScriptWriter, CommandSpec + self.run_command("egg_info") if self.distribution.scripts: orig.install_scripts.run(self) # run first to set up self.outfiles @@ -31,15 +30,14 @@ class install_scripts(orig.install_scripts): ei_cmd.egg_name, ei_cmd.egg_version, ) bs_cmd = self.get_finalized_command('build_scripts') - executable = getattr(bs_cmd, 'executable', sys_executable) + cmd = CommandSpec.from_param(getattr(bs_cmd, 'executable', None)) is_wininst = getattr( self.get_finalized_command("bdist_wininst"), '_is_running', False ) if is_wininst: - executable = "python.exe" + cmd = CommandSpec.from_string("python.exe") writer = ScriptWriter.get_writer(force_windows=is_wininst) - header = ScriptWriter.get_header("", nt_quote_arg(executable)) - for args in writer.get_args(dist, header): + for args in writer.get_args(dist, cmd.as_header()): self.write_script(*args) def write_script(self, script_name, contents, mode="t", *ignored): -- cgit v1.2.1 From 254c2f03c69fd6ae34e70c1f89cb7ccbc4b5fed3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 21:44:38 -0500 Subject: Use CommandSpec in get_script_header --- setuptools/command/easy_install.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 5667864b..f075200c 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -36,6 +36,7 @@ import site import struct import contextlib import subprocess +import shlex from setuptools import Command from setuptools.sandbox import run_setup @@ -1884,10 +1885,10 @@ class CommandSpec(list): Construct a command spec from a simple string, assumed to represent the full name to an executable. """ - return cls._for_jython(string) or cls([string]) + return JythonCommandSpec.from_string(string) or cls([string]) def install_options(self, script_text): - self.options.extend(self._extract_options(script_text)) + self.options = shlex.split(self._extract_options(script_text)) cmdline = subprocess.list2cmdline(self) if not isascii(cmdline): self.options[:0] = ['-x'] @@ -1977,9 +1978,11 @@ class ScriptWriter(object): def get_script_header(cls, script_text, executable=None, wininst=False): # for backward compatibility warnings.warn("Use get_header", DeprecationWarning) - executable = executable or CommandSpec.launcher - executable = "python.exe" if wininst else nt_quote_arg(executable) - return cls.get_header(script_text, executable) + if wininst: + executable = "python.exe" + cmd = CommandSpec.from_param(executable) + cmd.install_options(script_text) + return cmd.as_header() @classmethod def get_args(cls, dist, header=None): -- cgit v1.2.1 From 126d971737a7b0fc89b0b84c2b48f6fd139df729 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 21:53:03 -0500 Subject: Use CommandSpec in ScriptWriter, removing now unused methods. --- setuptools/command/easy_install.py | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index f075200c..7f8a9800 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -2014,39 +2014,9 @@ class ScriptWriter(object): @classmethod def get_header(cls, script_text="", executable=None): """Create a #! line, getting options (if any) from script_text""" - executable = executable or nt_quote_arg(CommandSpec.launcher) - - options = cls._extract_options(script_text) - options = cls._handle_non_ascii_exe(executable, options) - tmpl = '#!{executable} {options}\n' if options else '#!{executable}\n' - - executable = fix_jython_executable(executable, options) - return tmpl.format(**locals()) - - @classmethod - def _extract_options(cls, orig_script): - """ - Extract any options from the first line of the script. - """ - first = (orig_script + '\n').splitlines()[0] - match = _first_line_re().match(first) - options = match.group(1) or '' if match else '' - return options.strip() - - @classmethod - def _handle_non_ascii_exe(cls, executable, options): - if isascii(executable): - return options - - # Non-ascii path to sys.executable, use -x to prevent warnings - if not options: - return '-x' - - if not options.strip().startswith('-'): - # punt, we can't do it, let the warning happen anyway - return options - - return '-x' + options.strip()[1:] + cmd = CommandSpec.from_param(executable) + cmd.install_options(script_text) + return cmd.as_header() class WindowsScriptWriter(ScriptWriter): -- cgit v1.2.1 From ab6887a55394c77982212c058c59addeb77736f7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 22:02:56 -0500 Subject: Remove redundant line --- setuptools/command/easy_install.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 7f8a9800..0b24c8e3 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1969,7 +1969,6 @@ class ScriptWriter(object): def get_script_args(cls, dist, executable=None, wininst=False): # for backward compatibility warnings.warn("Use get_args", DeprecationWarning) - executable = executable or CommandSpec.launcher writer = cls.get_writer(wininst) header = cls.get_script_header("", executable, wininst) return writer.get_args(dist, header) -- cgit v1.2.1 From 6ab7d6dbb13e0ef1f44bf0461f3ffdb06f07b3b2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 22:11:08 -0500 Subject: Add test demonstrating how a custom launch command spec that could be passed as the script executable. --- setuptools/tests/test_easy_install.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 86870866..3a8ddbfb 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -23,7 +23,7 @@ from setuptools.compat import StringIO, BytesIO, urlparse from setuptools.sandbox import run_setup from setuptools.command.easy_install import ( easy_install, fix_jython_executable, nt_quote_arg, - is_sh, ScriptWriter, + is_sh, ScriptWriter, CommandSpec, ) from setuptools.command.easy_install import PthDistributions from setuptools.command import easy_install as easy_install_pkg @@ -481,3 +481,21 @@ class TestScriptHeader: assert candidate == '#!%s -x\n' % self.non_ascii_exe output = locals()[expect_out] assert 'Unable to adapt shebang line' in output.getvalue() + + +class TestCommandSpec: + def test_custom_launch_command(self): + """ + Show how a custom CommandSpec could be used to specify a #! executable + which takes parameters. + """ + cmd = CommandSpec(['/usr/bin/env', 'python3']) + assert cmd.as_header() == '#!/usr/bin/env python3\n' + + def test_from_param_for_CommandSpec_is_passthrough(self): + """ + from_param should return an instance of a CommandSpec + """ + cmd = CommandSpec(['python']) + cmd_new = CommandSpec.from_param(cmd) + assert cmd is cmd_new -- cgit v1.2.1 From 4356a2dc99a74be0d970f63e045eba40f463695d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 22:22:44 -0500 Subject: Allow CommandSpec to be constructed simply from a list. --- setuptools/command/easy_install.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 0b24c8e3..fb953dbb 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1870,6 +1870,8 @@ class CommandSpec(list): """ if isinstance(param, cls): return param + if isinstance(param, list): + return cls(param) if param is None: return cls.from_environment() # otherwise, assume it's a string. -- cgit v1.2.1 From 0ad48553589fc68faeb7a5fc2f76da128249ac86 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 22:29:37 -0500 Subject: Add test capturing expectation around sys.executable having spaces in the name. --- setuptools/command/easy_install.py | 9 ++++++--- setuptools/tests/test_easy_install.py | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index fb953dbb..54a3bc3a 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1859,8 +1859,11 @@ class CommandSpec(list): """ options = [] - _default = os.path.normpath(sys.executable) - launcher = os.environ.get('__PYVENV_LAUNCHER__', _default) + + @classmethod + def _sys_executable(cls): + _default = os.path.normpath(sys.executable) + return os.environ.get('__PYVENV_LAUNCHER__', _default) @classmethod def from_param(cls, param): @@ -1879,7 +1882,7 @@ class CommandSpec(list): @classmethod def from_environment(cls): - return cls.from_string(cls.launcher) + return cls.from_string(cls._sys_executable()) @classmethod def from_string(cls, string): diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 3a8ddbfb..e1f06788 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -499,3 +499,9 @@ class TestCommandSpec: cmd = CommandSpec(['python']) cmd_new = CommandSpec.from_param(cmd) assert cmd is cmd_new + + def test_from_environment_with_spaces_in_executable(self): + with mock.patch('sys.executable', TestScriptHeader.exe_with_spaces): + cmd = CommandSpec.from_environment() + assert len(cmd) == 1 + assert cmd.as_header().startswith('#!"') -- cgit v1.2.1 From 3b68368e30aa51d4a7f96053501c604a8cb6fe42 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 22:44:28 -0500 Subject: Change the way string values are interpreted from build.executable - now they must be quoted or otherwise escaped suitable for parsing by shlex.split. --- setuptools/command/easy_install.py | 9 +++++---- setuptools/tests/test_easy_install.py | 9 +++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 54a3bc3a..340b1fac 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1882,15 +1882,16 @@ class CommandSpec(list): @classmethod def from_environment(cls): - return cls.from_string(cls._sys_executable()) + return cls.from_string('"' + cls._sys_executable() + '"') @classmethod def from_string(cls, string): """ - Construct a command spec from a simple string, assumed to represent - the full name to an executable. + Construct a command spec from a simple string representing a command + line parseable by shlex.split. """ - return JythonCommandSpec.from_string(string) or cls([string]) + items = shlex.split(string) + return JythonCommandSpec.from_string(string) or cls(items) def install_options(self, script_text): self.options = shlex.split(self._extract_options(script_text)) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index e1f06788..a3d5b0a9 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -505,3 +505,12 @@ class TestCommandSpec: cmd = CommandSpec.from_environment() assert len(cmd) == 1 assert cmd.as_header().startswith('#!"') + + def test_from_simple_string_uses_shlex(self): + """ + In order to support `executable = /usr/bin/env my-python`, make sure + from_param invokes shlex on that input. + """ + cmd = CommandSpec.from_param('/usr/bin/env my-python') + assert len(cmd) == 2 + assert '"' not in cmd.as_header() -- cgit v1.2.1 From b2c646684986070b34b92aef52d2f57391c99626 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 22:45:56 -0500 Subject: Fix failing test (now that expectation is different). --- setuptools/tests/test_easy_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index a3d5b0a9..72b040e1 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -438,7 +438,7 @@ class TestScriptHeader: assert actual == expected actual = ScriptWriter.get_script_header('#!/usr/bin/python', - executable=self.exe_with_spaces) + executable='"'+self.exe_with_spaces+'"') expected = '#!"%s"\n' % self.exe_with_spaces assert actual == expected -- cgit v1.2.1 From 81df10c70a695360683d76daa1737ba3feb56f6f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 22:48:07 -0500 Subject: Update note in changelog --- CHANGES.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 8fc9e981..d6cf236a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,15 @@ CHANGES ======= +---- +12.0 +---- + +* Issue #188: Setuptools now support multiple entities in the value for + ``build.executable``, such that an executable of "/usr/bin/env my-python" may + be specified. This means that systems with a specified executable whose name + has spaces in the path must be updated to escape or quote that value. + ---- 11.1 ---- -- cgit v1.2.1 From 3ba436a301a5e020de8c33fbeca016c205511f4a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 Jan 2015 12:58:07 -0500 Subject: Bump stacklevel to 2 to inform the caller of the issue. --- pkg_resources/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index a0b354ff..0e6223de 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2261,6 +2261,7 @@ class EntryPoint(object): "`require` parameter is deprecated. Use " "EntryPoint._load instead.", DeprecationWarning, + stacklevel=2, ) return self._load() -- cgit v1.2.1 From 0a655117169b85d529c6f65c8895ad4bff824b6f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 Jan 2015 13:00:26 -0500 Subject: Update changelog --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 8fc9e981..956b1ad4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,12 @@ CHANGES ======= +---- +11.2 +---- + +* Pip #2326: Report deprecation warning at stacklevel 2 for easier diagnosis. + ---- 11.1 ---- -- cgit v1.2.1 From 85df7c83592f997764717253a5f7c23caaf7b966 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 Jan 2015 13:03:22 -0500 Subject: Added tag 11.2 for changeset feb5971e7827 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 021c8ff4..c9664970 100644 --- a/.hgtags +++ b/.hgtags @@ -183,3 +183,4 @@ fa069bf2411a150c9379d31a04d1c3836e2d3027 9.0.1 1f5de53c079d577ead9d80265c9e006503b16457 10.2.1 b4b92805bc0e9802da0b597d00df4fa42b30bc40 11.0 6cd2b18f4be2a9c188fa505b34505b32f4a4554b 11.1 +feb5971e7827483bbdeb67613126bb79ed09e6d9 11.2 -- cgit v1.2.1 From b38ede5b91f82c552f1d79a0346ea5f24b0b7d1a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 Jan 2015 13:03:59 -0500 Subject: Bumped to 11.3 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 388ff490..e3de2829 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "11.2" +DEFAULT_VERSION = "11.3" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index a6fd3e36..b1a75f41 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '11.2' +__version__ = '11.3' -- cgit v1.2.1 From dd0ef1f363e42a8859889ba319b37a29c1f03855 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 Jan 2015 13:07:42 -0500 Subject: Add support for linkifying pip issues. --- linkify.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linkify.py b/linkify.py index e7b3ca7b..5c6e16b4 100644 --- a/linkify.py +++ b/linkify.py @@ -15,6 +15,7 @@ link_patterns = [ r"Jython #(?P\d+)", r"Python #(?P\d+)", r"Interop #(?P\d+)", + r"Pip #(?P\d+)", ] issue_urls = dict( @@ -27,6 +28,7 @@ issue_urls = dict( jython='http://bugs.jython.org/issue{jython}', python='http://bugs.python.org/issue{python}', interop='https://github.com/pypa/interoperability-peps/issues/{interop}', + pip='https://github.com/pypa/pip/issues/{pip}', ) -- cgit v1.2.1 From 7fa87f2fbdf84d414e069ca96f6c6d860d7e0505 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 Jan 2015 13:12:16 -0500 Subject: Update changelog. --- CHANGES.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 956b1ad4..9ebfb145 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -36,7 +36,9 @@ CHANGES 10.2 ---- -* Deprecated use of EntryPoint.load(require=False). +* Deprecated use of EntryPoint.load(require=False). Passing a boolean to a + function to select behavior is an anti-pattern. Instead use + ``Entrypoint._load()``. * Substantial refactoring of all unit tests. Tests are now much leaner and re-use a lot of fixtures and contexts for better clarity of purpose. -- cgit v1.2.1 From 92a553d3adeb431cdf92b136ac9ccc3f2ef98bf1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 Jan 2015 14:21:41 -0500 Subject: Add EntryPoint.resolve and deprecate most usage of EntryPoint.load. Removed EntryPoint._load. --- CHANGES.txt | 14 ++++++++++++++ pkg_resources/__init__.py | 22 ++++++++++++++-------- setuptools/command/test.py | 2 +- setuptools/dist.py | 2 +- setuptools/tests/test_sdist.py | 2 +- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 9ebfb145..ab93a9c6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,20 @@ CHANGES ======= +---- +11.3 +---- + +* Expose ``EntryPoint.resolve`` in place of EntryPoint._load, implementing the + simple, non-requiring load. Deprecated all uses of ``EntryPoint._load`` + except for calling with no parameters, which is just a shortcut for + ``ep.require(); ep.resolve();``. + + Apps currently invoking ``ep.load(require=False)`` should instead do the + following if wanting to avoid the deprecating warning:: + + getattr(ep, "resolve", lambda: ep.load(require=False))() + ---- 11.2 ---- diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index b31ae532..fd8efaa8 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2294,19 +2294,25 @@ class EntryPoint(object): def __repr__(self): return "EntryPoint.parse(%r)" % str(self) - def load(self, require=True, env=None, installer=None): - if require: - self.require(env, installer) - else: + def load(self, require=True, *args, **kwargs): + """ + Require packages for this EntryPoint, then resolve it. + """ + if not require or args or kwargs: warnings.warn( - "`require` parameter is deprecated. Use " - "EntryPoint._load instead.", + "Parameters to load are deprecated. Call .resolve and " + ".require separately.", DeprecationWarning, stacklevel=2, ) - return self._load() + if require: + self.require(*args, **kwargs) + return self.resolve() - def _load(self): + def resolve(self): + """ + Resolve the entry point from its module and attrs. + """ module = __import__(self.module_name, fromlist=['__name__'], level=0) try: return functools.reduce(getattr, self.attrs, module) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 2bf5cb16..42689f70 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -172,4 +172,4 @@ class test(Command): if val is None: return parsed = EntryPoint.parse("x=" + val) - return parsed._load()() + return parsed.resolve()() diff --git a/setuptools/dist.py b/setuptools/dist.py index 1917a610..bc29b131 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -434,7 +434,7 @@ class Distribution(_Distribution): for ep in pkg_resources.iter_entry_points('distutils.commands'): if ep.name not in self.cmdclass: # don't require extras as the commands won't be invoked - cmdclass = ep._load() + cmdclass = ep.resolve() self.cmdclass[ep.name] = cmdclass return _Distribution.print_commands(self) diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index d3494d7a..9013b505 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -415,5 +415,5 @@ def test_default_revctrl(): """ ep_def = 'svn_cvs = setuptools.command.sdist:_default_revctrl' ep = pkg_resources.EntryPoint.parse(ep_def) - res = ep._load() + res = ep.resolve() assert hasattr(res, '__iter__') -- cgit v1.2.1 From 94391e16a7c821df85a00c82a48b3326d7155fc4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 Jan 2015 14:23:33 -0500 Subject: Added tag 11.3 for changeset a1a6a1ac9113 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c9664970..cef45b3b 100644 --- a/.hgtags +++ b/.hgtags @@ -184,3 +184,4 @@ fa069bf2411a150c9379d31a04d1c3836e2d3027 9.0.1 b4b92805bc0e9802da0b597d00df4fa42b30bc40 11.0 6cd2b18f4be2a9c188fa505b34505b32f4a4554b 11.1 feb5971e7827483bbdeb67613126bb79ed09e6d9 11.2 +a1a6a1ac9113b90009052ca7263174a488434099 11.3 -- cgit v1.2.1 From 6fe9a6147ff850b64ffc241f65c2411f53fb34c4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 Jan 2015 14:24:10 -0500 Subject: Bumped to 11.4 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index e3de2829..1b567ef7 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "11.3" +DEFAULT_VERSION = "11.4" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index b1a75f41..cef537ae 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '11.3' +__version__ = '11.4' -- cgit v1.2.1 From 32ce474415accc4ad11fdbab57f7a65176d4197b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 6 Jan 2015 09:48:30 -0500 Subject: Restore support for printable characters in the entry point name. Fixes #327. --- CHANGES.txt | 7 +++++++ pkg_resources/__init__.py | 2 +- pkg_resources/tests/test_resources.py | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index ab93a9c6..5fce5d9c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +------ +11.3.1 +------ + +* Issue #327: Formalize and restore support for any printable character in an + entry point name. + ---- 11.3 ---- diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index fd8efaa8..c0c095b2 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2328,7 +2328,7 @@ class EntryPoint(object): pattern = re.compile( r'\s*' - r'(?P[+\w. -]+?)\s*' + r'(?P.+?)\s*' r'=\s*' r'(?P[\w.]+)\s*' r'(:\s*(?P[\w.]+))?\s*' diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index f252ddff..4a82167b 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -2,6 +2,7 @@ import os import sys import tempfile import shutil +import string import pytest @@ -302,6 +303,16 @@ class TestEntryPoints: except ValueError: pass else: raise AssertionError("Should've been bad", ep) + def test_printable_name(self): + """ + Allow any printable character in the name. + """ + # Create a name with all printable characters; strip the whitespace. + name = string.printable.strip() + spec = "{name} = module:attr".format(**locals()) + ep = EntryPoint.parse(spec) + assert ep.name == name + def checkSubMap(self, m): assert len(m) == len(self.submap_expect) for key, ep in pkg_resources.iteritems(self.submap_expect): -- cgit v1.2.1 From 1524a98d7e0e5344134ef51e77cfe5a04e582a8f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 6 Jan 2015 10:01:51 -0500 Subject: Equal signs are now allowed in entry point names. --- pkg_resources/tests/test_resources.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 4a82167b..00ba0cf5 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -297,7 +297,7 @@ class TestEntryPoints: def testRejects(self): for ep in [ - "foo", "x=1=2", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2", + "foo", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2", ]: try: EntryPoint.parse(ep) except ValueError: pass -- cgit v1.2.1 From de11e9e9b57db01e029657acb1148a9fd70581b5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 6 Jan 2015 10:02:44 -0500 Subject: Refactor for clarity --- pkg_resources/tests/test_resources.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 00ba0cf5..36cb6482 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -296,9 +296,8 @@ class TestEntryPoints: assert ep.name == 'html+mako' def testRejects(self): - for ep in [ - "foo", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2", - ]: + specs = "foo", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2" + for ep in specs: try: EntryPoint.parse(ep) except ValueError: pass else: raise AssertionError("Should've been bad", ep) -- cgit v1.2.1 From 9d04e13b60ccd4ec6058c31e219d6e7d124f9574 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 6 Jan 2015 10:07:03 -0500 Subject: Use pytests parametrize to create separate tests for each spec --- pkg_resources/tests/test_resources.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 36cb6482..9c1eaeec 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -295,12 +295,12 @@ class TestEntryPoints: ep = EntryPoint.parse(spec) assert ep.name == 'html+mako' - def testRejects(self): - specs = "foo", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2" - for ep in specs: - try: EntryPoint.parse(ep) - except ValueError: pass - else: raise AssertionError("Should've been bad", ep) + reject_specs = "foo", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2" + @pytest.mark.parametrize("reject_spec", reject_specs) + def test_reject_spec(self, reject_spec): + try: EntryPoint.parse(reject_spec) + except ValueError: pass + else: raise AssertionError("Should've been bad", reject_spec) def test_printable_name(self): """ -- cgit v1.2.1 From 7d4bd8dabb45242671527282474c84179c967ede Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 6 Jan 2015 10:08:15 -0500 Subject: Use pytest.raises for brevity and clarity of purpose. --- pkg_resources/tests/test_resources.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 9c1eaeec..a55478a2 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -298,9 +298,8 @@ class TestEntryPoints: reject_specs = "foo", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2" @pytest.mark.parametrize("reject_spec", reject_specs) def test_reject_spec(self, reject_spec): - try: EntryPoint.parse(reject_spec) - except ValueError: pass - else: raise AssertionError("Should've been bad", reject_spec) + with pytest.raises(ValueError): + EntryPoint.parse(reject_spec) def test_printable_name(self): """ -- cgit v1.2.1 From 37c72186f7cd585a0ceab8d11c3baede009ca961 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 6 Jan 2015 10:11:49 -0500 Subject: Bumped to 11.3.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 1b567ef7..955a8008 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "11.4" +DEFAULT_VERSION = "11.3.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index cef537ae..6e50490a 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '11.4' +__version__ = '11.3.1' -- cgit v1.2.1 From 6c02bf0985ae092a1ac94d8176b6e710675e9ccb Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 6 Jan 2015 10:11:53 -0500 Subject: Added tag 11.3.1 for changeset 1116e568f534 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index cef45b3b..343bfa9e 100644 --- a/.hgtags +++ b/.hgtags @@ -185,3 +185,4 @@ b4b92805bc0e9802da0b597d00df4fa42b30bc40 11.0 6cd2b18f4be2a9c188fa505b34505b32f4a4554b 11.1 feb5971e7827483bbdeb67613126bb79ed09e6d9 11.2 a1a6a1ac9113b90009052ca7263174a488434099 11.3 +1116e568f534ad8f4f41328a0f5fa183eb739c90 11.3.1 -- cgit v1.2.1 From a8f60a73238ae67e0c5a04e437fd9f4edf08bbd6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 6 Jan 2015 10:12:28 -0500 Subject: Bumped to 11.3.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 955a8008..f1e4aeae 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "11.3.1" +DEFAULT_VERSION = "11.3.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index 6e50490a..1e71f92d 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '11.3.1' +__version__ = '11.3.2' -- cgit v1.2.1 From 74637dd638a30c153d9af60688078c7e12d810d3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 21:23:57 -0500 Subject: Extract Exception saving behavior. --- setuptools/sandbox.py | 70 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 7971f42c..37d89a2a 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -92,6 +92,37 @@ def pushd(target): os.chdir(saved) +class ExceptionSaver: + """ + A Context Manager that will save an exception, serialized, and restore it + later. + """ + def __enter__(self): + return self + + def __exit__(self, type, exc, tb): + if not exc: + return + + # dump the exception + self.saved_type = pickle.dumps(type) + self.saved_exc = pickle.dumps(exc) + self.tb = tb + + # suppress the exception + return True + + def resume(self): + "restore and re-raise any exception" + + if 'saved_exc' not in vars(self): + return + + type = pickle.loads(self.saved_type) + exc = pickle.loads(self.saved_exc) + compat.reraise(type, exc, self.tb) + + @contextlib.contextmanager def save_modules(): """ @@ -101,31 +132,20 @@ def save_modules(): outside the context. """ saved = sys.modules.copy() - try: - try: - yield saved - except: - # dump any exception - class_, exc, tb = sys.exc_info() - saved_cls = pickle.dumps(class_) - saved_exc = pickle.dumps(exc) - raise - finally: - sys.modules.update(saved) - # remove any modules imported since - del_modules = ( - mod_name for mod_name in sys.modules - if mod_name not in saved - # exclude any encodings modules. See #285 - and not mod_name.startswith('encodings.') - ) - _clear_modules(del_modules) - except: - # reload and re-raise any exception, using restored modules - class_, exc, tb = sys.exc_info() - new_cls = pickle.loads(saved_cls) - new_exc = pickle.loads(saved_exc) - compat.reraise(new_cls, new_exc, tb) + with ExceptionSaver() as saved_exc: + yield saved + + sys.modules.update(saved) + # remove any modules imported since + del_modules = ( + mod_name for mod_name in sys.modules + if mod_name not in saved + # exclude any encodings modules. See #285 + and not mod_name.startswith('encodings.') + ) + _clear_modules(del_modules) + + saved_exc.resume() def _clear_modules(module_names): -- cgit v1.2.1 From 19c95d3ef6dba78bf6431b6b13d000bc19e84cd6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 21:24:17 -0500 Subject: Remove unused import --- setuptools/tests/test_sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index cadc4812..9a2a6b7b 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -7,7 +7,7 @@ import pytest import pkg_resources import setuptools.sandbox -from setuptools.sandbox import DirectorySandbox, SandboxViolation +from setuptools.sandbox import DirectorySandbox class TestSandbox: -- cgit v1.2.1 From c10a38e97daf7aad2167b3b444be8542dccc652e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 21:32:39 -0500 Subject: Add tests for new ExceptionSaver --- setuptools/tests/test_sandbox.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index 9a2a6b7b..33fb3329 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -54,3 +54,31 @@ class TestSandbox: with setup_py.open('wb') as stream: stream.write(b'"degenerate script"\r\n') setuptools.sandbox._execfile(str(setup_py), globals()) + + +class TestExceptionSaver: + def test_exception_trapped(self): + with setuptools.sandbox.ExceptionSaver(): + raise ValueError("details") + + def test_exception_resumed(self): + with setuptools.sandbox.ExceptionSaver() as saved_exc: + raise ValueError("details") + + with pytest.raises(ValueError) as caught: + saved_exc.resume() + + assert isinstance(caught.value, ValueError) + assert str(caught.value) == 'details' + + def test_exception_reconstructed(self): + orig_exc = ValueError("details") + + with setuptools.sandbox.ExceptionSaver() as saved_exc: + raise orig_exc + + with pytest.raises(ValueError) as caught: + saved_exc.resume() + + assert isinstance(caught.value, ValueError) + assert caught.value is not orig_exc -- cgit v1.2.1 From a33a5ba6ed5be3affc10fd0e789799b7490d2053 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 21:38:25 -0500 Subject: Adding test for non-exceptional condition. --- setuptools/tests/test_sandbox.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index 33fb3329..1340cecf 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -82,3 +82,9 @@ class TestExceptionSaver: assert isinstance(caught.value, ValueError) assert caught.value is not orig_exc + + def test_no_exception_passes_quietly(self): + with setuptools.sandbox.ExceptionSaver() as saved_exc: + pass + + saved_exc.resume() -- cgit v1.2.1 From 9948d3c8a7880cbc13012e8a3fedda130614601d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 21:40:02 -0500 Subject: Make attributes private and remove redundant naming. --- setuptools/sandbox.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 37d89a2a..0847ef41 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -105,9 +105,9 @@ class ExceptionSaver: return # dump the exception - self.saved_type = pickle.dumps(type) - self.saved_exc = pickle.dumps(exc) - self.tb = tb + self._type = pickle.dumps(type) + self._exc = pickle.dumps(exc) + self._tb = tb # suppress the exception return True @@ -115,12 +115,12 @@ class ExceptionSaver: def resume(self): "restore and re-raise any exception" - if 'saved_exc' not in vars(self): + if '_exc' not in vars(self): return - type = pickle.loads(self.saved_type) - exc = pickle.loads(self.saved_exc) - compat.reraise(type, exc, self.tb) + type = pickle.loads(self._type) + exc = pickle.loads(self._exc) + compat.reraise(type, exc, self._tb) @contextlib.contextmanager -- cgit v1.2.1 From 9c3d6750cbef8e0673e4123aa39149e28a8a098e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 21:49:12 -0500 Subject: Add test capturing failure when the Exception is not pickleable. Ref #329. --- setuptools/tests/test_sandbox.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index 1340cecf..6e1e9e1c 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -88,3 +88,15 @@ class TestExceptionSaver: pass saved_exc.resume() + + def test_unpickleable_exception(self): + class CantPickleThis(Exception): + "This Exception is unpickleable because it's not in globals" + + with setuptools.sandbox.ExceptionSaver() as saved_exc: + raise CantPickleThis('detail') + + with pytest.raises(setuptools.sandbox.UnpickleableException) as caught: + saved_exc.resume() + + assert str(caught.value) == "CantPickleThis('detail',)" -- cgit v1.2.1 From 9cf04f13f2ff72a7befa15f8f4835d2c662508e6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 22:06:09 -0500 Subject: Wrap unpickleable exceptions in another class. Fixes #329. --- setuptools/sandbox.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 0847ef41..83283ca3 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -92,6 +92,22 @@ def pushd(target): os.chdir(saved) +class UnpickleableException(Exception): + """ + An exception representing another Exception that could not be pickled. + """ + @classmethod + def dump(cls, type, exc): + """ + Always return a dumped (pickled) type and exc. If exc can't be pickled, + wrap it in UnpickleableException first. + """ + try: + return pickle.dumps(type), pickle.dumps(exc) + except Exception: + return cls.dump(cls, cls(repr(exc))) + + class ExceptionSaver: """ A Context Manager that will save an exception, serialized, and restore it @@ -105,8 +121,7 @@ class ExceptionSaver: return # dump the exception - self._type = pickle.dumps(type) - self._exc = pickle.dumps(exc) + self._saved = UnpickleableException.dump(type, exc) self._tb = tb # suppress the exception @@ -115,11 +130,10 @@ class ExceptionSaver: def resume(self): "restore and re-raise any exception" - if '_exc' not in vars(self): + if '_saved' not in vars(self): return - type = pickle.loads(self._type) - exc = pickle.loads(self._exc) + type, exc = map(pickle.loads, self._saved) compat.reraise(type, exc, self._tb) -- cgit v1.2.1 From 72d5cc0b9ea095437bf2796298dd3658624c081e Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Fri, 9 Jan 2015 09:40:48 +0000 Subject: Access os.environ[key], not os.environ['key'] --- setuptools/tests/contexts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/contexts.py b/setuptools/tests/contexts.py index d06a333f..4a461765 100644 --- a/setuptools/tests/contexts.py +++ b/setuptools/tests/contexts.py @@ -27,7 +27,7 @@ def environment(**replacements): to clear the values. """ saved = dict( - (key, os.environ['key']) + (key, os.environ[key]) for key in replacements if key in os.environ ) -- cgit v1.2.1 From 35b0d82423b88702bbaaa20436b28720c70e3a6d Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Mon, 12 Jan 2015 17:31:44 -0500 Subject: Fix tox settings so they work Update the dependency list to include the mock package. Update the way py.test is called to only scan the setuptools directory, to avoid scanning all of the packages installed in .tox and other temporary directories. --- tox.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 1ac46202..7aeffdd8 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,7 @@ [tox] envlist = py26,py27,py31,py32,py33,py34 [testenv] -deps=pytest -commands=py.test {posargs} +deps= + pytest + mock +commands=py.test setuptools {posargs} -- cgit v1.2.1 From cde1eb84bd1813ff4425fe6f05cbdeba8e410c13 Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Thu, 15 Jan 2015 23:25:04 +0100 Subject: Use unittest.mock from standard library instead of external mock with Python >=3.3. --- setup.py | 3 +-- setuptools/tests/fixtures.py | 5 ++++- setuptools/tests/test_easy_install.py | 5 ++++- setuptools/tests/test_msvc9compiler.py | 5 ++++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index b4b93b38..63093917 100755 --- a/setup.py +++ b/setup.py @@ -170,8 +170,7 @@ setup_params = dict( tests_require=[ 'setuptools[ssl]', 'pytest', - 'mock', - ], + ] + (['mock'] if sys.version_info[:2] < (3, 3) else []), setup_requires=[ ] + pytest_runner, ) diff --git a/setuptools/tests/fixtures.py b/setuptools/tests/fixtures.py index 0b1eaf5f..c70c38cb 100644 --- a/setuptools/tests/fixtures.py +++ b/setuptools/tests/fixtures.py @@ -1,4 +1,7 @@ -import mock +try: + from unittest import mock +except ImportError: + import mock import pytest from . import contexts diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 72b040e1..689860c3 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -15,7 +15,10 @@ import logging import itertools import pytest -import mock +try: + from unittest import mock +except ImportError: + import mock from setuptools import sandbox from setuptools import compat diff --git a/setuptools/tests/test_msvc9compiler.py b/setuptools/tests/test_msvc9compiler.py index a0820fff..e54e7a6e 100644 --- a/setuptools/tests/test_msvc9compiler.py +++ b/setuptools/tests/test_msvc9compiler.py @@ -7,7 +7,10 @@ import contextlib import distutils.errors import pytest -import mock +try: + from unittest import mock +except ImportError: + import mock from . import contexts -- cgit v1.2.1 From 1cd6c9a1f6840ff82217a9e7059b8ec7049f3a32 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 15 Jan 2015 19:41:04 -0500 Subject: Skip integration tests when SSL is broken. Ref #317. --- setuptools/tests/test_integration.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setuptools/tests/test_integration.py b/setuptools/tests/test_integration.py index 92a27080..90bb4313 100644 --- a/setuptools/tests/test_integration.py +++ b/setuptools/tests/test_integration.py @@ -12,6 +12,7 @@ import pytest from setuptools.command.easy_install import easy_install from setuptools.command import easy_install as easy_install_pkg from setuptools.dist import Distribution +from setuptools.compat import urlopen def setup_module(module): @@ -24,6 +25,11 @@ def setup_module(module): except ImportError: pass + try: + urlopen('https://pypi.python.org/pypi') + except Exception as exc: + pytest.skip(reason=str(exc)) + @pytest.fixture def install_context(request, tmpdir, monkeypatch): -- cgit v1.2.1 From 3558c1a03584064e9bb86d3886009902eec6832d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 15 Jan 2015 19:53:25 -0500 Subject: Have mock_install_dir actually yield the file name. Ref #317. --- setuptools/tests/test_msvc9compiler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/test_msvc9compiler.py b/setuptools/tests/test_msvc9compiler.py index e54e7a6e..82c4d521 100644 --- a/setuptools/tests/test_msvc9compiler.py +++ b/setuptools/tests/test_msvc9compiler.py @@ -173,4 +173,4 @@ class TestModulePatch: vcvarsall = os.path.join(result, 'vcvarsall.bat') with open(vcvarsall, 'w'): pass - yield + yield vcvarsall -- cgit v1.2.1 From 903de3abdd20a96051cedad2f0f4287a3a4b11b5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 15 Jan 2015 20:48:10 -0500 Subject: Just the path is expected --- setuptools/tests/test_msvc9compiler.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/setuptools/tests/test_msvc9compiler.py b/setuptools/tests/test_msvc9compiler.py index 82c4d521..0790e3d2 100644 --- a/setuptools/tests/test_msvc9compiler.py +++ b/setuptools/tests/test_msvc9compiler.py @@ -113,7 +113,8 @@ class TestModulePatch: Ensure user's settings are preferred. """ result = distutils.msvc9compiler.find_vcvarsall(9.0) - assert user_preferred_setting == result + expected = os.path.join(user_preferred_setting, 'vcvarsall.bat') + assert expected == result @pytest.yield_fixture def local_machine_setting(self): @@ -134,7 +135,8 @@ class TestModulePatch: Ensure machine setting is honored if user settings are not present. """ result = distutils.msvc9compiler.find_vcvarsall(9.0) - assert local_machine_setting == result + expected = os.path.join(local_machine_setting, 'vcvarsall.bat') + assert expected == result @pytest.yield_fixture def x64_preferred_setting(self): @@ -160,7 +162,8 @@ class TestModulePatch: Ensure 64-bit system key is preferred. """ result = distutils.msvc9compiler.find_vcvarsall(9.0) - assert x64_preferred_setting == result + expected = os.path.join(x64_preferred_setting, 'vcvarsall.bat') + assert expected == result @staticmethod @contextlib.contextmanager @@ -173,4 +176,4 @@ class TestModulePatch: vcvarsall = os.path.join(result, 'vcvarsall.bat') with open(vcvarsall, 'w'): pass - yield vcvarsall + yield result -- cgit v1.2.1 From 07dac60e9e33d9d74232eab325a3a8ad6a05e50d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 15 Jan 2015 19:57:21 -0500 Subject: Remove unused import --- setuptools/msvc9_support.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/setuptools/msvc9_support.py b/setuptools/msvc9_support.py index e76d70f0..2e4032b1 100644 --- a/setuptools/msvc9_support.py +++ b/setuptools/msvc9_support.py @@ -1,5 +1,3 @@ -import sys - try: import distutils.msvc9compiler except ImportError: -- cgit v1.2.1 From 64f09ab5fb6c9c0a0344e50388022ee6e2e85d85 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 15 Jan 2015 20:28:02 -0500 Subject: Extract variables --- setuptools/msvc9_support.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setuptools/msvc9_support.py b/setuptools/msvc9_support.py index 2e4032b1..a69c7474 100644 --- a/setuptools/msvc9_support.py +++ b/setuptools/msvc9_support.py @@ -27,13 +27,15 @@ def patch_for_specialized_compiler(): def find_vcvarsall(version): Reg = distutils.msvc9compiler.Reg VC_BASE = r'Software\%sMicrosoft\DevDiv\VCForPython\%0.1f' + key = VC_BASE % ('', version) try: # Per-user installs register the compiler path here - productdir = Reg.get_value(VC_BASE % ('', version), "installdir") + productdir = Reg.get_value(key, "installdir") except KeyError: try: # All-user installs on a 64-bit system register here - productdir = Reg.get_value(VC_BASE % ('Wow6432Node\\', version), "installdir") + key = VC_BASE % ('Wow6432Node\\', version) + productdir = Reg.get_value(key, "installdir") except KeyError: productdir = None -- cgit v1.2.1 From 21ebac859dff95cb593180f7fffdf74d8a5e5275 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 15 Jan 2015 21:09:57 -0500 Subject: Fix failing test by reverting to author's original intent. Ref #317 --- setuptools/tests/test_msvc9compiler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_msvc9compiler.py b/setuptools/tests/test_msvc9compiler.py index 0790e3d2..09e0460c 100644 --- a/setuptools/tests/test_msvc9compiler.py +++ b/setuptools/tests/test_msvc9compiler.py @@ -142,7 +142,7 @@ class TestModulePatch: def x64_preferred_setting(self): """ Set up environment with 64-bit and 32-bit system settings configured - and yield the 64-bit location. + and yield the canonical location. """ with self.mock_install_dir() as x32_dir: with self.mock_install_dir() as x64_dir: @@ -155,7 +155,7 @@ class TestModulePatch: }, ) with reg: - yield x64_dir + yield x32_dir def test_ensure_64_bit_preferred(self, x64_preferred_setting): """ -- cgit v1.2.1 From 921fc3e28378598912d69d3f2a6ebdd090ed3e4e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 16 Jan 2015 15:33:09 -0500 Subject: Renamed .get_writer to .best and removed boolean argument. --- CHANGES.txt | 2 ++ setuptools/command/easy_install.py | 25 +++++++++++++++++++------ setuptools/command/install_scripts.py | 11 ++++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index afec8156..ad419d25 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -10,6 +10,8 @@ CHANGES ``build.executable``, such that an executable of "/usr/bin/env my-python" may be specified. This means that systems with a specified executable whose name has spaces in the path must be updated to escape or quote that value. +* Deprecated ``easy_install.ScriptWriter.get_writer``, replaced by ``.best()`` + with slightly different semantics (no force_windows flag). ------ 11.3.1 diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 340b1fac..b61ab034 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -742,7 +742,7 @@ Please make the appropriate changes for your system and try again. def install_wrapper_scripts(self, dist): if not self.exclude_scripts: - for args in ScriptWriter.get_args(dist): + for args in ScriptWriter.best().get_args(dist): self.write_script(*args) def install_script(self, dist, script_name, script_text, dev_path=None): @@ -1975,7 +1975,7 @@ class ScriptWriter(object): def get_script_args(cls, dist, executable=None, wininst=False): # for backward compatibility warnings.warn("Use get_args", DeprecationWarning) - writer = cls.get_writer(wininst) + writer = (WindowsScriptWriter if wininst else ScriptWriter).best() header = cls.get_script_header("", executable, wininst) return writer.get_args(dist, header) @@ -2007,9 +2007,16 @@ class ScriptWriter(object): @classmethod def get_writer(cls, force_windows): - if force_windows or sys.platform == 'win32': - return WindowsScriptWriter.get_writer() - return cls + # for backward compatibility + warnings.warn("Use best", DeprecationWarning) + return WindowsScriptWriter.best() if force_windows else cls.best() + + @classmethod + def best(cls): + """ + Select the best ScriptWriter for this environment. + """ + return WindowsScriptWriter.best() if sys.platform == 'win32' else cls @classmethod def _get_script_args(cls, type_, name, header, script_text): @@ -2027,8 +2034,14 @@ class ScriptWriter(object): class WindowsScriptWriter(ScriptWriter): @classmethod def get_writer(cls): + # for backward compatibility + warnings.warn("Use best", DeprecationWarning) + return cls.best() + + @classmethod + def best(cls): """ - Get a script writer suitable for Windows + Select the best ScriptWriter suitable for Windows """ writer_lookup = dict( executable=WindowsExecutableLauncherWriter, diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index 722b0566..ad89c5fd 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -13,7 +13,7 @@ class install_scripts(orig.install_scripts): self.no_ep = False def run(self): - from setuptools.command.easy_install import ScriptWriter, CommandSpec + import setuptools.command.easy_install as ei self.run_command("egg_info") if self.distribution.scripts: @@ -30,14 +30,15 @@ class install_scripts(orig.install_scripts): ei_cmd.egg_name, ei_cmd.egg_version, ) bs_cmd = self.get_finalized_command('build_scripts') - cmd = CommandSpec.from_param(getattr(bs_cmd, 'executable', None)) + cmd = ei.CommandSpec.from_param(getattr(bs_cmd, 'executable', None)) is_wininst = getattr( self.get_finalized_command("bdist_wininst"), '_is_running', False ) + writer = ei.ScriptWriter if is_wininst: - cmd = CommandSpec.from_string("python.exe") - writer = ScriptWriter.get_writer(force_windows=is_wininst) - for args in writer.get_args(dist, cmd.as_header()): + cmd = ei.CommandSpec.from_string("python.exe") + writer = ei.WindowsScriptWriter + for args in writer.best().get_args(dist, cmd.as_header()): self.write_script(*args) def write_script(self, script_name, contents, mode="t", *ignored): -- cgit v1.2.1 From 2e8bbf46b8fba71b22d20e69224d86e4750726c0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 16 Jan 2015 16:38:28 -0500 Subject: Bumped to 12.0 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index f1e4aeae..70d45e15 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "11.3.2" +DEFAULT_VERSION = "12.0" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index 1e71f92d..f4e58d46 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '11.3.2' +__version__ = '12.0' -- cgit v1.2.1 From fd43bed470262e8bb2dc87b78886ccca52b8ce52 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 16 Jan 2015 16:38:31 -0500 Subject: Added tag 12.0 for changeset 55666947c9eb --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 343bfa9e..4763ed81 100644 --- a/.hgtags +++ b/.hgtags @@ -186,3 +186,4 @@ b4b92805bc0e9802da0b597d00df4fa42b30bc40 11.0 feb5971e7827483bbdeb67613126bb79ed09e6d9 11.2 a1a6a1ac9113b90009052ca7263174a488434099 11.3 1116e568f534ad8f4f41328a0f5fa183eb739c90 11.3.1 +55666947c9eb7e3ba78081ad6ae004807c84aede 12.0 -- cgit v1.2.1 From cda3ccf5c2b87212ca53b91fb782e2b858686dd3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 16 Jan 2015 16:39:06 -0500 Subject: Bumped to 12.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 70d45e15..dd1fea71 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.0" +DEFAULT_VERSION = "12.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index f4e58d46..9e9002b4 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.0' +__version__ = '12.1' -- cgit v1.2.1 From 072653066beade0dc5fde02c26e747002ab80baa Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 16 Jan 2015 17:22:22 -0500 Subject: Restore setuptools.command.easy_install.sys_executable for pbr compatibility. --- CHANGES.txt | 8 ++++++++ setuptools/command/easy_install.py | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index ad419d25..d6775876 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +------ +12.0.1 +------ + +* Restore ``setuptools.command.easy_install.sys_executable`` for pbr + compatibility. For the future, tools should construct a CommandSpec + explicitly. + ---- 12.0 ---- diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index b61ab034..adb18140 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -56,7 +56,6 @@ from pkg_resources import ( ) import pkg_resources - # Turn on PEP440Warnings warnings.filterwarnings("default", category=pkg_resources.PEP440Warning) @@ -1917,6 +1916,9 @@ class CommandSpec(list): cmdline = subprocess.list2cmdline(items) return '#!' + cmdline + '\n' +# For pbr compat; will be removed in a future version. +sys_executable = CommandSpec._sys_executable() + class JythonCommandSpec(CommandSpec): @classmethod @@ -2238,4 +2240,3 @@ def _patch_usage(): yield finally: distutils.core.gen_usage = saved - -- cgit v1.2.1 From 085191a65831a18f81bd654d2171bcb7b0b3381a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 16 Jan 2015 17:37:36 -0500 Subject: Bumped to 12.0.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index dd1fea71..040a1c26 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.1" +DEFAULT_VERSION = "12.0.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index 9e9002b4..06db60e2 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.1' +__version__ = '12.0.1' -- cgit v1.2.1 From f1c04084ce88023ead9ef12b1aa7756fb1cb94b4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 16 Jan 2015 17:37:38 -0500 Subject: Added tag 12.0.1 for changeset 747018b2e35a --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 4763ed81..8e333649 100644 --- a/.hgtags +++ b/.hgtags @@ -187,3 +187,4 @@ feb5971e7827483bbdeb67613126bb79ed09e6d9 11.2 a1a6a1ac9113b90009052ca7263174a488434099 11.3 1116e568f534ad8f4f41328a0f5fa183eb739c90 11.3.1 55666947c9eb7e3ba78081ad6ae004807c84aede 12.0 +747018b2e35a40cb4b1c444f150f013d02197c64 12.0.1 -- cgit v1.2.1 From 57fb24d60656bc99192c9768ff04dd78de9ef695 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 16 Jan 2015 17:38:07 -0500 Subject: Bumped to 12.0.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 040a1c26..d86456fe 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.0.1" +DEFAULT_VERSION = "12.0.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index 06db60e2..dd108765 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.0.1' +__version__ = '12.0.2' -- cgit v1.2.1 From fd7fb7ade0fc879e24543f13c39b00de073004bc Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Sat, 17 Jan 2015 21:41:55 +0100 Subject: Fix "AttributeError: 'TarFile' object has no attribute '__exit__'" with Python 3.1. --- setuptools/tests/py26compat.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setuptools/tests/py26compat.py b/setuptools/tests/py26compat.py index c53b4809..c5680881 100644 --- a/setuptools/tests/py26compat.py +++ b/setuptools/tests/py26compat.py @@ -8,4 +8,7 @@ def _tarfile_open_ex(*args, **kwargs): """ return contextlib.closing(tarfile.open(*args, **kwargs)) -tarfile_open = _tarfile_open_ex if sys.version_info < (2,7) else tarfile.open +if sys.version_info[:2] < (2, 7) or (3, 0) <= sys.version_info[:2] < (3, 2): + tarfile_open = _tarfile_open_ex +else: + tarfile_open = tarfile.open -- cgit v1.2.1 From 49a3b4c156062e4212ed59e2061a178577196fb6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 15:51:42 -0500 Subject: Remove unintended shebang. Fixes #333. --- setuptools/tests/test_easy_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 689860c3..5e36044d 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -1,4 +1,4 @@ -#! -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- """Easy install Tests """ -- cgit v1.2.1 From f2685d1d9311fa2603ea069d4ed13a74624c8f8c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 19:22:59 -0500 Subject: Extract messages as class attributes for nicer indentation. --- setuptools/command/easy_install.py | 161 ++++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 73 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index adb18140..fcd96bea 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -445,43 +445,49 @@ class easy_install(Command): self.pth_file = None # and don't create a .pth file self.install_dir = instdir - def cant_write_to_target(self): - template = """can't create or remove files in install directory + __cant_write_msg = textwrap.dedent(""" + can't create or remove files in install directory -The following error occurred while trying to add or remove files in the -installation directory: + The following error occurred while trying to add or remove files in the + installation directory: - %s + %s -The installation directory you specified (via --install-dir, --prefix, or -the distutils default setting) was: + The installation directory you specified (via --install-dir, --prefix, or + the distutils default setting) was: - %s -""" - msg = template % (sys.exc_info()[1], self.install_dir,) + %s + """).lstrip() - if not os.path.exists(self.install_dir): - msg += """ -This directory does not currently exist. Please create it and try again, or -choose a different installation directory (using the -d or --install-dir -option). -""" - else: - msg += """ -Perhaps your account does not have write access to this directory? If the -installation directory is a system-owned directory, you may need to sign in -as the administrator or "root" account. If you do not have administrative -access to this machine, you may wish to choose a different installation -directory, preferably one that is listed in your PYTHONPATH environment -variable. + __not_exists_id = textwrap.dedent(""" + This directory does not currently exist. Please create it and try again, or + choose a different installation directory (using the -d or --install-dir + option). + """).lstrip() -For information on other options, you may wish to consult the -documentation at: + __access_msg = textwrap.dedent(""" + Perhaps your account does not have write access to this directory? If the + installation directory is a system-owned directory, you may need to sign in + as the administrator or "root" account. If you do not have administrative + access to this machine, you may wish to choose a different installation + directory, preferably one that is listed in your PYTHONPATH environment + variable. - https://pythonhosted.org/setuptools/easy_install.html + For information on other options, you may wish to consult the + documentation at: -Please make the appropriate changes for your system and try again. -""" + https://pythonhosted.org/setuptools/easy_install.html + + Please make the appropriate changes for your system and try again. + """).lstrip() + + def cant_write_to_target(self): + msg = self._cant_write_msg % (sys.exc_info()[1], self.install_dir,) + + if not os.path.exists(self.install_dir): + msg += '\n' + self.__not_exists_id + else: + msg += '\n' + self.__access_msg raise DistutilsError(msg) def check_pth_processing(self): @@ -979,46 +985,52 @@ Please make the appropriate changes for your system and try again. f.write('\n'.join(locals()[name]) + '\n') f.close() + __mv_warning = textwrap.dedent(""" + Because this distribution was installed --multi-version, before you can + import modules from this package in an application, you will need to + 'import pkg_resources' and then use a 'require()' call similar to one of + these examples, in order to select the desired version: + + pkg_resources.require("%(name)s") # latest installed version + pkg_resources.require("%(name)s==%(version)s") # this exact version + pkg_resources.require("%(name)s>=%(version)s") # this version or higher + """).lstrip() + + __id_warning = textwrap.dedent(""" + Note also that the installation directory must be on sys.path at runtime for + this to work. (e.g. by being the application's script directory, by being on + PYTHONPATH, or by being added to sys.path by your code.) + """) + def installation_report(self, req, dist, what="Installed"): """Helpful installation message for display to package users""" msg = "\n%(what)s %(eggloc)s%(extras)s" if self.multi_version and not self.no_report: - msg += """ - -Because this distribution was installed --multi-version, before you can -import modules from this package in an application, you will need to -'import pkg_resources' and then use a 'require()' call similar to one of -these examples, in order to select the desired version: - - pkg_resources.require("%(name)s") # latest installed version - pkg_resources.require("%(name)s==%(version)s") # this exact version - pkg_resources.require("%(name)s>=%(version)s") # this version or higher -""" + msg += '\n' + self.__mv_warning if self.install_dir not in map(normalize_path, sys.path): - msg += """ + msg += '\n' + self.__id_warning -Note also that the installation directory must be on sys.path at runtime for -this to work. (e.g. by being the application's script directory, by being on -PYTHONPATH, or by being added to sys.path by your code.) -""" eggloc = dist.location name = dist.project_name version = dist.version extras = '' # TODO: self.report_extras(req, dist) return msg % locals() - def report_editable(self, spec, setup_script): - dirname = os.path.dirname(setup_script) - python = sys.executable - return """\nExtracted editable version of %(spec)s to %(dirname)s + __editable_msg = textwrap.dedent(""" + Extracted editable version of %(spec)s to %(dirname)s -If it uses setuptools in its setup script, you can activate it in -"development" mode by going to that directory and running:: + If it uses setuptools in its setup script, you can activate it in + "development" mode by going to that directory and running:: - %(python)s setup.py develop + %(python)s setup.py develop -See the setuptools documentation for the "develop" command for more info. -""" % locals() + See the setuptools documentation for the "develop" command for more info. + """).lstrip() + + def report_editable(self, spec, setup_script): + dirname = os.path.dirname(setup_script) + python = sys.executable + return '\n' + self.__editable_msg % locals() def run_setup(self, setup_script, setup_base, args): sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) @@ -1169,35 +1181,38 @@ See the setuptools documentation for the "develop" command for more info. finally: log.set_verbosity(self.verbose) # restore original verbosity - def no_default_version_msg(self): - template = """bad install directory or PYTHONPATH + __no_default_msg = textwrap.dedent(""" + bad install directory or PYTHONPATH -You are attempting to install a package to a directory that is not -on PYTHONPATH and which Python does not read ".pth" files from. The -installation directory you specified (via --install-dir, --prefix, or -the distutils default setting) was: + You are attempting to install a package to a directory that is not + on PYTHONPATH and which Python does not read ".pth" files from. The + installation directory you specified (via --install-dir, --prefix, or + the distutils default setting) was: - %s + %s -and your PYTHONPATH environment variable currently contains: + and your PYTHONPATH environment variable currently contains: - %r + %r -Here are some of your options for correcting the problem: + Here are some of your options for correcting the problem: -* You can choose a different installation directory, i.e., one that is - on PYTHONPATH or supports .pth files + * You can choose a different installation directory, i.e., one that is + on PYTHONPATH or supports .pth files -* You can add the installation directory to the PYTHONPATH environment - variable. (It must then also be on PYTHONPATH whenever you run - Python and want to use the package(s) you are installing.) + * You can add the installation directory to the PYTHONPATH environment + variable. (It must then also be on PYTHONPATH whenever you run + Python and want to use the package(s) you are installing.) -* You can set up the installation directory to support ".pth" files by - using one of the approaches described here: + * You can set up the installation directory to support ".pth" files by + using one of the approaches described here: - https://pythonhosted.org/setuptools/easy_install.html#custom-installation-locations + https://pythonhosted.org/setuptools/easy_install.html#custom-installation-locations -Please make the appropriate changes for your system and try again.""" + Please make the appropriate changes for your system and try again.""").lstrip() + + def no_default_version_msg(self): + template = self.__no_default_msg return template % (self.install_dir, os.environ.get('PYTHONPATH', '')) def install_site_py(self): -- cgit v1.2.1 From 7cf2343ad9f5b77992422598d27d1f70e9473db0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 19:45:22 -0500 Subject: Extract variable for bdist_wininst command --- setuptools/command/install_scripts.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index ad89c5fd..cad524ec 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -31,9 +31,8 @@ class install_scripts(orig.install_scripts): ) bs_cmd = self.get_finalized_command('build_scripts') cmd = ei.CommandSpec.from_param(getattr(bs_cmd, 'executable', None)) - is_wininst = getattr( - self.get_finalized_command("bdist_wininst"), '_is_running', False - ) + bw_cmd = self.get_finalized_command("bdist_wininst") + is_wininst = getattr(bw_cmd, '_is_running', False) writer = ei.ScriptWriter if is_wininst: cmd = ei.CommandSpec.from_string("python.exe") -- cgit v1.2.1 From 0d32bf350dce5cf21c821b9216799fa53550c5c1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 19:46:46 -0500 Subject: Extract variable for exec_param --- setuptools/command/install_scripts.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index cad524ec..f85f4520 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -30,7 +30,8 @@ class install_scripts(orig.install_scripts): ei_cmd.egg_name, ei_cmd.egg_version, ) bs_cmd = self.get_finalized_command('build_scripts') - cmd = ei.CommandSpec.from_param(getattr(bs_cmd, 'executable', None)) + exec_param = getattr(bs_cmd, 'executable', None) + cmd = ei.CommandSpec.from_param(exec_param) bw_cmd = self.get_finalized_command("bdist_wininst") is_wininst = getattr(bw_cmd, '_is_running', False) writer = ei.ScriptWriter -- cgit v1.2.1 From 0a0f7d5816fa7e42fd787d4923265adc965e1360 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 19:54:01 -0500 Subject: Defer resolution of the CommandSpec and do it exactly once. --- setuptools/command/install_scripts.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index f85f4520..af079fbb 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -31,13 +31,13 @@ class install_scripts(orig.install_scripts): ) bs_cmd = self.get_finalized_command('build_scripts') exec_param = getattr(bs_cmd, 'executable', None) - cmd = ei.CommandSpec.from_param(exec_param) bw_cmd = self.get_finalized_command("bdist_wininst") is_wininst = getattr(bw_cmd, '_is_running', False) writer = ei.ScriptWriter if is_wininst: - cmd = ei.CommandSpec.from_string("python.exe") + exec_param = "python.exe" writer = ei.WindowsScriptWriter + cmd = ei.CommandSpec.from_param(exec_param) for args in writer.best().get_args(dist, cmd.as_header()): self.write_script(*args) -- cgit v1.2.1 From 97f96e8cd4d1938095101f26a28f17d6a3f97435 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 19:55:09 -0500 Subject: Extract writer resolution as a variable --- setuptools/command/install_scripts.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index af079fbb..8d251ee7 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -37,8 +37,10 @@ class install_scripts(orig.install_scripts): if is_wininst: exec_param = "python.exe" writer = ei.WindowsScriptWriter + # resolve the writer to the environment + writer = writer.best() cmd = ei.CommandSpec.from_param(exec_param) - for args in writer.best().get_args(dist, cmd.as_header()): + for args in writer.get_args(dist, cmd.as_header()): self.write_script(*args) def write_script(self, script_name, contents, mode="t", *ignored): -- cgit v1.2.1 From 43ffa78752de38190b2480b68d9ad908cf1b7fa5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 19:57:02 -0500 Subject: Allow the CommandSpec class to be resolved by the writer. --- setuptools/command/easy_install.py | 2 ++ setuptools/command/install_scripts.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index fcd96bea..9d25a139 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1988,6 +1988,8 @@ class ScriptWriter(object): ) """).lstrip() + command_spec_class = CommandSpec + @classmethod def get_script_args(cls, dist, executable=None, wininst=False): # for backward compatibility diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index 8d251ee7..9d4ac420 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -39,7 +39,7 @@ class install_scripts(orig.install_scripts): writer = ei.WindowsScriptWriter # resolve the writer to the environment writer = writer.best() - cmd = ei.CommandSpec.from_param(exec_param) + cmd = writer.command_spec_cls.from_param(exec_param) for args in writer.get_args(dist, cmd.as_header()): self.write_script(*args) -- cgit v1.2.1 From 659e2bd057382e4819f38c2c77ff3b7783d63c6b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:11:29 -0500 Subject: Adding test capturing failure where sys.executable loses backslashes on Windows. Ref #331. --- setuptools/tests/test_easy_install.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 5e36044d..91461364 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -517,3 +517,11 @@ class TestCommandSpec: cmd = CommandSpec.from_param('/usr/bin/env my-python') assert len(cmd) == 2 assert '"' not in cmd.as_header() + + def test_sys_executable(self): + """ + CommandSpec.from_string(sys.executable) should contain just that param. + """ + cmd = CommandSpec.from_string(sys.executable) + assert len(cmd) == 1 + assert cmd[0] == sys.executable -- cgit v1.2.1 From 246a5982a37f38c70012326577278582f0b01ef2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:17:12 -0500 Subject: Use the command spec as resolved by the best ScriptWriter. --- setuptools/tests/test_easy_install.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 91461364..cbbe99db 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -522,6 +522,7 @@ class TestCommandSpec: """ CommandSpec.from_string(sys.executable) should contain just that param. """ - cmd = CommandSpec.from_string(sys.executable) + writer = ScriptWriter.best() + cmd = writer.command_spec_class.from_string(sys.executable) assert len(cmd) == 1 assert cmd[0] == sys.executable -- cgit v1.2.1 From 8711abcb4bac42e771647718e6994c6847e0383a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:18:38 -0500 Subject: Also use command_spec_class in ScriptWriter. --- setuptools/command/easy_install.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 9d25a139..137193f1 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -2004,7 +2004,7 @@ class ScriptWriter(object): warnings.warn("Use get_header", DeprecationWarning) if wininst: executable = "python.exe" - cmd = CommandSpec.from_param(executable) + cmd = cls.command_spec_class.from_param(executable) cmd.install_options(script_text) return cmd.as_header() @@ -2045,7 +2045,7 @@ class ScriptWriter(object): @classmethod def get_header(cls, script_text="", executable=None): """Create a #! line, getting options (if any) from script_text""" - cmd = CommandSpec.from_param(executable) + cmd = cls.command_spec_class.from_param(executable) cmd.install_options(script_text) return cmd.as_header() -- cgit v1.2.1 From 27ffea086d37a26dbac2ebbd8b1e0edb4c8a803e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:27:56 -0500 Subject: Use non-posix semantics in a WindowsCommandSpec and use that class in the Windows script writers. Fixes #331. --- setuptools/command/easy_install.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 137193f1..541666ce 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1873,6 +1873,7 @@ class CommandSpec(list): """ options = [] + split_args = dict() @classmethod def _sys_executable(cls): @@ -1904,7 +1905,7 @@ class CommandSpec(list): Construct a command spec from a simple string representing a command line parseable by shlex.split. """ - items = shlex.split(string) + items = shlex.split(string, **cls.split_args) return JythonCommandSpec.from_string(string) or cls(items) def install_options(self, script_text): @@ -1935,6 +1936,10 @@ class CommandSpec(list): sys_executable = CommandSpec._sys_executable() +class WindowsCommandSpec(CommandSpec): + split_args = dict(posix=False) + + class JythonCommandSpec(CommandSpec): @classmethod def from_string(cls, string): @@ -2051,6 +2056,8 @@ class ScriptWriter(object): class WindowsScriptWriter(ScriptWriter): + command_spec_class = WindowsCommandSpec + @classmethod def get_writer(cls): # for backward compatibility -- cgit v1.2.1 From 768ffcf6707173a6ca34e71ba8776d282ccd41bb Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:32:31 -0500 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index d6775876..e9da34d2 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +------ +12.0.2 +------ + +* Issue #331: Fixed ``install_scripts`` command on Windows systems corrupting + the header. + ------ 12.0.1 ------ -- cgit v1.2.1 From 4fb993309210598e35e6db7bef9dcd6f19bb2117 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:34:55 -0500 Subject: Added tag 12.0.2 for changeset a177ea34bf81 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 8e333649..7542030c 100644 --- a/.hgtags +++ b/.hgtags @@ -188,3 +188,4 @@ a1a6a1ac9113b90009052ca7263174a488434099 11.3 1116e568f534ad8f4f41328a0f5fa183eb739c90 11.3.1 55666947c9eb7e3ba78081ad6ae004807c84aede 12.0 747018b2e35a40cb4b1c444f150f013d02197c64 12.0.1 +a177ea34bf81662b904fe3af46f3c8719a947ef1 12.0.2 -- cgit v1.2.1 From c1f5cdb9d49d2dc6872c1c51a94dbcc95526666a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:35:36 -0500 Subject: Bumped to 12.0.3 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index d86456fe..1a33e276 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.0.2" +DEFAULT_VERSION = "12.0.3" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index dd108765..410c5970 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.0.2' +__version__ = '12.0.3' -- cgit v1.2.1 From e584d52bc8080aa0e1dfec9514068bfef175b7fd Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:46:32 -0500 Subject: Correct command reference. --- setuptools/command/install_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index 9d4ac420..20c2cce9 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -39,7 +39,7 @@ class install_scripts(orig.install_scripts): writer = ei.WindowsScriptWriter # resolve the writer to the environment writer = writer.best() - cmd = writer.command_spec_cls.from_param(exec_param) + cmd = writer.command_spec_class.from_param(exec_param) for args in writer.get_args(dist, cmd.as_header()): self.write_script(*args) -- cgit v1.2.1 From 45ee5d3515f43c022ad4587f31325135c5ce4a3d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:48:20 -0500 Subject: Update changelog --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index e9da34d2..80a9e9c9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,12 @@ CHANGES ======= +------ +12.0.3 +------ + +* Fixed incorrect class attribute in ``install_scripts``. Tests would be nice. + ------ 12.0.2 ------ -- cgit v1.2.1 From df3410f0134a756c9d8ef659694157985fa86aba Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:48:32 -0500 Subject: Added tag 12.0.3 for changeset bf8c5bcacd49 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 7542030c..dd756cbc 100644 --- a/.hgtags +++ b/.hgtags @@ -189,3 +189,4 @@ a1a6a1ac9113b90009052ca7263174a488434099 11.3 55666947c9eb7e3ba78081ad6ae004807c84aede 12.0 747018b2e35a40cb4b1c444f150f013d02197c64 12.0.1 a177ea34bf81662b904fe3af46f3c8719a947ef1 12.0.2 +bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 -- cgit v1.2.1 From c808d232427ed8072b3b46b9e1c03df9d4cf9f76 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Jan 2015 20:49:13 -0500 Subject: Bumped to 12.0.4 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 1a33e276..2d7611c0 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.0.3" +DEFAULT_VERSION = "12.0.4" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index 410c5970..2527f6f7 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.0.3' +__version__ = '12.0.4' -- cgit v1.2.1 From ad794c2809cc2ad0a48a14129dca82996f14af28 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 20:33:29 -0500 Subject: Use a .best classmethod to resolve JythonCommandSpec when relevant. --- setuptools/command/easy_install.py | 35 ++++++++++++++++++++++------------- setuptools/command/install_scripts.py | 2 +- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index dda183c8..9978c132 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1875,6 +1875,13 @@ class CommandSpec(list): options = [] split_args = dict() + @classmethod + def best(cls): + """ + Choose the best CommandSpec class based on environmental conditions. + """ + return cls if not JythonCommandSpec.relevant() else JythonCommandSpec + @classmethod def _sys_executable(cls): _default = os.path.normpath(sys.executable) @@ -1897,9 +1904,7 @@ class CommandSpec(list): @classmethod def from_environment(cls): - string = '"' + cls._sys_executable() + '"' - jython_spec = JythonCommandSpec.from_string(string) - return jython_spec or cls([cls._sys_executable()]) + return cls([cls._sys_executable()]) @classmethod def from_string(cls, string): @@ -1908,7 +1913,7 @@ class CommandSpec(list): line parseable by shlex.split. """ items = shlex.split(string, **cls.split_args) - return JythonCommandSpec.from_string(string) or cls(items) + return cls(items) def install_options(self, script_text): self.options = shlex.split(self._extract_options(script_text)) @@ -1944,17 +1949,21 @@ class WindowsCommandSpec(CommandSpec): class JythonCommandSpec(CommandSpec): @classmethod - def from_string(cls, string): - """ - On Jython, construct an instance of this class. - On platforms other than Jython, return None. - """ - needs_jython_spec = ( + def relevant(cls): + return ( sys.platform.startswith('java') and __import__('java').lang.System.getProperty('os.name') != 'Linux' ) - return cls([string]) if needs_jython_spec else None + + @classmethod + def from_environment(cls): + string = '"' + cls._sys_executable() + '"' + return cls.from_string(string) + + @classmethod + def from_string(cls, string): + return cls([string]) def as_header(self): """ @@ -2011,7 +2020,7 @@ class ScriptWriter(object): warnings.warn("Use get_header", DeprecationWarning) if wininst: executable = "python.exe" - cmd = cls.command_spec_class.from_param(executable) + cmd = cls.command_spec_class.best().from_param(executable) cmd.install_options(script_text) return cmd.as_header() @@ -2052,7 +2061,7 @@ class ScriptWriter(object): @classmethod def get_header(cls, script_text="", executable=None): """Create a #! line, getting options (if any) from script_text""" - cmd = cls.command_spec_class.from_param(executable) + cmd = cls.command_spec_class.best().from_param(executable) cmd.install_options(script_text) return cmd.as_header() diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index 20c2cce9..be66cb22 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -39,7 +39,7 @@ class install_scripts(orig.install_scripts): writer = ei.WindowsScriptWriter # resolve the writer to the environment writer = writer.best() - cmd = writer.command_spec_class.from_param(exec_param) + cmd = writer.command_spec_class.best().from_param(exec_param) for args in writer.get_args(dist, cmd.as_header()): self.write_script(*args) -- cgit v1.2.1 From 9209b9f7ce6ecb4d9518037b2463bbedd544dcfc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 20:48:18 -0500 Subject: Decode file as latin-1 when opening to ensure decoding any bytes. --- setuptools/command/easy_install.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 9978c132..5e25f2cd 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1801,9 +1801,8 @@ def is_python(text, filename=''): def is_sh(executable): """Determine if the specified executable is a .sh (contains a #! line)""" try: - fp = open(executable) - magic = fp.read(2) - fp.close() + with open(executable, encoding='latin-1') as fp: + magic = fp.read(2) except (OSError, IOError): return executable return magic == '#!' -- cgit v1.2.1 From adbb4edde04b071e4b092b675bb0c2ffb66a0977 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 21:03:56 -0500 Subject: Deprecate fix_jython_executable and replace with JythonCommandSpec --- setuptools/command/easy_install.py | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 5e25f2cd..b8efff73 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1844,25 +1844,14 @@ def chmod(path, mode): def fix_jython_executable(executable, options): - if sys.platform.startswith('java') and is_sh(executable): - # Workaround for Jython is not needed on Linux systems. - import java + warnings.warn("Use JythonCommandSpec", DeprecationWarning, stacklevel=2) - if java.lang.System.getProperty("os.name") == "Linux": - return executable + if not JythonCommandSpec.relevant(): + return executable - # Workaround Jython's sys.executable being a .sh (an invalid - # shebang line interpreter) - if options: - # Can't apply the workaround, leave it broken - log.warn( - "WARNING: Unable to adapt shebang line for Jython," - " the following script is NOT executable\n" - " see http://bugs.jython.org/issue1112 for" - " more information.") - else: - return '/usr/bin/env %s' % executable - return executable + cmd = CommandSpec.best().from_param(executable) + cmd.install_options(options) + return cmd.as_header().lstrip('#!').rstrip('\n') class CommandSpec(list): -- cgit v1.2.1 From 0a81b14fbfdf9b41bf128c99da42a374dff6122a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 21:05:41 -0500 Subject: Replace use of fix_jython_executable with CommandSpec invocation. --- setuptools/tests/test_easy_install.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index a2f26e08..3be829c5 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -26,7 +26,7 @@ from setuptools.compat import StringIO, BytesIO, urlparse from setuptools.sandbox import run_setup import setuptools.command.easy_install as ei from setuptools.command.easy_install import ( - easy_install, fix_jython_executable, nt_quote_arg, + easy_install, nt_quote_arg, is_sh, ScriptWriter, CommandSpec, ) from setuptools.command.easy_install import PthDistributions @@ -51,8 +51,7 @@ class FakeDist(object): def as_requirement(self): return 'spec' -WANTED = DALS(""" - #!%s +WANTED = ei.CommandSpec.best().from_environment().as_header() + DALS(""" # EASY-INSTALL-ENTRY-SCRIPT: 'spec','console_scripts','name' __requires__ = 'spec' import sys @@ -62,7 +61,7 @@ WANTED = DALS(""" sys.exit( load_entry_point('spec', 'console_scripts', 'name')() ) - """) % nt_quote_arg(fix_jython_executable(sys.executable, "")) + """) SETUP_PY = DALS(""" from setuptools import setup -- cgit v1.2.1 From 2554cbb108a56ab4932e7f1a773f5a57abdabcd2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 21:09:10 -0500 Subject: Use module namespace. --- setuptools/tests/test_easy_install.py | 51 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 3be829c5..51d6f094 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -25,10 +25,6 @@ from setuptools import compat from setuptools.compat import StringIO, BytesIO, urlparse from setuptools.sandbox import run_setup import setuptools.command.easy_install as ei -from setuptools.command.easy_install import ( - easy_install, nt_quote_arg, - is_sh, ScriptWriter, CommandSpec, -) from setuptools.command.easy_install import PthDistributions from setuptools.command import easy_install as easy_install_pkg from setuptools.dist import Distribution @@ -73,7 +69,7 @@ class TestEasyInstallTest: def test_install_site_py(self): dist = Distribution() - cmd = easy_install(dist) + cmd = ei.easy_install(dist) cmd.sitepy_installed = False cmd.install_dir = tempfile.mkdtemp() try: @@ -86,7 +82,7 @@ class TestEasyInstallTest: def test_get_script_args(self): dist = FakeDist() - args = next(ScriptWriter.get_args(dist)) + args = next(ei.ScriptWriter.get_args(dist)) name, script = itertools.islice(args, 2) assert script == WANTED @@ -95,7 +91,7 @@ class TestEasyInstallTest: # new option '--no-find-links', that blocks find-links added at # the project level dist = Distribution() - cmd = easy_install(dist) + cmd = ei.easy_install(dist) cmd.check_pth_processing = lambda: True cmd.no_find_links = True cmd.find_links = ['link1', 'link2'] @@ -105,7 +101,7 @@ class TestEasyInstallTest: assert cmd.package_index.scanned_urls == {} # let's try without it (default behavior) - cmd = easy_install(dist) + cmd = ei.easy_install(dist) cmd.check_pth_processing = lambda: True cmd.find_links = ['link1', 'link2'] cmd.install_dir = os.path.join(tempfile.mkdtemp(), 'ok') @@ -154,7 +150,7 @@ class TestUserInstallTest: #XXX: replace with something meaningfull dist = Distribution() dist.script_name = 'setup.py' - cmd = easy_install(dist) + cmd = ei.easy_install(dist) cmd.args = ['py'] cmd.ensure_finalized() assert cmd.user, 'user should be implied' @@ -175,7 +171,7 @@ class TestUserInstallTest: #XXX: replace with something meaningfull dist = Distribution() dist.script_name = 'setup.py' - cmd = easy_install(dist) + cmd = ei.easy_install(dist) cmd.args = ['py'] cmd.initialize_options() assert not cmd.user, 'NOT user should be implied' @@ -196,7 +192,7 @@ class TestUserInstallTest: try: dist = Distribution() dist.script_name = 'setup.py' - cmd = easy_install(dist) + cmd = ei.easy_install(dist) cmd.install_dir = target cmd.args = ['foo'] cmd.ensure_finalized() @@ -423,24 +419,25 @@ class TestScriptHeader: exe_with_spaces = r'C:\Program Files\Python33\python.exe' @pytest.mark.skipif( - sys.platform.startswith('java') and is_sh(sys.executable), + sys.platform.startswith('java') and ei.is_sh(sys.executable), reason="Test cannot run under java when executable is sh" ) def test_get_script_header(self): - expected = '#!%s\n' % nt_quote_arg(os.path.normpath(sys.executable)) - actual = ScriptWriter.get_script_header('#!/usr/local/bin/python') + expected = '#!%s\n' % ei.nt_quote_arg(os.path.normpath(sys.executable)) + actual = ei.ScriptWriter.get_script_header('#!/usr/local/bin/python') assert actual == expected - expected = '#!%s -x\n' % nt_quote_arg(os.path.normpath(sys.executable)) - actual = ScriptWriter.get_script_header('#!/usr/bin/python -x') + expected = '#!%s -x\n' % ei.nt_quote_arg(os.path.normpath + (sys.executable)) + actual = ei.ScriptWriter.get_script_header('#!/usr/bin/python -x') assert actual == expected - actual = ScriptWriter.get_script_header('#!/usr/bin/python', + actual = ei.ScriptWriter.get_script_header('#!/usr/bin/python', executable=self.non_ascii_exe) expected = '#!%s -x\n' % self.non_ascii_exe assert actual == expected - actual = ScriptWriter.get_script_header('#!/usr/bin/python', + actual = ei.ScriptWriter.get_script_header('#!/usr/bin/python', executable='"'+self.exe_with_spaces+'"') expected = '#!"%s"\n' % self.exe_with_spaces assert actual == expected @@ -463,7 +460,7 @@ class TestScriptHeader: f.write(header) exe = str(exe) - header = ScriptWriter.get_script_header('#!/usr/local/bin/python', + header = ei.ScriptWriter.get_script_header('#!/usr/local/bin/python', executable=exe) assert header == '#!/usr/bin/env %s\n' % exe @@ -472,14 +469,14 @@ class TestScriptHeader: with contexts.quiet() as (stdout, stderr): # When options are included, generate a broken shebang line # with a warning emitted - candidate = ScriptWriter.get_script_header('#!/usr/bin/python -x', + candidate = ei.ScriptWriter.get_script_header('#!/usr/bin/python -x', executable=exe) assert candidate == '#!%s -x\n' % exe output = locals()[expect_out] assert 'Unable to adapt shebang line' in output.getvalue() with contexts.quiet() as (stdout, stderr): - candidate = ScriptWriter.get_script_header('#!/usr/bin/python', + candidate = ei.ScriptWriter.get_script_header('#!/usr/bin/python', executable=self.non_ascii_exe) assert candidate == '#!%s -x\n' % self.non_ascii_exe output = locals()[expect_out] @@ -492,20 +489,20 @@ class TestCommandSpec: Show how a custom CommandSpec could be used to specify a #! executable which takes parameters. """ - cmd = CommandSpec(['/usr/bin/env', 'python3']) + cmd = ei.CommandSpec(['/usr/bin/env', 'python3']) assert cmd.as_header() == '#!/usr/bin/env python3\n' def test_from_param_for_CommandSpec_is_passthrough(self): """ from_param should return an instance of a CommandSpec """ - cmd = CommandSpec(['python']) - cmd_new = CommandSpec.from_param(cmd) + cmd = ei.CommandSpec(['python']) + cmd_new = ei.CommandSpec.from_param(cmd) assert cmd is cmd_new def test_from_environment_with_spaces_in_executable(self): with mock.patch('sys.executable', TestScriptHeader.exe_with_spaces): - cmd = CommandSpec.from_environment() + cmd = ei.CommandSpec.from_environment() assert len(cmd) == 1 assert cmd.as_header().startswith('#!"') @@ -514,7 +511,7 @@ class TestCommandSpec: In order to support `executable = /usr/bin/env my-python`, make sure from_param invokes shlex on that input. """ - cmd = CommandSpec.from_param('/usr/bin/env my-python') + cmd = ei.CommandSpec.from_param('/usr/bin/env my-python') assert len(cmd) == 2 assert '"' not in cmd.as_header() @@ -522,7 +519,7 @@ class TestCommandSpec: """ CommandSpec.from_string(sys.executable) should contain just that param. """ - writer = ScriptWriter.best() + writer = ei.ScriptWriter.best() cmd = writer.command_spec_class.from_string(sys.executable) assert len(cmd) == 1 assert cmd[0] == sys.executable -- cgit v1.2.1 From 209fbc31d5df376de6db40bc6b1d1d50e87a0a83 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 21:11:36 -0500 Subject: Move global into the only method where it's used. --- setuptools/tests/test_easy_install.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 51d6f094..ab6a8f0d 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -47,18 +47,6 @@ class FakeDist(object): def as_requirement(self): return 'spec' -WANTED = ei.CommandSpec.best().from_environment().as_header() + DALS(""" - # EASY-INSTALL-ENTRY-SCRIPT: 'spec','console_scripts','name' - __requires__ = 'spec' - import sys - from pkg_resources import load_entry_point - - if __name__ == '__main__': - sys.exit( - load_entry_point('spec', 'console_scripts', 'name')() - ) - """) - SETUP_PY = DALS(""" from setuptools import setup @@ -80,12 +68,24 @@ class TestEasyInstallTest: shutil.rmtree(cmd.install_dir) def test_get_script_args(self): + header = ei.CommandSpec.best().from_environment().as_header() + expected = header + DALS(""" + # EASY-INSTALL-ENTRY-SCRIPT: 'spec','console_scripts','name' + __requires__ = 'spec' + import sys + from pkg_resources import load_entry_point + + if __name__ == '__main__': + sys.exit( + load_entry_point('spec', 'console_scripts', 'name')() + ) + """) dist = FakeDist() args = next(ei.ScriptWriter.get_args(dist)) name, script = itertools.islice(args, 2) - assert script == WANTED + assert script == expected def test_no_find_links(self): # new option '--no-find-links', that blocks find-links added at -- cgit v1.2.1 From d66e85f360940a5e583ef6a363d20e8aa8cfd486 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 21:47:02 -0500 Subject: Use io module for Python 2 compatibility --- setuptools/command/easy_install.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index b8efff73..206fc58d 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -37,6 +37,7 @@ import struct import contextlib import subprocess import shlex +import io from setuptools import Command from setuptools.sandbox import run_setup @@ -1801,7 +1802,7 @@ def is_python(text, filename=''): def is_sh(executable): """Determine if the specified executable is a .sh (contains a #! line)""" try: - with open(executable, encoding='latin-1') as fp: + with io.open(executable, encoding='latin-1') as fp: magic = fp.read(2) except (OSError, IOError): return executable -- cgit v1.2.1 From d3e60f4d454d43f0b0bf3d5e0811bf5b8fbeb92d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 22:06:15 -0500 Subject: Update changelog --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 80a9e9c9..97c16c5e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,12 @@ CHANGES ======= +------ +12.0.4 +------ + +* Issue #335: Fix script header generation on Windows. + ------ 12.0.3 ------ -- cgit v1.2.1 From fe1968668732b7a60e94b311d59182a9d710cac7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 22:08:41 -0500 Subject: Added tag 12.0.4 for changeset 73dcfc90e3ee --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index dd756cbc..99bd7293 100644 --- a/.hgtags +++ b/.hgtags @@ -190,3 +190,4 @@ a1a6a1ac9113b90009052ca7263174a488434099 11.3 747018b2e35a40cb4b1c444f150f013d02197c64 12.0.1 a177ea34bf81662b904fe3af46f3c8719a947ef1 12.0.2 bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 +73dcfc90e3eecec6baddea19302c6b342e68e2fa 12.0.4 -- cgit v1.2.1 From 71f6d20fcaa959ef429aa162d1f7c1fa73f52a44 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 22:16:20 -0500 Subject: Bumped to 12.0.5 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 2d7611c0..a7206278 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.0.4" +DEFAULT_VERSION = "12.0.5" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" def _python_cmd(*args): diff --git a/setuptools/version.py b/setuptools/version.py index 2527f6f7..8bb69c5f 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.0.4' +__version__ = '12.0.5' -- cgit v1.2.1 From 2cf86e6e6e8f68370eb797eade989168b37edcf1 Mon Sep 17 00:00:00 2001 From: John Vandenberg Date: Mon, 19 Jan 2015 21:11:33 +1100 Subject: pep8 and pep257 compliance --- ez_setup.py | 85 +++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index a7206278..bbcef8c7 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -"""Bootstrap setuptools installation +"""Bootstrap setuptools installation. To use setuptools in your package's setup.py, include this file in the same directory and add this to the top of your setup.py:: @@ -39,8 +39,11 @@ except ImportError: DEFAULT_VERSION = "12.0.5" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" + def _python_cmd(*args): """ + Execute a command. + Return True if the command succeeded. """ args = (sys.executable,) + args @@ -48,6 +51,7 @@ def _python_cmd(*args): def _install(archive_filename, install_args=()): + """Install Setuptools.""" with archive_context(archive_filename): # installing log.warn('Installing Setuptools') @@ -59,6 +63,7 @@ def _install(archive_filename, install_args=()): def _build_egg(egg, archive_filename, to_dir): + """Build Setuptools egg.""" with archive_context(archive_filename): # building an egg log.warn('Building a Setuptools egg in %s', to_dir) @@ -70,20 +75,19 @@ def _build_egg(egg, archive_filename, to_dir): class ContextualZipFile(zipfile.ZipFile): - """ - Supplement ZipFile class to support context manager for Python 2.6 - """ + + """Supplement ZipFile class to support context manager for Python 2.6.""" def __enter__(self): + """Context manager __enter__ hook.""" return self def __exit__(self, type, value, traceback): + """Context manager __exit__ hook.""" self.close() def __new__(cls, *args, **kwargs): - """ - Construct a ZipFile or ContextualZipFile as appropriate - """ + """Construct a ZipFile or ContextualZipFile as appropriate.""" if hasattr(zipfile.ZipFile, '__exit__'): return zipfile.ZipFile(*args, **kwargs) return super(ContextualZipFile, cls).__new__(cls) @@ -91,7 +95,7 @@ class ContextualZipFile(zipfile.ZipFile): @contextlib.contextmanager def archive_context(filename): - # extracting the archive + """Extract archive.""" tmpdir = tempfile.mkdtemp() log.warn('Extracting in %s', tmpdir) old_wd = os.getcwd() @@ -112,6 +116,7 @@ def archive_context(filename): def _do_download(version, download_base, to_dir, download_delay): + """Download Setuptools.""" egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' % (version, sys.version_info[0], sys.version_info[1])) if not os.path.exists(egg): @@ -129,8 +134,10 @@ def _do_download(version, download_base, to_dir, download_delay): setuptools.bootstrap_install_from = egg -def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, +def use_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15): + """Download, install and use Setuptools.""" to_dir = os.path.abspath(to_dir) rep_modules = 'pkg_resources', 'setuptools' imported = set(sys.modules).intersection(rep_modules) @@ -146,9 +153,9 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, except pkg_resources.VersionConflict as VC_err: if imported: msg = textwrap.dedent(""" - The required version of setuptools (>={version}) is not available, - and can't be installed while this script is running. Please - install a more recent version first, using + The required version of setuptools (>={version}) is not + available, and can't be installed while this script is running. + Please install a more recent version first, using 'easy_install -U setuptools'. (Currently using {VC_err.args[0]!r}) @@ -160,10 +167,12 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, del pkg_resources, sys.modules['pkg_resources'] return _do_download(version, download_base, to_dir, download_delay) + def _clean_check(cmd, target): """ - Run the command to download target. If the command fails, clean up before - re-raising the error. + Run the command to download target. + + If the command fails, clean up before re-raising the error. """ try: subprocess.check_call(cmd) @@ -172,10 +181,13 @@ def _clean_check(cmd, target): os.unlink(target) raise + def download_file_powershell(url, target): """ - Download the file at url to target using Powershell (which will validate - trust). Raise an exception if the command cannot complete. + Download the file at url to target using Powershell. + + Powershell will validate trust. + Raise an exception if the command cannot complete. """ target = os.path.abspath(target) ps_cmd = ( @@ -191,7 +203,9 @@ def download_file_powershell(url, target): ] _clean_check(cmd, target) + def has_powershell(): + """Determine if Powershell is available.""" if platform.system() != 'Windows': return False cmd = ['powershell', '-Command', 'echo test'] @@ -202,13 +216,18 @@ def has_powershell(): return False return True + download_file_powershell.viable = has_powershell + def download_file_curl(url, target): + """Use curl to download the file.""" cmd = ['curl', url, '--silent', '--output', target] _clean_check(cmd, target) + def has_curl(): + """Determine if curl is available.""" cmd = ['curl', '--version'] with open(os.path.devnull, 'wb') as devnull: try: @@ -217,13 +236,18 @@ def has_curl(): return False return True + download_file_curl.viable = has_curl + def download_file_wget(url, target): + """Use wget to download the file.""" cmd = ['wget', url, '--quiet', '--output-document', target] _clean_check(cmd, target) + def has_wget(): + """Determine if wget is available.""" cmd = ['wget', '--version'] with open(os.path.devnull, 'wb') as devnull: try: @@ -232,13 +256,12 @@ def has_wget(): return False return True + download_file_wget.viable = has_wget + def download_file_insecure(url, target): - """ - Use Python to download the file, even though it cannot authenticate the - connection. - """ + """Use Python to download the file, without connection authentication.""" src = urlopen(url) try: # Read all the data in one block. @@ -250,9 +273,12 @@ def download_file_insecure(url, target): with open(target, "wb") as dst: dst.write(data) + download_file_insecure.viable = lambda: True + def get_best_downloader(): + """Determine the best downloader.""" downloaders = ( download_file_powershell, download_file_curl, @@ -262,10 +288,12 @@ def get_best_downloader(): viable_downloaders = (dl for dl in downloaders if dl.viable()) return next(viable_downloaders, None) -def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, + +def download_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader): """ - Download setuptools from a specified location and return its filename + Download setuptools from a specified location and return its filename. `version` should be a valid setuptools version number that is available as an sdist for download under the `download_base` URL (which should end @@ -287,16 +315,18 @@ def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, downloader(url, saveto) return os.path.realpath(saveto) + def _build_install_args(options): """ - Build the arguments to 'python setup.py install' on the setuptools package + Build the arguments to 'python setup.py install' on the setuptools package. + + Returns list of command line arguments. """ return ['--user'] if options.user_install else [] + def _parse_args(): - """ - Parse the command line for options - """ + """Parse the command line for options.""" parser = optparse.OptionParser() parser.add_option( '--user', dest='user_install', action='store_true', default=False, @@ -318,8 +348,9 @@ def _parse_args(): # positional arguments are ignored return options + def main(): - """Install or upgrade setuptools and EasyInstall""" + """Install or upgrade setuptools and EasyInstall.""" options = _parse_args() archive = download_setuptools( version=options.version, -- cgit v1.2.1 From dc1b07f1dfc92e097be704ad19824194a95317d2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 09:40:43 -0500 Subject: Add test capturing regression in script creation in WindowsScriptWriter. --- setuptools/tests/test_easy_install.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index cbbe99db..a2f26e08 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -24,6 +24,7 @@ from setuptools import sandbox from setuptools import compat from setuptools.compat import StringIO, BytesIO, urlparse from setuptools.sandbox import run_setup +import setuptools.command.easy_install as ei from setuptools.command.easy_install import ( easy_install, fix_jython_executable, nt_quote_arg, is_sh, ScriptWriter, CommandSpec, @@ -526,3 +527,14 @@ class TestCommandSpec: cmd = writer.command_spec_class.from_string(sys.executable) assert len(cmd) == 1 assert cmd[0] == sys.executable + + +class TestWindowsScriptWriter: + def test_header(self): + hdr = ei.WindowsScriptWriter.get_script_header('') + assert hdr.startswith('#!') + assert hdr.endswith('\n') + hdr = hdr.lstrip('#!') + hdr = hdr.rstrip('\n') + # header should not start with an escaped quote + assert not hdr.startswith('\\"') -- cgit v1.2.1 From c279903336c73f74c9c8df7aac1e43fb6046c34e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 20 Jan 2015 09:56:16 -0500 Subject: Bypass string handling when default behavior of sys.executable is used. --- setuptools/command/easy_install.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 541666ce..dda183c8 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1897,7 +1897,9 @@ class CommandSpec(list): @classmethod def from_environment(cls): - return cls.from_string('"' + cls._sys_executable() + '"') + string = '"' + cls._sys_executable() + '"' + jython_spec = JythonCommandSpec.from_string(string) + return jython_spec or cls([cls._sys_executable()]) @classmethod def from_string(cls, string): -- cgit v1.2.1 From 0478d8fa223ca94e5c9a3f42dd5f92ed8be1270f Mon Sep 17 00:00:00 2001 From: Min RK Date: Tue, 20 Jan 2015 11:24:18 -0800 Subject: remove warning on normalization It seems inappropriate to show a warning on schemes officially supported in PEP 440. --HG-- branch : no-normalize-warning --- setuptools/dist.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index bc29b131..03d78520 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -276,13 +276,6 @@ class Distribution(_Distribution): ver = packaging.version.Version(self.metadata.version) normalized_version = str(ver) if self.metadata.version != normalized_version: - warnings.warn( - "The version specified requires normalization, " - "consider using '%s' instead of '%s'." % ( - normalized_version, - self.metadata.version, - ) - ) self.metadata.version = normalized_version except (packaging.version.InvalidVersion, TypeError): warnings.warn( -- cgit v1.2.1 From 3b71b0907d1b989a1a27fee8a7357ec361e08b71 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 21 Jan 2015 08:44:55 -0500 Subject: Backout some ugly docstrings from rigorous implementation of ill-conceived PEP-257. --- ez_setup.py | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index bbcef8c7..90e3d820 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -1,4 +1,5 @@ #!/usr/bin/env python + """Bootstrap setuptools installation. To use setuptools in your package's setup.py, include this @@ -13,6 +14,7 @@ the appropriate options to ``use_setuptools()``. This file can also be run as a script to install or upgrade setuptools. """ + import os import shutil import sys @@ -79,11 +81,9 @@ class ContextualZipFile(zipfile.ZipFile): """Supplement ZipFile class to support context manager for Python 2.6.""" def __enter__(self): - """Context manager __enter__ hook.""" return self def __exit__(self, type, value, traceback): - """Context manager __exit__ hook.""" self.close() def __new__(cls, *args, **kwargs): @@ -95,7 +95,11 @@ class ContextualZipFile(zipfile.ZipFile): @contextlib.contextmanager def archive_context(filename): - """Extract archive.""" + """ + Unzip filename to a temporary directory, set to the cwd. + + The unzipped target is cleaned up after. + """ tmpdir = tempfile.mkdtemp() log.warn('Extracting in %s', tmpdir) old_wd = os.getcwd() @@ -137,10 +141,22 @@ def _do_download(version, download_base, to_dir, download_delay): def use_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15): - """Download, install and use Setuptools.""" + """ + Download, install, and import Setuptools. + + Return None. + """ to_dir = os.path.abspath(to_dir) rep_modules = 'pkg_resources', 'setuptools' imported = set(sys.modules).intersection(rep_modules) + conflict_tmpl = textwrap.dedent(""" + The required version of setuptools (>={version}) is not available, + and can't be installed while this script is running. Please + install a more recent version first, using + 'easy_install -U setuptools'. + + (Currently using {VC_err.args[0]!r}) + """) try: import pkg_resources except ImportError: @@ -152,14 +168,7 @@ def use_setuptools( return _do_download(version, download_base, to_dir, download_delay) except pkg_resources.VersionConflict as VC_err: if imported: - msg = textwrap.dedent(""" - The required version of setuptools (>={version}) is not - available, and can't be installed while this script is running. - Please install a more recent version first, using - 'easy_install -U setuptools'. - - (Currently using {VC_err.args[0]!r}) - """).format(VC_err=VC_err, version=version) + msg = conflict_tmpl.format(VC_err=VC_err, version=version) sys.stderr.write(msg) sys.exit(2) @@ -185,7 +194,7 @@ def _clean_check(cmd, target): def download_file_powershell(url, target): """ Download the file at url to target using Powershell. - + Powershell will validate trust. Raise an exception if the command cannot complete. """ @@ -215,19 +224,15 @@ def has_powershell(): except Exception: return False return True - - download_file_powershell.viable = has_powershell def download_file_curl(url, target): - """Use curl to download the file.""" cmd = ['curl', url, '--silent', '--output', target] _clean_check(cmd, target) def has_curl(): - """Determine if curl is available.""" cmd = ['curl', '--version'] with open(os.path.devnull, 'wb') as devnull: try: @@ -235,19 +240,15 @@ def has_curl(): except Exception: return False return True - - download_file_curl.viable = has_curl def download_file_wget(url, target): - """Use wget to download the file.""" cmd = ['wget', url, '--quiet', '--output-document', target] _clean_check(cmd, target) def has_wget(): - """Determine if wget is available.""" cmd = ['wget', '--version'] with open(os.path.devnull, 'wb') as devnull: try: @@ -255,8 +256,6 @@ def has_wget(): except Exception: return False return True - - download_file_wget.viable = has_wget @@ -272,13 +271,10 @@ def download_file_insecure(url, target): # Write all the data in one block to avoid creating a partial file. with open(target, "wb") as dst: dst.write(data) - - download_file_insecure.viable = lambda: True def get_best_downloader(): - """Determine the best downloader.""" downloaders = ( download_file_powershell, download_file_curl, -- cgit v1.2.1 From 47236e6fff9884a1bb4a023a7c0a3ea56819f212 Mon Sep 17 00:00:00 2001 From: Richard Ipsum Date: Thu, 22 Jan 2015 14:01:28 +0000 Subject: Reintroduce use of setup_requirements writer This was originally removed due to an underlying issue (#315) with the upgrade code, which combined with this writer caused upgrades to fail. Issue #315 is resolved now so we can add this writer back. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 63093917..d02b7875 100755 --- a/setup.py +++ b/setup.py @@ -126,6 +126,7 @@ setup_params = dict( "egg_info.writers": [ "PKG-INFO = setuptools.command.egg_info:write_pkg_info", "requires.txt = setuptools.command.egg_info:write_requirements", + "setup_requires.txt = setuptools.command.egg_info:write_setup_requirements", "entry_points.txt = setuptools.command.egg_info:write_entries", "eager_resources.txt = setuptools.command.egg_info:overwrite_arg", "namespace_packages.txt = setuptools.command.egg_info:overwrite_arg", -- cgit v1.2.1 From 2436fdf2b3b65073879366505925c0dc18132943 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 22 Jan 2015 10:21:35 -0500 Subject: Remove docs on 'using', which only describe the no longer necessary bootstrapping technique. Ref #336. --- docs/index.txt | 1 - docs/using.txt | 13 ------------- 2 files changed, 14 deletions(-) delete mode 100644 docs/using.txt diff --git a/docs/index.txt b/docs/index.txt index d8eb968b..529f08f3 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -19,7 +19,6 @@ Documentation content: history roadmap python3 - using setuptools easy_install pkg_resources diff --git a/docs/using.txt b/docs/using.txt deleted file mode 100644 index bd80893d..00000000 --- a/docs/using.txt +++ /dev/null @@ -1,13 +0,0 @@ -================================ -Using Setuptools in your project -================================ - -To use Setuptools in your project, the recommended way is to ship -`ez_setup.py` alongside your `setup.py` script and call -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 -`_. -- cgit v1.2.1 From 57d6e0fc1ff66e5569296af5cf409cbbcf025148 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 22 Jan 2015 10:25:38 -0500 Subject: Deprecated use_setuptools. Fixes #336. --- ez_setup.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 90e3d820..45c92465 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -1,18 +1,9 @@ #!/usr/bin/env python -"""Bootstrap setuptools installation. - -To use setuptools in your package's setup.py, include this -file in the same directory and add this to the top of your setup.py:: - - from ez_setup import use_setuptools - use_setuptools() - -To require a specific version of setuptools, set a download -mirror, or use an alternate download directory, simply supply -the appropriate options to ``use_setuptools()``. +""" +Setuptools bootstrapping installer. -This file can also be run as a script to install or upgrade setuptools. +Run this script to install or upgrade setuptools. """ import os @@ -25,6 +16,7 @@ import subprocess import platform import textwrap import contextlib +import warnings from distutils import log @@ -142,10 +134,15 @@ def use_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15): """ - Download, install, and import Setuptools. + *deprecated* Download, install, and import Setuptools. Return None. """ + warnings.warn( + "`use_setuptools` is deprecated. To enforce a specific " + "version of setuptools, use `pkg_resources.require`.", + DeprecationWarning, + ) to_dir = os.path.abspath(to_dir) rep_modules = 'pkg_resources', 'setuptools' imported = set(sys.modules).intersection(rep_modules) -- cgit v1.2.1 From 732f5e89a8e417ff536d9a51a85d7b328e80dab1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 26 Jan 2015 08:29:56 -0500 Subject: Add test capturing Attribute error. Ref #339. --- setuptools/tests/test_easy_install.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index ab6a8f0d..4331d30e 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -13,6 +13,7 @@ import contextlib import tarfile import logging import itertools +import distutils.errors import pytest try: @@ -110,6 +111,16 @@ class TestEasyInstallTest: keys = sorted(cmd.package_index.scanned_urls.keys()) assert keys == ['link1', 'link2'] + def test_write_exception(self): + """ + Test that `cant_write_to_target` is rendered as a DistutilsError. + """ + dist = Distribution() + cmd = ei.easy_install(dist) + cmd.install_dir = os.getcwd() + with pytest.raises(distutils.errors.DistutilsError): + cmd.cant_write_to_target() + class TestPTHFileWriter: def test_add_from_cwd_site_sets_dirty(self): -- cgit v1.2.1 From 7824a2b4c6c53615feb18ff558a8a60b44e8fd41 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 26 Jan 2015 08:32:27 -0500 Subject: Reference the proper attribute. Fixes #339. --- setuptools/command/easy_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 206fc58d..e057b508 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -483,7 +483,7 @@ class easy_install(Command): """).lstrip() def cant_write_to_target(self): - msg = self._cant_write_msg % (sys.exc_info()[1], self.install_dir,) + msg = self.__cant_write_msg % (sys.exc_info()[1], self.install_dir,) if not os.path.exists(self.install_dir): msg += '\n' + self.__not_exists_id -- cgit v1.2.1 From 27416cfc54c46ab68e3fddd9c3312421b408b038 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 26 Jan 2015 08:33:04 -0500 Subject: Update changelog --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 97c16c5e..183f9734 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,12 @@ CHANGES ======= +------ +12.0.5 +------ + +* Issue #339: Correct Attribute reference in ``cant_write_to_target``. + ------ 12.0.4 ------ -- cgit v1.2.1 From be6f94e2b60be95f9324ed24bc06190d5581e30a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 26 Jan 2015 08:35:05 -0500 Subject: Added tag 12.0.5 for changeset 01fbfc9194a2 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 99bd7293..77481225 100644 --- a/.hgtags +++ b/.hgtags @@ -191,3 +191,4 @@ a1a6a1ac9113b90009052ca7263174a488434099 11.3 a177ea34bf81662b904fe3af46f3c8719a947ef1 12.0.2 bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 73dcfc90e3eecec6baddea19302c6b342e68e2fa 12.0.4 +01fbfc9194a2bc502edd682eebbf4d2f1bc79eee 12.0.5 -- cgit v1.2.1 From f5098c20ae773bff28ac809a6dea9459f24a27dc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 26 Jan 2015 08:35:43 -0500 Subject: Bumped to 12.0.6 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 45c92465..5a3f9d42 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.0.5" +DEFAULT_VERSION = "12.0.6" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" diff --git a/setuptools/version.py b/setuptools/version.py index 8bb69c5f..56d97f7f 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.0.5' +__version__ = '12.0.6' -- cgit v1.2.1 From fae9ca36955cdaebb81936bb54c3e9e44b5e6928 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 29 Jan 2015 13:50:20 +0000 Subject: Update warning to clarify when and how the instance should be use directly or what to do otherwise. --- pkg_resources/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index c0c095b2..2ce663d2 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -182,8 +182,10 @@ class _SetuptoolsVersionMixin(object): "You have iterated over the result of " "pkg_resources.parse_version. This is a legacy behavior which is " "inconsistent with the new version class introduced in setuptools " - "8.0. That class should be used directly instead of attempting to " - "iterate over the result.", + "8.0. In most cases, conversion to a tuple is unnecessary. For " + "comparison of versions, sort the Version instances directly. If " + "you have another use case requiring the tuple, please file a " + "bug with the setuptools project describing that need.", RuntimeWarning, stacklevel=1, ) -- cgit v1.2.1 From 492758aff46622fb93845f96b9062dab029064f4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 3 Feb 2015 22:28:29 +0400 Subject: Re-use context available in sandbox. --- setuptools/sandbox.py | 4 +++- setuptools/tests/contexts.py | 8 -------- setuptools/tests/test_easy_install.py | 2 +- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 83283ca3..67255123 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -47,8 +47,10 @@ def _execfile(filename, globals, locals=None): @contextlib.contextmanager -def save_argv(): +def save_argv(repl=None): saved = sys.argv[:] + if repl is not None: + sys.argv[:] = repl try: yield saved finally: diff --git a/setuptools/tests/contexts.py b/setuptools/tests/contexts.py index 4a461765..1d29284b 100644 --- a/setuptools/tests/contexts.py +++ b/setuptools/tests/contexts.py @@ -48,14 +48,6 @@ def environment(**replacements): os.environ.update(saved) -@contextlib.contextmanager -def argv(repl): - old_argv = sys.argv[:] - sys.argv[:] = repl - yield - sys.argv[:] = old_argv - - @contextlib.contextmanager def quiet(): """ diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 4331d30e..b9b2e392 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -312,7 +312,7 @@ class TestSetupRequires: '--install-dir', temp_install_dir, dist_file, ] - with contexts.argv(['easy_install']): + with sandbox.save_argv(['easy_install']): # attempt to install the dist. It should fail because # it doesn't exist. with pytest.raises(SystemExit): -- cgit v1.2.1 From 88f62bfe62531bed69f871425d21d8c4e3203ecf Mon Sep 17 00:00:00 2001 From: MinRK Date: Thu, 5 Feb 2015 12:11:23 -0800 Subject: soften normalized version warning indicate that normalization is happening, but don't be pushy about changing valid versions. --HG-- branch : no-normalize-warning --- setuptools/dist.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setuptools/dist.py b/setuptools/dist.py index 03d78520..ffbc7c48 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -276,6 +276,12 @@ class Distribution(_Distribution): ver = packaging.version.Version(self.metadata.version) normalized_version = str(ver) if self.metadata.version != normalized_version: + warnings.warn( + "Normalizing '%s' to '%s'" % ( + self.metadata.version, + normalized_version, + ) + ) self.metadata.version = normalized_version except (packaging.version.InvalidVersion, TypeError): warnings.warn( -- cgit v1.2.1 From 0c2d002a26ac527938c56eccb5edf04591da33b7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 10 Feb 2015 20:14:48 -0500 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 183f9734..f77ab24b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +---- +12.1 +---- + +* Pull Request #118: Soften warning for non-normalized versions in + Distribution. + ------ 12.0.5 ------ -- cgit v1.2.1 From f12a54d83140cb65a7a0098eeb20e469ce7fb5b5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 10 Feb 2015 20:15:39 -0500 Subject: Bumped to 12.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 5a3f9d42..b1d68cc8 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.0.6" +DEFAULT_VERSION = "12.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" diff --git a/setuptools/version.py b/setuptools/version.py index 56d97f7f..9e9002b4 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.0.6' +__version__ = '12.1' -- cgit v1.2.1 From d26bdb80a713fbd0080e94d0f5f6836afce87600 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 10 Feb 2015 20:15:43 -0500 Subject: Added tag 12.1 for changeset 7bca89384348 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 77481225..e9d7e3de 100644 --- a/.hgtags +++ b/.hgtags @@ -192,3 +192,4 @@ a177ea34bf81662b904fe3af46f3c8719a947ef1 12.0.2 bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 73dcfc90e3eecec6baddea19302c6b342e68e2fa 12.0.4 01fbfc9194a2bc502edd682eebbf4d2f1bc79eee 12.0.5 +7bca8938434839dbb546b8bfccd9aab7a86d851e 12.1 -- cgit v1.2.1 From 5d2f77f308c8ccc89be855994da1b7503b5a4294 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 10 Feb 2015 20:17:22 -0500 Subject: Bumped to 12.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index b1d68cc8..1a360ced 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.1" +DEFAULT_VERSION = "12.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" diff --git a/setuptools/version.py b/setuptools/version.py index 9e9002b4..c59a5777 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.1' +__version__ = '12.2' -- cgit v1.2.1 From cf6639df27879641b6ea561fa38ec52320b09780 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 09:42:21 -0500 Subject: Add comments --- ez_setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ez_setup.py b/ez_setup.py index 1a360ced..154cae0a 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -160,16 +160,21 @@ def use_setuptools( return _do_download(version, download_base, to_dir, download_delay) try: pkg_resources.require("setuptools>=" + version) + # a suitable version is already installed return except pkg_resources.DistributionNotFound: + # no version of setuptools was found return _do_download(version, download_base, to_dir, download_delay) except pkg_resources.VersionConflict as VC_err: if imported: + # setuptools was imported prior to invocation of this function, + # so it's not safe to unload it. msg = conflict_tmpl.format(VC_err=VC_err, version=version) sys.stderr.write(msg) sys.exit(2) - # otherwise, reload ok + # otherwise, unload pkg_resources to allow the downloaded version to + # take precedence. del pkg_resources, sys.modules['pkg_resources'] return _do_download(version, download_base, to_dir, download_delay) -- cgit v1.2.1 From 4df44da1561f239f63ee24a44acfba06d3898de4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 09:49:33 -0500 Subject: Extract function for unloading pkg_resources. Ref #345. --- ez_setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ez_setup.py b/ez_setup.py index 154cae0a..4bffc14c 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -175,10 +175,15 @@ def use_setuptools( # otherwise, unload pkg_resources to allow the downloaded version to # take precedence. - del pkg_resources, sys.modules['pkg_resources'] + del pkg_resources + _unload_pkg_resources() return _do_download(version, download_base, to_dir, download_delay) +def _unload_pkg_resources(): + del sys.modules['pkg_resources'] + + def _clean_check(cmd, target): """ Run the command to download target. -- cgit v1.2.1 From e1bc6caa509afc1df671a21b94d33906a88930d9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 09:51:51 -0500 Subject: Unload all pkg_resources modules and not just the main module. Fixes #345. --- ez_setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ez_setup.py b/ez_setup.py index 4bffc14c..0734d6c5 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -181,7 +181,12 @@ def use_setuptools( def _unload_pkg_resources(): - del sys.modules['pkg_resources'] + del_modules = [ + name for name in sys.modules + if name.startswith('pkg_resources') + ] + for mod_name in del_modules: + del sys.modules[mod_name] def _clean_check(cmd, target): -- cgit v1.2.1 From cd6f8d58314ce146b18142f4be56fc2a18f977d5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 09:53:52 -0500 Subject: Collapse common behavior --- ez_setup.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 0734d6c5..a1c69d0b 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -163,8 +163,8 @@ def use_setuptools( # a suitable version is already installed return except pkg_resources.DistributionNotFound: - # no version of setuptools was found - return _do_download(version, download_base, to_dir, download_delay) + # no version of setuptools was found; allow download + pass except pkg_resources.VersionConflict as VC_err: if imported: # setuptools was imported prior to invocation of this function, @@ -177,7 +177,8 @@ def use_setuptools( # take precedence. del pkg_resources _unload_pkg_resources() - return _do_download(version, download_base, to_dir, download_delay) + + return _do_download(version, download_base, to_dir, download_delay) def _unload_pkg_resources(): -- cgit v1.2.1 From 947b300262d3415f4a1a073887973f2772792ae0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 10:02:04 -0500 Subject: Refactor behavior into a single try/except block with exactly one invocation of _do_download. --- ez_setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index a1c69d0b..d8d2ad8b 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -156,12 +156,12 @@ def use_setuptools( """) try: import pkg_resources - except ImportError: - return _do_download(version, download_base, to_dir, download_delay) - try: pkg_resources.require("setuptools>=" + version) # a suitable version is already installed return + except ImportError: + # pkg_resources not available; setuptools is not installed; download + pass except pkg_resources.DistributionNotFound: # no version of setuptools was found; allow download pass -- cgit v1.2.1 From 1ba919120ead7b064e1b0b80e4174d7c4435e700 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 10:05:59 -0500 Subject: Extract _conflict_bail function --- ez_setup.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index d8d2ad8b..19af8969 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -146,14 +146,6 @@ def use_setuptools( to_dir = os.path.abspath(to_dir) rep_modules = 'pkg_resources', 'setuptools' imported = set(sys.modules).intersection(rep_modules) - conflict_tmpl = textwrap.dedent(""" - The required version of setuptools (>={version}) is not available, - and can't be installed while this script is running. Please - install a more recent version first, using - 'easy_install -U setuptools'. - - (Currently using {VC_err.args[0]!r}) - """) try: import pkg_resources pkg_resources.require("setuptools>=" + version) @@ -167,11 +159,7 @@ def use_setuptools( pass except pkg_resources.VersionConflict as VC_err: if imported: - # setuptools was imported prior to invocation of this function, - # so it's not safe to unload it. - msg = conflict_tmpl.format(VC_err=VC_err, version=version) - sys.stderr.write(msg) - sys.exit(2) + _conflict_bail(VC_err, version) # otherwise, unload pkg_resources to allow the downloaded version to # take precedence. @@ -181,6 +169,24 @@ def use_setuptools( return _do_download(version, download_base, to_dir, download_delay) +def _conflict_bail(VC_err, version): + """ + Setuptools was imported prior to invocation, so it is + unsafe to unload it. Bail out. + """ + conflict_tmpl = textwrap.dedent(""" + The required version of setuptools (>={version}) is not available, + and can't be installed while this script is running. Please + install a more recent version first, using + 'easy_install -U setuptools'. + + (Currently using {VC_err.args[0]!r}) + """) + msg = conflict_tmpl.format(**locals()) + sys.stderr.write(msg) + sys.exit(2) + + def _unload_pkg_resources(): del_modules = [ name for name in sys.modules -- cgit v1.2.1 From bd6fbd3fd8d4e5346a3464898cd3e303bc58f552 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 10:07:26 -0500 Subject: Add comment --- ez_setup.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ez_setup.py b/ez_setup.py index 19af8969..26e42998 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -144,8 +144,12 @@ def use_setuptools( DeprecationWarning, ) to_dir = os.path.abspath(to_dir) + + # prior to importing, capture the module state for + # representative modules. rep_modules = 'pkg_resources', 'setuptools' imported = set(sys.modules).intersection(rep_modules) + try: import pkg_resources pkg_resources.require("setuptools>=" + version) -- cgit v1.2.1 From 3735dd9e689cd98d6ee45fcdac21d1f41c952a76 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 10:15:58 -0500 Subject: Update changelog --- CHANGES.txt | 11 +++++++++++ ez_setup.py | 10 +++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index f77ab24b..4e058be8 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,16 @@ CHANGES ======= +---- +12.2 +---- + +* Issue #345: Unload all modules under pkg_resources during + ``ez_setup.use_setuptools()``. +* Issue #336: Removed deprecation from ``ez_setup.use_setuptools``, + as it is clearly still used by buildout's bootstrap. ``ez_setup`` + remains deprecated for use by individual packages. + ---- 12.1 ---- @@ -14,6 +24,7 @@ CHANGES ------ * Issue #339: Correct Attribute reference in ``cant_write_to_target``. +* Issue #336: Deprecated ``ez_setup.use_setuptools``. ------ 12.0.4 diff --git a/ez_setup.py b/ez_setup.py index 26e42998..4bd83580 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -134,15 +134,11 @@ def use_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15): """ - *deprecated* Download, install, and import Setuptools. + Ensure that a setuptools version is installed. - Return None. + Return None. Raise SystemExit if the requested version + or later cannot be installed. """ - warnings.warn( - "`use_setuptools` is deprecated. To enforce a specific " - "version of setuptools, use `pkg_resources.require`.", - DeprecationWarning, - ) to_dir = os.path.abspath(to_dir) # prior to importing, capture the module state for -- cgit v1.2.1 From e69b9745ff0d8bd3ab134a80d1c91707377d06ed Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 10:19:24 -0500 Subject: Update changelog --- CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.txt b/CHANGES.txt index 4e058be8..45658bb0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -11,6 +11,7 @@ CHANGES * Issue #336: Removed deprecation from ``ez_setup.use_setuptools``, as it is clearly still used by buildout's bootstrap. ``ez_setup`` remains deprecated for use by individual packages. +* Simplified implementation of ``ez_setup.use_setuptools``. ---- 12.1 -- cgit v1.2.1 From dcc413ea650eacd7c9fdcf824f65501dd39748ed Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 10:24:28 -0500 Subject: Added tag 12.2 for changeset 5ff5c804a8fa --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index e9d7e3de..1b63050d 100644 --- a/.hgtags +++ b/.hgtags @@ -193,3 +193,4 @@ bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 73dcfc90e3eecec6baddea19302c6b342e68e2fa 12.0.4 01fbfc9194a2bc502edd682eebbf4d2f1bc79eee 12.0.5 7bca8938434839dbb546b8bfccd9aab7a86d851e 12.1 +5ff5c804a8fa580cff499ba0025ff2e6a5474fd0 12.2 -- cgit v1.2.1 From 582d31e08ea15893f98deddfaa476cd294f1b5db Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 10:25:13 -0500 Subject: Bumped to 12.3 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 4bd83580..426a22c9 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.2" +DEFAULT_VERSION = "12.3" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" diff --git a/setuptools/version.py b/setuptools/version.py index c59a5777..c2fa1dce 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.2' +__version__ = '12.3' -- cgit v1.2.1 From c30d4387af485202103c76b13c2741b5bd78b410 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 16 Feb 2015 10:32:17 -0500 Subject: Bump script used for ez_setup.py --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0e648b38..16605597 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,4 +12,4 @@ script: - python bootstrap.py - python setup.py ptr --addopts='-rs' - - python ez_setup.py --version 10.2.1 + - python ez_setup.py --version 12.2 -- cgit v1.2.1 From 47cbdc5228ca5a730518f1cca83df283c54f7249 Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Wed, 18 Feb 2015 20:42:49 +0100 Subject: Fix setuptools.command.easy_install.extract_wininst_cfg() with Python 2.6 and 2.7. It was broken since commit 3bbd42903af8, which changed chr(0) (which is '\x00') into bytes([0]). bytes([0]) is '[0]' in Python 2.6 and 2.7 and b'\x00' in Python 3. --- setuptools/command/easy_install.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index e057b508..b039e2da 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1413,13 +1413,8 @@ def extract_wininst_cfg(dist_filename): {'version': '', 'target_version': ''}) try: part = f.read(cfglen) - # part is in bytes, but we need to read up to the first null - # byte. - if sys.version_info >= (2, 6): - null_byte = bytes([0]) - else: - null_byte = chr(0) - config = part.split(null_byte, 1)[0] + # Read up to the first null byte. + config = part.split(b'\0', 1)[0] # Now the config is in bytes, but for RawConfigParser, it should # be text, so decode it. config = config.decode(sys.getfilesystemencoding()) -- cgit v1.2.1 From b16a6dd269e4fd283a78834c7f379c977aad0f6e Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Wed, 18 Feb 2015 21:09:01 +0100 Subject: Delete some dead code. --- setuptools/command/bdist_egg.py | 13 ++----------- setuptools/command/build_py.py | 17 +---------------- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/setuptools/command/bdist_egg.py b/setuptools/command/bdist_egg.py index 34fdeec2..87dce882 100644 --- a/setuptools/command/bdist_egg.py +++ b/setuptools/command/bdist_egg.py @@ -2,7 +2,6 @@ Build .egg distributions""" -# This module should be kept compatible with Python 2.3 from distutils.errors import DistutilsSetupError from distutils.dir_util import remove_tree, mkpath from distutils import log @@ -406,10 +405,6 @@ def scan_module(egg_dir, base, name, stubs): if bad in symbols: log.warn("%s: module MAY be using inspect.%s", module, bad) safe = False - if '__name__' in symbols and '__main__' in symbols and '.' not in module: - if sys.version[:3] == "2.4": # -m works w/zipfiles in 2.5 - log.warn("%s: top-level module may be 'python -m' script", module) - safe = False return safe @@ -441,7 +436,7 @@ INSTALL_DIRECTORY_ATTRS = [ ] -def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=None, +def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=True, mode='w'): """Create a zip file from all the files under 'base_dir'. The output zip file will be named 'base_dir' + ".zip". Uses either the "zipfile" @@ -463,11 +458,7 @@ def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=None, z.write(path, p) log.debug("adding '%s'" % p) - if compress is None: - # avoid 2.3 zipimport bug when 64 bits - compress = (sys.version >= "2.4") - - compression = [zipfile.ZIP_STORED, zipfile.ZIP_DEFLATED][bool(compress)] + compression = zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED if not dry_run: z = zipfile.ZipFile(zip_filename, mode, compression=compression) for dirname, dirs, files in os.walk(base_dir): diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 98080694..a873d54b 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -136,22 +136,7 @@ class build_py(orig.build_py, Mixin2to3): mf.setdefault(src_dirs[d], []).append(path) def get_data_files(self): - pass # kludge 2.4 for lazy computation - - if sys.version < "2.4": # Python 2.4 already has this code - def get_outputs(self, include_bytecode=1): - """Return complete list of files copied to the build directory - - This includes both '.py' files and data files, as well as '.pyc' - and '.pyo' files if 'include_bytecode' is true. (This method is - needed for the 'install_lib' command to do its job properly, and to - generate a correct installation manifest.) - """ - return orig.build_py.get_outputs(self, include_bytecode) + [ - os.path.join(build_dir, filename) - for package, src_dir, build_dir, filenames in self.data_files - for filename in filenames - ] + pass # Lazily compute data files in _get_data_files() function. def check_package(self, package, package_dir): """Check namespace packages' __init__ for declare_namespace""" -- cgit v1.2.1 From 02fac66f96af6b6952d227809186db1c5ae628a6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Feb 2015 22:36:06 -0600 Subject: Use rst.linker for generating linked changelog --- docs/conf.py | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- linkify.py | 56 -------------------------------------------------------- setup.py | 1 + 3 files changed, 49 insertions(+), 57 deletions(-) delete mode 100644 linkify.py diff --git a/docs/conf.py b/docs/conf.py index 5ea2e05e..24830987 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,7 +28,7 @@ import setup as setup_script # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['linkify'] +extensions = ['rst.linker'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -198,3 +198,50 @@ latex_documents = [ # If false, no module index is generated. #latex_use_modindex = True + +link_files = { + 'CHANGES.txt': dict( + using=dict( + BB='https://bitbucket.org', + GH='https://github.com', + ), + replace=[ + dict( + pattern=r"(Issue )?#(?P\d+)", + url='{BB}/pypa/setuptools/issue/{issue}', + ), + dict( + pattern=r"Pull Request ?#(?P\d+)", + url='{BB}/pypa/setuptools/pull-request/{pull_request}', + ), + dict( + pattern=r"Distribute #(?P\d+)", + url='{BB}/tarek/distribute/issue/{distribute}', + ), + dict( + pattern=r"Buildout #(?P\d+)", + url='{GH}/buildout/buildout/issues/{buildout}', + ), + dict( + pattern=r"Old Setuptools #(?P\d+)", + url='http://bugs.python.org/setuptools/issue{old_setuptools}', + ), + dict( + pattern=r"Jython #(?P\d+)", + url='http://bugs.jython.org/issue{jython}', + ), + dict( + pattern=r"Python #(?P\d+)", + url='http://bugs.python.org/issue{python}', + ), + dict( + pattern=r"Interop #(?P\d+)", + url='{GH}/pypa/interoperability-peps/issues/{interop}', + ), + dict( + pattern=r"Pip #(?P\d+)", + url='{GH}/pypa/pip/issues/{pip}', + ), + ], + ), +} diff --git a/linkify.py b/linkify.py deleted file mode 100644 index 5c6e16b4..00000000 --- a/linkify.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Sphinx plugin to add links to the changelog. -""" - -import re -import os - - -link_patterns = [ - r"(Issue )?#(?P\d+)", - r"Pull Request ?#(?P\d+)", - r"Distribute #(?P\d+)", - r"Buildout #(?P\d+)", - r"Old Setuptools #(?P\d+)", - r"Jython #(?P\d+)", - r"Python #(?P\d+)", - r"Interop #(?P\d+)", - r"Pip #(?P\d+)", -] - -issue_urls = dict( - pull_request='https://bitbucket.org' - '/pypa/setuptools/pull-request/{pull_request}', - issue='https://bitbucket.org/pypa/setuptools/issue/{issue}', - distribute='https://bitbucket.org/tarek/distribute/issue/{distribute}', - buildout='https://github.com/buildout/buildout/issues/{buildout}', - old_setuptools='http://bugs.python.org/setuptools/issue{old_setuptools}', - jython='http://bugs.jython.org/issue{jython}', - python='http://bugs.python.org/issue{python}', - interop='https://github.com/pypa/interoperability-peps/issues/{interop}', - pip='https://github.com/pypa/pip/issues/{pip}', -) - - -def _linkify(source, dest): - pattern = '|'.join(link_patterns) - with open(source) as source: - out = re.sub(pattern, replacer, source.read()) - with open(dest, 'w') as dest: - dest.write(out) - - -def replacer(match): - text = match.group(0) - match_dict = match.groupdict() - for key in match_dict: - if match_dict[key]: - url = issue_urls[key].format(**match_dict) - return "`{text} <{url}>`_".format(text=text, url=url) - -def setup(app): - _linkify('CHANGES.txt', 'CHANGES (links).txt') - app.connect('build-finished', remove_file) - -def remove_file(app, exception): - os.remove('CHANGES (links).txt') diff --git a/setup.py b/setup.py index 63093917..9d4330ac 100755 --- a/setup.py +++ b/setup.py @@ -172,6 +172,7 @@ setup_params = dict( 'pytest', ] + (['mock'] if sys.version_info[:2] < (3, 3) else []), setup_requires=[ + 'rst.linker', ] + pytest_runner, ) -- cgit v1.2.1 From 70b0594ff0d67dba65feb59a606007768eced05b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 25 Feb 2015 08:51:24 -0500 Subject: Only require rst.linker when docs commands are invoked. Also specify sphinx dependency. --- setup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 9d4330ac..807c0180 100755 --- a/setup.py +++ b/setup.py @@ -76,6 +76,8 @@ if sys.platform == 'win32' or force_windows_specific_files: package_data.setdefault('setuptools.command', []).extend(['*.xml']) pytest_runner = ['pytest-runner'] if 'ptr' in sys.argv else [] +needs_sphinx = set(['build_sphinx', 'upload_docs']).intersection(sys.argv) +sphinx = ['sphinx', 'rst.linker'] if needs_sphinx else [] setup_params = dict( name="setuptools", @@ -172,8 +174,7 @@ setup_params = dict( 'pytest', ] + (['mock'] if sys.version_info[:2] < (3, 3) else []), setup_requires=[ - 'rst.linker', - ] + pytest_runner, + ] + sphinx + pytest_runner, ) if __name__ == '__main__': -- cgit v1.2.1 From 34bd844443954929c7199e772e715ed6f0669332 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 25 Feb 2015 08:52:48 -0500 Subject: Update conditional setup-time dependency to also support pytest and test commands. --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 807c0180..e1b302a3 100755 --- a/setup.py +++ b/setup.py @@ -75,7 +75,8 @@ if sys.platform == 'win32' or force_windows_specific_files: package_data.setdefault('setuptools', []).extend(['*.exe']) package_data.setdefault('setuptools.command', []).extend(['*.xml']) -pytest_runner = ['pytest-runner'] if 'ptr' in sys.argv else [] +needs_pytest = set(['ptr', 'pytest', 'test']) in sys.argv else [] +pytest_runner = ['pytest-runner'] if needs_pytest else [] needs_sphinx = set(['build_sphinx', 'upload_docs']).intersection(sys.argv) sphinx = ['sphinx', 'rst.linker'] if needs_sphinx else [] -- cgit v1.2.1 From eaeaf36088bccfcb35e798dcfa4ad187ef05f2f5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 25 Feb 2015 08:54:00 -0500 Subject: Move pytest config to pytest.ini (as it conflicts with the pytest-runner pytest command). --- pytest.ini | 3 +++ setup.cfg | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100755 pytest.ini diff --git a/pytest.ini b/pytest.ini new file mode 100755 index 00000000..91d64bb8 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +addopts=--doctest-modules --ignore release.py --ignore setuptools/lib2to3_ex.py --ignore tests/manual_test.py --ignore tests/shlib_test --doctest-glob=pkg_resources/api_tests.txt +norecursedirs=dist build *.egg diff --git a/setup.cfg b/setup.cfg index 5937edd0..a6da2c77 100755 --- a/setup.cfg +++ b/setup.cfg @@ -5,6 +5,7 @@ tag_build = dev release = egg_info -RDb '' source = register sdist binary binary = bdist_egg upload --show-response +test = pytest [build_sphinx] source-dir = docs/ @@ -19,7 +20,3 @@ formats = gztar zip [wheel] universal=1 - -[pytest] -addopts=--doctest-modules --ignore release.py --ignore setuptools/lib2to3_ex.py --ignore tests/manual_test.py --ignore tests/shlib_test --doctest-glob=pkg_resources/api_tests.txt -norecursedirs=dist build *.egg -- cgit v1.2.1 From d21b8dbfa1f0ad6f4c3f5b4101035c228bd6a6d8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 25 Feb 2015 08:54:29 -0500 Subject: Now tests may be invoked simply with setup.py test. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 16605597..45cace4b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,5 +11,5 @@ script: # update egg_info based on setup.py in checkout - python bootstrap.py - - python setup.py ptr --addopts='-rs' + - python setup.py test --addopts='-rs' - python ez_setup.py --version 12.2 -- cgit v1.2.1 From 3bf060e378ce5d942079452450864ef30bdaa44f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 25 Feb 2015 09:03:49 -0500 Subject: Correct usage in needs_pytest --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e1b302a3..438e512b 100755 --- a/setup.py +++ b/setup.py @@ -75,7 +75,7 @@ if sys.platform == 'win32' or force_windows_specific_files: package_data.setdefault('setuptools', []).extend(['*.exe']) package_data.setdefault('setuptools.command', []).extend(['*.xml']) -needs_pytest = set(['ptr', 'pytest', 'test']) in sys.argv else [] +needs_pytest = set(['ptr', 'pytest', 'test']).intersection(sys.argv) pytest_runner = ['pytest-runner'] if needs_pytest else [] needs_sphinx = set(['build_sphinx', 'upload_docs']).intersection(sys.argv) sphinx = ['sphinx', 'rst.linker'] if needs_sphinx else [] -- cgit v1.2.1 From 0dc29630918288846f3a398d884de8ecd9db7ced Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 26 Feb 2015 13:59:06 -0500 Subject: Formally describe the supported documentation build process. Fixes #354. --- docs/developer-guide.txt | 17 +++++++++++++++++ docs/development.txt | 1 - 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index 558d6ee7..27c304e5 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -109,3 +109,20 @@ Setuptools follows ``semver`` with some exceptions: - Omits 'v' prefix for tags. .. explain value of reflecting meaning in versions. + +---------------------- +Building Documentation +---------------------- + +Setuptools relies on the Sphinx system for building documentation and in +particular the ``build_sphinx`` distutils command. To build the +documentation, invoke:: + + python setup.py build_sphinx + +from the root of the repository. Setuptools will download a compatible +build of Sphinx and any requisite plugins and then build the +documentation in the build/sphinx directory. + +Setuptools does not support invoking the doc builder from the docs/ +directory as some tools expect. diff --git a/docs/development.txt b/docs/development.txt index 6fe30f6e..455f038a 100644 --- a/docs/development.txt +++ b/docs/development.txt @@ -33,4 +33,3 @@ setuptools changes. You have been warned. developer-guide formats releases - -- cgit v1.2.1 From d98aadec63981a34eff17f502038e132fa131432 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 26 Feb 2015 14:13:50 -0500 Subject: Update changelog --- CHANGES.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 45658bb0..5be54711 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,16 @@ CHANGES ======= +---- +12.3 +---- + +* Documentation is now linked using the rst.linker package. +* Fix ``setuptools.command.easy_install.extract_wininst_cfg()`` + with Python 2.6 and 2.7. +* Issue #354. Added documentation on building setuptools + documentation. + ---- 12.2 ---- -- cgit v1.2.1 From 89f72e5dc90554be4dddd09381150a67588266cf Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 26 Feb 2015 14:15:26 -0500 Subject: Added tag 12.3 for changeset 8d50aac3b207 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 1b63050d..b0ab3b16 100644 --- a/.hgtags +++ b/.hgtags @@ -194,3 +194,4 @@ bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 01fbfc9194a2bc502edd682eebbf4d2f1bc79eee 12.0.5 7bca8938434839dbb546b8bfccd9aab7a86d851e 12.1 5ff5c804a8fa580cff499ba0025ff2e6a5474fd0 12.2 +8d50aac3b20793954121edb300b477cc75f3ec96 12.3 -- cgit v1.2.1 From f8813bed5e035a4b7f3deba54949439e846c8125 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 26 Feb 2015 14:16:10 -0500 Subject: Bumped to 12.4 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 426a22c9..5221b4ff 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.3" +DEFAULT_VERSION = "12.4" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" diff --git a/setuptools/version.py b/setuptools/version.py index c2fa1dce..f64c7985 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.3' +__version__ = '12.4' -- cgit v1.2.1 From 5153b6f17cb2b6fac162a9ae1a989b976cc6d7de Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 3 Mar 2015 17:50:32 -0500 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 5be54711..82f4db61 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +---- +12.4 +---- + +* Pull Request #119: Restore writing of ``setup_requires`` to metadata + (previously added in 8.4 and removed in 9.0). + ---- 12.3 ---- -- cgit v1.2.1 From fe899eef84b75a58aeb443e36904e9f4a5fd5c20 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 4 Mar 2015 10:10:44 -0500 Subject: Reindent header --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 021e7fee..7a404f82 100755 --- a/setup.py +++ b/setup.py @@ -1,5 +1,8 @@ #!/usr/bin/env python -"""Distutils setup file, used to install or test 'setuptools'""" +""" +Distutils setup file, used to install or test 'setuptools' +""" + import io import os import sys -- cgit v1.2.1 From 7a410b2cafcbeac951d88e8070b378cfb1001de0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 4 Mar 2015 11:07:53 -0500 Subject: Added tag 12.4 for changeset 297931cb8cac --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index b0ab3b16..9a949af9 100644 --- a/.hgtags +++ b/.hgtags @@ -195,3 +195,4 @@ bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 7bca8938434839dbb546b8bfccd9aab7a86d851e 12.1 5ff5c804a8fa580cff499ba0025ff2e6a5474fd0 12.2 8d50aac3b20793954121edb300b477cc75f3ec96 12.3 +297931cb8cac7d44d970adb927efd6cb36ac3526 12.4 -- cgit v1.2.1 From 7aa02cb6109845a421aabdc366216dacfdf38d33 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 4 Mar 2015 11:09:37 -0500 Subject: Bumped to 12.5 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 5221b4ff..6f6a8319 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.4" +DEFAULT_VERSION = "12.5" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" diff --git a/setuptools/version.py b/setuptools/version.py index f64c7985..e5fc9c8c 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.4' +__version__ = '12.5' -- cgit v1.2.1 From ee36e46917421eb503f2e6d41f7421463564845b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 19:28:34 -0500 Subject: Backed out changeset: 8bff4399a7af; Fixes #356 --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 7a404f82..5d98de06 100755 --- a/setup.py +++ b/setup.py @@ -132,7 +132,6 @@ setup_params = dict( "egg_info.writers": [ "PKG-INFO = setuptools.command.egg_info:write_pkg_info", "requires.txt = setuptools.command.egg_info:write_requirements", - "setup_requires.txt = setuptools.command.egg_info:write_setup_requirements", "entry_points.txt = setuptools.command.egg_info:write_entries", "eager_resources.txt = setuptools.command.egg_info:overwrite_arg", "namespace_packages.txt = setuptools.command.egg_info:overwrite_arg", -- cgit v1.2.1 From 80df5396a629d49b826b7522f7a72c15b75b710a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 19:31:08 -0500 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 82f4db61..78469cbd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +---- +13.0 +---- + +* Issue #356: Back out Pull Request #119 as it requires Setuptools 10 or later + as the source during an upgrade. + ---- 12.4 ---- -- cgit v1.2.1 From 4e0a8cd8f37e4f427a75cac454bea4aca0c4ea0c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 19:37:20 -0500 Subject: Remove build_py (unused) --- CHANGES.txt | 1 + setup.py | 15 --------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 78469cbd..bf0acb1a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,7 @@ CHANGES * Issue #356: Back out Pull Request #119 as it requires Setuptools 10 or later as the source during an upgrade. +* Removed apparently unused build_py class in setup.py. ---- 12.4 diff --git a/setup.py b/setup.py index 5d98de06..234a7885 100755 --- a/setup.py +++ b/setup.py @@ -28,7 +28,6 @@ with open(ver_path) as ver_file: exec(ver_file.read(), main_ns) import setuptools -from setuptools.command.build_py import build_py as _build_py scripts = [] @@ -49,20 +48,6 @@ def _gen_console_scripts(): console_scripts = list(_gen_console_scripts()) - -# specific command that is used to generate windows .exe files -class build_py(_build_py): - def build_package_data(self): - """Copy data files into build directory""" - for package, src_dir, build_dir, filenames in self.data_files: - for filename in filenames: - target = os.path.join(build_dir, filename) - self.mkpath(os.path.dirname(target)) - srcfile = os.path.join(src_dir, filename) - outf, copied = self.copy_file(srcfile, target) - srcfile = os.path.abspath(srcfile) - - readme_file = io.open('README.txt', encoding='utf-8') with readme_file: -- cgit v1.2.1 From 67aa21c88ef5e57d7a2d0f379c970e5987c14cd4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 19:51:32 -0500 Subject: Bumped to 13.0 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 6f6a8319..a709688f 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "12.5" +DEFAULT_VERSION = "13.0" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" diff --git a/setuptools/version.py b/setuptools/version.py index e5fc9c8c..0a56eb68 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '12.5' +__version__ = '13.0' -- cgit v1.2.1 From 2168ff0927546296e304dc457d6a013edf0dfe7f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 20:16:35 -0500 Subject: Update changelog --- CHANGES.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index bf0acb1a..1b99e9c5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,7 +8,9 @@ CHANGES * Issue #356: Back out Pull Request #119 as it requires Setuptools 10 or later as the source during an upgrade. -* Removed apparently unused build_py class in setup.py. +* Removed build_py class from setup.py. According to 892f439d216e, this + functionality was added to support upgrades from old Distribute versions, + 0.6.5 and 0.6.6. ---- 12.4 -- cgit v1.2.1 From 9f12c42238c20fa92efbc78a0762b57756c20d24 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 20:37:51 -0500 Subject: Added tag 13.0 for changeset df34cc186242 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 9a949af9..15190e1c 100644 --- a/.hgtags +++ b/.hgtags @@ -196,3 +196,4 @@ bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 5ff5c804a8fa580cff499ba0025ff2e6a5474fd0 12.2 8d50aac3b20793954121edb300b477cc75f3ec96 12.3 297931cb8cac7d44d970adb927efd6cb36ac3526 12.4 +df34cc18624279faffdbc729c0a11e6ab0f46572 13.0 -- cgit v1.2.1 From e556b07add2c521523bfd48f69397b0982bcc963 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 20:42:28 -0500 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 1b99e9c5..cc9c3939 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +------ +13.0.1 +------ + +Re-release of 13.0. Intermittent connectivity issues caused the release +process to fail and PyPI uploads no longer accept files for 13.0. + ---- 13.0 ---- -- cgit v1.2.1 From 1914157913c7e28c21ccb8fa5ffe7581721d5bad Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 20:42:40 -0500 Subject: Bumped to 13.0.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index a709688f..0fd17a5c 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "13.0" +DEFAULT_VERSION = "13.0.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" diff --git a/setuptools/version.py b/setuptools/version.py index 0a56eb68..d1ff1727 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '13.0' +__version__ = '13.0.1' -- cgit v1.2.1 From 5a1ac91fede0884c66cb2008485c13020f831a10 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 20:42:42 -0500 Subject: Added tag 13.0.1 for changeset ae1a5c5cf78f --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 15190e1c..0a790e01 100644 --- a/.hgtags +++ b/.hgtags @@ -197,3 +197,4 @@ bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 8d50aac3b20793954121edb300b477cc75f3ec96 12.3 297931cb8cac7d44d970adb927efd6cb36ac3526 12.4 df34cc18624279faffdbc729c0a11e6ab0f46572 13.0 +ae1a5c5cf78f4f9f98c054f1c8cec6168d1d19b4 13.0.1 -- cgit v1.2.1 From 570305131f408b42522d1d7e87292ec752457e65 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 20:43:59 -0500 Subject: Bumped to 13.0.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 0fd17a5c..d0af7948 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "13.0.1" +DEFAULT_VERSION = "13.0.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" diff --git a/setuptools/version.py b/setuptools/version.py index d1ff1727..525a47ea 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '13.0.1' +__version__ = '13.0.2' -- cgit v1.2.1 From 973df2da9c895ce58955121f6cf7cbde4b7fe0ee Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 21:30:58 -0500 Subject: Extract function for _download_args --- ez_setup.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index d0af7948..e58f43d3 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -364,14 +364,19 @@ def _parse_args(): return options +def _download_args(options): + """Return args for download_setuptools function from cmdline args.""" + return dict( + version=options.version, + download_base=options.download_base, + downloader_factory=options.downloader_factory, + ) + + def main(): """Install or upgrade setuptools and EasyInstall.""" options = _parse_args() - archive = download_setuptools( - version=options.version, - download_base=options.download_base, - downloader_factory=options.downloader_factory, - ) + archive = download_setuptools(**_download_args(options)) return _install(archive, _build_install_args(options)) if __name__ == '__main__': -- cgit v1.2.1 From 4368e4a2d3f1e0de7a29b909c2cff599b211a441 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 21:47:08 -0500 Subject: Add --to-dir to bootstrap script --- CHANGES.txt | 8 ++++++++ ez_setup.py | 12 ++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index cc9c3939..62272286 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +---- +13.1 +---- + +Bootstrap script now accepts ``--to-dir`` to customize save directory or +allow for re-use of existing repository of setuptools versions. See +Pull Request #112 for an alternate implementation. + ------ 13.0.1 ------ diff --git a/ez_setup.py b/ez_setup.py index e58f43d3..9ece89d7 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -32,6 +32,7 @@ except ImportError: DEFAULT_VERSION = "13.0.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" +DEFAULT_SAVE_DIR = os.curdir def _python_cmd(*args): @@ -132,7 +133,7 @@ def _do_download(version, download_base, to_dir, download_delay): def use_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, - to_dir=os.curdir, download_delay=15): + to_dir=DEFAULT_SAVE_DIR, download_delay=15): """ Ensure that a setuptools version is installed. @@ -306,7 +307,8 @@ def get_best_downloader(): def download_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, - to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader): + to_dir=DEFAULT_SAVE_DIR, delay=15, + downloader_factory=get_best_downloader): """ Download setuptools from a specified location and return its filename. @@ -359,6 +361,11 @@ def _parse_args(): '--version', help="Specify which version to download", default=DEFAULT_VERSION, ) + parser.add_option( + '--to-dir', + help="Directory to save (and re-use) package", + default=DEFAULT_SAVE_DIR, + ) options, args = parser.parse_args() # positional arguments are ignored return options @@ -370,6 +377,7 @@ def _download_args(options): version=options.version, download_base=options.download_base, downloader_factory=options.downloader_factory, + to_dir=options.to_dir, ) -- cgit v1.2.1 From cf8edd7c24a6afdb81ac928f348faeaba77860bf Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 5 Mar 2015 22:28:53 -0500 Subject: Update changelog --- CHANGES.txt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 62272286..dfb7ba39 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,12 +3,20 @@ CHANGES ======= ---- -13.1 +14.0 ---- -Bootstrap script now accepts ``--to-dir`` to customize save directory or -allow for re-use of existing repository of setuptools versions. See -Pull Request #112 for an alternate implementation. +* Bootstrap script now accepts ``--to-dir`` to customize save directory or + allow for re-use of existing repository of setuptools versions. See + Pull Request #112 for an alternate implementation. +* Issue #285: ``easy_install`` no longer will default to installing + packages to the "user site packages" directory if it is itself installed + there. Instead, the user must pass ``--user`` in all cases to install + packages to the user site packages. + This behavior now matches that of "pip install". To configure + an environment to always install to the user site packages, consider + using the "install-dir" and "scripts-dir" parameters to easy_install + through an appropriate distutils config file. ------ 13.0.1 -- cgit v1.2.1 From 78337beb23e68b062f60f42e1f7baf1d51f2587d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 10:50:30 -0500 Subject: Include pytest.ini in MANIFEST.in. Fixes #359. --- CHANGES.txt | 7 +++++++ MANIFEST.in | 1 + 2 files changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index cc9c3939..f7c56b4a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +------ +13.0.2 +------ + +* Issue #359: Include pytest.ini in the sdist so invocation of py.test on the + sdist honors the pytest configuration. + ------ 13.0.1 ------ diff --git a/MANIFEST.in b/MANIFEST.in index 428bbd1e..8a4523a9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,3 +9,4 @@ include *.txt include MANIFEST.in include launcher.c include msvc-build-launcher.cmd +include pytest.ini -- cgit v1.2.1 From 64297dfe3bf0088480b0499b6bb5dc7d5946938b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 10:56:46 -0500 Subject: Added tag 13.0.2 for changeset e22a1d613bdd --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 0a790e01..e21214e5 100644 --- a/.hgtags +++ b/.hgtags @@ -198,3 +198,4 @@ bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 297931cb8cac7d44d970adb927efd6cb36ac3526 12.4 df34cc18624279faffdbc729c0a11e6ab0f46572 13.0 ae1a5c5cf78f4f9f98c054f1c8cec6168d1d19b4 13.0.1 +e22a1d613bddf311e125eecd9c1e1cad02ab5063 13.0.2 -- cgit v1.2.1 From 01e38bed190a1278f231f101431e2d09071de678 Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Fri, 6 Mar 2015 09:11:39 -0800 Subject: Add __ne__ method to Requirement class It seems like if it has an `__eq__` method, it should probably have a `__ne__` method. I ran into this while working on pip -- see https://github.com/pypa/pip/pull/2493#discussion_r25955295 --- pkg_resources/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 2ce663d2..7701292b 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2907,6 +2907,9 @@ class Requirement: self.hashCmp == other.hashCmp ) + def __ne__(self, other): + return not self == other + def __contains__(self, item): if isinstance(item, Distribution): if item.key != self.key: -- cgit v1.2.1 From d138579b07086630732fa949a947dfad34a241d5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 15:46:27 -0500 Subject: Update test to match new expectation following pull request #109. Refs #285. --- setuptools/tests/test_easy_install.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index b9b2e392..af09d681 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -156,15 +156,17 @@ class TestUserInstallTest: @mock.patch('setuptools.command.easy_install.__file__', None) def test_user_install_implied(self): + # simulate setuptools installed in user site packages easy_install_pkg.__file__ = site.USER_SITE - site.ENABLE_USER_SITE = True # disabled sometimes - #XXX: replace with something meaningfull + site.ENABLE_USER_SITE = True + + # create a finalized easy_install command dist = Distribution() dist.script_name = 'setup.py' cmd = ei.easy_install(dist) cmd.args = ['py'] cmd.ensure_finalized() - assert cmd.user, 'user should be implied' + assert not cmd.user, 'user should not be implied' def test_multiproc_atexit(self): try: -- cgit v1.2.1 From c05957b09a66c4728c9a578e2e5f33fbd7b97977 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 15:48:40 -0500 Subject: Use pytest.importorskip. --- setuptools/tests/test_easy_install.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index af09d681..8ba0c49c 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -169,11 +169,7 @@ class TestUserInstallTest: assert not cmd.user, 'user should not be implied' def test_multiproc_atexit(self): - try: - __import__('multiprocessing') - except ImportError: - # skip the test if multiprocessing is not available - return + pytest.importorskip('multiprocessing') log = logging.getLogger('test_easy_install') logging.basicConfig(level=logging.INFO, stream=sys.stderr) -- cgit v1.2.1 From 1ea8018e5c3a8c7c8d980368efc5ac3b81df37e9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 15:49:04 -0500 Subject: Rename test to reflect implementation. --- setuptools/tests/test_easy_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 8ba0c49c..36d66428 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -155,7 +155,7 @@ def setup_context(tmpdir): class TestUserInstallTest: @mock.patch('setuptools.command.easy_install.__file__', None) - def test_user_install_implied(self): + def test_user_install_not_implied(self): # simulate setuptools installed in user site packages easy_install_pkg.__file__ = site.USER_SITE site.ENABLE_USER_SITE = True -- cgit v1.2.1 From 55f0838ddfdd301f6f69369f94a3b476b5591b71 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 15:49:46 -0500 Subject: Move related tests into proximity --- setuptools/tests/test_easy_install.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 36d66428..2f7b27c5 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -168,13 +168,6 @@ class TestUserInstallTest: cmd.ensure_finalized() assert not cmd.user, 'user should not be implied' - def test_multiproc_atexit(self): - pytest.importorskip('multiprocessing') - - log = logging.getLogger('test_easy_install') - logging.basicConfig(level=logging.INFO, stream=sys.stderr) - log.info('this should not break') - def test_user_install_not_implied_without_usersite_enabled(self): site.ENABLE_USER_SITE = False # usually enabled #XXX: replace with something meaningfull @@ -185,6 +178,13 @@ class TestUserInstallTest: cmd.initialize_options() assert not cmd.user, 'NOT user should be implied' + def test_multiproc_atexit(self): + pytest.importorskip('multiprocessing') + + log = logging.getLogger('test_easy_install') + logging.basicConfig(level=logging.INFO, stream=sys.stderr) + log.info('this should not break') + def test_local_index(self): # make sure the local index is used # when easy_install looks for installed -- cgit v1.2.1 From dc5ad278255437f54f3033e5c526d6f2d1d1f2e5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 15:51:33 -0500 Subject: Functions now mirror each other. --- setuptools/tests/test_easy_install.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 2f7b27c5..ec5d5faa 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -155,7 +155,7 @@ def setup_context(tmpdir): class TestUserInstallTest: @mock.patch('setuptools.command.easy_install.__file__', None) - def test_user_install_not_implied(self): + def test_user_install_not_implied_user_site_enabled(self): # simulate setuptools installed in user site packages easy_install_pkg.__file__ = site.USER_SITE site.ENABLE_USER_SITE = True @@ -168,9 +168,11 @@ class TestUserInstallTest: cmd.ensure_finalized() assert not cmd.user, 'user should not be implied' - def test_user_install_not_implied_without_usersite_enabled(self): - site.ENABLE_USER_SITE = False # usually enabled - #XXX: replace with something meaningfull + def test_user_install_not_implied_user_site_disabled(self): + # ensure user-site not enabled + site.ENABLE_USER_SITE = False + + # create a finalized easy_install command dist = Distribution() dist.script_name = 'setup.py' cmd = ei.easy_install(dist) -- cgit v1.2.1 From 997f97fcf456e9f63664e356e5ed2838e33d4cba Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 15:53:13 -0500 Subject: Extract method for common behavior. --- setuptools/tests/test_easy_install.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index ec5d5faa..eed3bdb5 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -160,25 +160,23 @@ class TestUserInstallTest: easy_install_pkg.__file__ = site.USER_SITE site.ENABLE_USER_SITE = True - # create a finalized easy_install command - dist = Distribution() - dist.script_name = 'setup.py' - cmd = ei.easy_install(dist) - cmd.args = ['py'] - cmd.ensure_finalized() - assert not cmd.user, 'user should not be implied' + self.assert_not_user_site() def test_user_install_not_implied_user_site_disabled(self): # ensure user-site not enabled site.ENABLE_USER_SITE = False + self.assert_not_user_site() + + @staticmethod + def assert_not_user_site(): # create a finalized easy_install command dist = Distribution() dist.script_name = 'setup.py' cmd = ei.easy_install(dist) cmd.args = ['py'] - cmd.initialize_options() - assert not cmd.user, 'NOT user should be implied' + cmd.ensure_finalized() + assert not cmd.user, 'user should not be implied' def test_multiproc_atexit(self): pytest.importorskip('multiprocessing') -- cgit v1.2.1 From 52172aa131f643c83370aa36968fa3f279c53858 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 15:58:03 -0500 Subject: Move patching into the patch methods. --- setuptools/tests/test_easy_install.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index eed3bdb5..773ca6b6 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -154,18 +154,14 @@ def setup_context(tmpdir): @pytest.mark.usefixtures("setup_context") class TestUserInstallTest: - @mock.patch('setuptools.command.easy_install.__file__', None) + # simulate setuptools installed in user site packages + @mock.patch('setuptools.command.easy_install.__file__', site.USER_SITE) + @mock.patch('site.ENABLE_USER_SITE', True) def test_user_install_not_implied_user_site_enabled(self): - # simulate setuptools installed in user site packages - easy_install_pkg.__file__ = site.USER_SITE - site.ENABLE_USER_SITE = True - self.assert_not_user_site() + @mock.patch('site.ENABLE_USER_SITE', False) def test_user_install_not_implied_user_site_disabled(self): - # ensure user-site not enabled - site.ENABLE_USER_SITE = False - self.assert_not_user_site() @staticmethod -- cgit v1.2.1 From 85dd199e880fdf29a2dbe25bff944b5fc3b1081e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 16:00:56 -0500 Subject: Replace comment with docstring assertion. --- setuptools/tests/test_easy_install.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 773ca6b6..4942acbf 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -182,9 +182,10 @@ class TestUserInstallTest: log.info('this should not break') def test_local_index(self): - # make sure the local index is used - # when easy_install looks for installed - # packages + """ + The local index must be used when easy_install locates installed + packages. + """ new_location = tempfile.mkdtemp() target = tempfile.mkdtemp() egg_file = os.path.join(new_location, 'foo-1.0.egg-info') -- cgit v1.2.1 From ac3e0877123c9cb1a4d53653e273dfb3f1d40ed3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 16:16:18 -0500 Subject: Extract fixture for foo_package. --- setuptools/tests/test_easy_install.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 4942acbf..791e3038 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -181,17 +181,19 @@ class TestUserInstallTest: logging.basicConfig(level=logging.INFO, stream=sys.stderr) log.info('this should not break') - def test_local_index(self): + @pytest.fixture() + def foo_package(self, tmpdir): + egg_file = tmpdir / 'foo-1.0.egg-info' + with egg_file.open('w') as f: + f.write('Name: foo\n') + return str(tmpdir) + + def test_local_index(self, foo_package): """ The local index must be used when easy_install locates installed packages. """ - new_location = tempfile.mkdtemp() target = tempfile.mkdtemp() - egg_file = os.path.join(new_location, 'foo-1.0.egg-info') - with open(egg_file, 'w') as f: - f.write('Name: foo\n') - sys.path.append(target) old_ppath = os.environ.get('PYTHONPATH') os.environ['PYTHONPATH'] = os.path.pathsep.join(sys.path) @@ -202,14 +204,14 @@ class TestUserInstallTest: cmd.install_dir = target cmd.args = ['foo'] cmd.ensure_finalized() - cmd.local_index.scan([new_location]) + cmd.local_index.scan([foo_package]) res = cmd.easy_install('foo') actual = os.path.normcase(os.path.realpath(res.location)) - expected = os.path.normcase(os.path.realpath(new_location)) + expected = os.path.normcase(os.path.realpath(foo_package)) assert actual == expected finally: sys.path.remove(target) - for basedir in [new_location, target, ]: + for basedir in [target, ]: if not os.path.exists(basedir) or not os.path.isdir(basedir): continue try: -- cgit v1.2.1 From a2719779b6604634f87aed64cf4413486ccca88c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 16:19:57 -0500 Subject: Extract install_target as fixture --- setuptools/tests/test_easy_install.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 791e3038..1acf08b5 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -188,20 +188,23 @@ class TestUserInstallTest: f.write('Name: foo\n') return str(tmpdir) - def test_local_index(self, foo_package): + @pytest.fixture() + def install_target(self, tmpdir): + return str(tmpdir) + + def test_local_index(self, foo_package, install_target): """ The local index must be used when easy_install locates installed packages. """ - target = tempfile.mkdtemp() - sys.path.append(target) + sys.path.append(install_target) old_ppath = os.environ.get('PYTHONPATH') os.environ['PYTHONPATH'] = os.path.pathsep.join(sys.path) try: dist = Distribution() dist.script_name = 'setup.py' cmd = ei.easy_install(dist) - cmd.install_dir = target + cmd.install_dir = install_target cmd.args = ['foo'] cmd.ensure_finalized() cmd.local_index.scan([foo_package]) @@ -210,14 +213,7 @@ class TestUserInstallTest: expected = os.path.normcase(os.path.realpath(foo_package)) assert actual == expected finally: - sys.path.remove(target) - for basedir in [target, ]: - if not os.path.exists(basedir) or not os.path.isdir(basedir): - continue - try: - shutil.rmtree(basedir) - except: - pass + sys.path.remove(install_target) if old_ppath is not None: os.environ['PYTHONPATH'] = old_ppath else: -- cgit v1.2.1 From c3b4d4bc997f71943b29bb8dccbdfcbc72bd7488 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 16:33:25 -0500 Subject: Extract sys.path and os.environ patching into install_target fixture --- setuptools/tests/test_easy_install.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 1acf08b5..6e2b25dd 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -188,18 +188,19 @@ class TestUserInstallTest: f.write('Name: foo\n') return str(tmpdir) - @pytest.fixture() + @pytest.yield_fixture() def install_target(self, tmpdir): - return str(tmpdir) + target = str(tmpdir) + with mock.patch('sys.path', sys.path + [target]): + python_path = os.path.pathsep.join(sys.path) + with mock.patch.dict(os.environ, PYTHONPATH=python_path): + yield target def test_local_index(self, foo_package, install_target): """ The local index must be used when easy_install locates installed packages. """ - sys.path.append(install_target) - old_ppath = os.environ.get('PYTHONPATH') - os.environ['PYTHONPATH'] = os.path.pathsep.join(sys.path) try: dist = Distribution() dist.script_name = 'setup.py' @@ -213,11 +214,7 @@ class TestUserInstallTest: expected = os.path.normcase(os.path.realpath(foo_package)) assert actual == expected finally: - sys.path.remove(install_target) - if old_ppath is not None: - os.environ['PYTHONPATH'] = old_ppath - else: - del os.environ['PYTHONPATH'] + pass @contextlib.contextmanager def user_install_setup_context(self, *args, **kwargs): -- cgit v1.2.1 From 427b3bf0f2ddc07cc01637605277ca555d5b26ce Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 16:34:34 -0500 Subject: Remove unnecessary block --- setuptools/tests/test_easy_install.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 6e2b25dd..7d61fb83 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -201,20 +201,17 @@ class TestUserInstallTest: The local index must be used when easy_install locates installed packages. """ - try: - dist = Distribution() - dist.script_name = 'setup.py' - cmd = ei.easy_install(dist) - cmd.install_dir = install_target - cmd.args = ['foo'] - cmd.ensure_finalized() - cmd.local_index.scan([foo_package]) - res = cmd.easy_install('foo') - actual = os.path.normcase(os.path.realpath(res.location)) - expected = os.path.normcase(os.path.realpath(foo_package)) - assert actual == expected - finally: - pass + dist = Distribution() + dist.script_name = 'setup.py' + cmd = ei.easy_install(dist) + cmd.install_dir = install_target + cmd.args = ['foo'] + cmd.ensure_finalized() + cmd.local_index.scan([foo_package]) + res = cmd.easy_install('foo') + actual = os.path.normcase(os.path.realpath(res.location)) + expected = os.path.normcase(os.path.realpath(foo_package)) + assert actual == expected @contextlib.contextmanager def user_install_setup_context(self, *args, **kwargs): -- cgit v1.2.1 From 47c3c95f074c8d10cf946511196a75d7e3a1738b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 16:59:43 -0500 Subject: Edit changelog --- CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 608dd77d..611b0124 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,7 +8,7 @@ CHANGES * Bootstrap script now accepts ``--to-dir`` to customize save directory or allow for re-use of existing repository of setuptools versions. See - Pull Request #112 for an alternate implementation. + Pull Request #112 for background. * Issue #285: ``easy_install`` no longer will default to installing packages to the "user site packages" directory if it is itself installed there. Instead, the user must pass ``--user`` in all cases to install -- cgit v1.2.1 From adbfaa73e54eef2a24673f49995c933eb0f88adf Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 17:30:09 -0500 Subject: Bumped to 14.0 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 9ece89d7..a1d95ac2 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "13.0.2" +DEFAULT_VERSION = "14.0" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 525a47ea..7720175d 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '13.0.2' +__version__ = '14.0' -- cgit v1.2.1 From 761473c7f30b8df3872416357224174ba8b654a8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 17:30:11 -0500 Subject: Added tag 14.0 for changeset a3a105f795f8 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index e21214e5..256a8171 100644 --- a/.hgtags +++ b/.hgtags @@ -199,3 +199,4 @@ bf8c5bcacd49bf0f9648013a40ebfc8f7c727f7b 12.0.3 df34cc18624279faffdbc729c0a11e6ab0f46572 13.0 ae1a5c5cf78f4f9f98c054f1c8cec6168d1d19b4 13.0.1 e22a1d613bddf311e125eecd9c1e1cad02ab5063 13.0.2 +a3a105f795f8362f26e84e9acbc237ee2d6bcca4 14.0 -- cgit v1.2.1 From 45bf0df21a53809a891ea5bb45e5407a2ebb5e02 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 17:30:46 -0500 Subject: Bumped to 14.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index a1d95ac2..3374c36f 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.0" +DEFAULT_VERSION = "14.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 7720175d..2ac79c23 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.0' +__version__ = '14.1' -- cgit v1.2.1 From ab794ef306bcbe88c1fde6439ed02f889487c239 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 22:59:39 -0500 Subject: Use filter(None) for brevity --- setuptools/command/easy_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 4e841520..81573fea 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -435,7 +435,7 @@ class easy_install(Command): self.pth_file = None PYTHONPATH = os.environ.get('PYTHONPATH', '').split(os.pathsep) - if instdir not in map(normalize_path, [_f for _f in PYTHONPATH if _f]): + if instdir not in map(normalize_path, filter(None, PYTHONPATH)): # only PYTHONPATH dirs need a site.py, so pretend it's there self.sitepy_installed = True elif self.multi_version and not os.path.exists(pth_file): -- cgit v1.2.1 From 275336b8fb9171ba8bf7a7114a2d6ae41993848b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:11:45 -0500 Subject: Remove comment that references a setup command, but even at the time it was committed, it's not duplicate code from anything in setuptools, and I'm unaware of what a setup command is. --- setuptools/command/easy_install.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 81573fea..c9e61d13 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -238,7 +238,6 @@ class easy_install(Command): self.config_vars['usersite'] = self.install_usersite # fix the install_dir if "--user" was used - # XXX: duplicate of the code in the setup command if self.user and site.ENABLE_USER_SITE: self.create_home_path() if self.install_userbase is None: -- cgit v1.2.1 From 126161426c858f6b3e73a330086d9bb0d2995a12 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:16:27 -0500 Subject: Calculate scheme name directly. --- setuptools/command/easy_install.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index c9e61d13..c35ae16c 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -244,10 +244,8 @@ class easy_install(Command): raise DistutilsPlatformError( "User base directory is not specified") self.install_base = self.install_platbase = self.install_userbase - if os.name == 'posix': - self.select_scheme("unix_user") - else: - self.select_scheme(os.name + "_user") + scheme_name = os.name.replace('posix', 'unix') + '_user' + self.select_scheme(scheme_name) self.expand_basedirs() self.expand_dirs() -- cgit v1.2.1 From 3a8d4728cbc3080a7a816f87dc20efafae6e28e5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:19:23 -0500 Subject: Extract method for fixing install dir --- setuptools/command/easy_install.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index c35ae16c..872f6bb8 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -237,15 +237,7 @@ class easy_install(Command): self.config_vars['userbase'] = self.install_userbase self.config_vars['usersite'] = self.install_usersite - # fix the install_dir if "--user" was used - if self.user and site.ENABLE_USER_SITE: - self.create_home_path() - if self.install_userbase is None: - raise DistutilsPlatformError( - "User base directory is not specified") - self.install_base = self.install_platbase = self.install_userbase - scheme_name = os.name.replace('posix', 'unix') + '_user' - self.select_scheme(scheme_name) + self._fix_install_dir_for_user_site() self.expand_basedirs() self.expand_dirs() @@ -340,6 +332,19 @@ class easy_install(Command): self.outputs = [] + def _fix_install_dir_for_user_site(self): + """ + Fix the install_dir if "--user" was used. + """ + if self.user and site.ENABLE_USER_SITE: + self.create_home_path() + if self.install_userbase is None: + raise DistutilsPlatformError( + "User base directory is not specified") + self.install_base = self.install_platbase = self.install_userbase + scheme_name = os.name.replace('posix', 'unix') + '_user' + self.select_scheme(scheme_name) + def _expand_attrs(self, attrs): for attr in attrs: val = getattr(self, attr) -- cgit v1.2.1 From 727f1668fc61f74867cc0cfdfabdd6d23699a6d9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:21:01 -0500 Subject: Use short circuit instead of nesting functionality. --- setuptools/command/easy_install.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 872f6bb8..efe5f68b 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -336,14 +336,16 @@ class easy_install(Command): """ Fix the install_dir if "--user" was used. """ - if self.user and site.ENABLE_USER_SITE: - self.create_home_path() - if self.install_userbase is None: - raise DistutilsPlatformError( - "User base directory is not specified") - self.install_base = self.install_platbase = self.install_userbase - scheme_name = os.name.replace('posix', 'unix') + '_user' - self.select_scheme(scheme_name) + if not self.user or not site.ENABLE_USER_SITE: + return + + self.create_home_path() + if self.install_userbase is None: + raise DistutilsPlatformError( + "User base directory is not specified") + self.install_base = self.install_platbase = self.install_userbase + scheme_name = os.name.replace('posix', 'unix') + '_user' + self.select_scheme(scheme_name) def _expand_attrs(self, attrs): for attr in attrs: -- cgit v1.2.1 From f922da30d3d4d6ef6ac99f65509cf243dcce1ea4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:22:40 -0500 Subject: Extract variable for error message. --- setuptools/command/easy_install.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index efe5f68b..9f480f05 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -341,8 +341,8 @@ class easy_install(Command): self.create_home_path() if self.install_userbase is None: - raise DistutilsPlatformError( - "User base directory is not specified") + msg = "User base directory is not specified" + raise DistutilsPlatformError(msg) self.install_base = self.install_platbase = self.install_userbase scheme_name = os.name.replace('posix', 'unix') + '_user' self.select_scheme(scheme_name) -- cgit v1.2.1 From 537c16561318df78f1a512101d0eca1b0593616e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:29:47 -0500 Subject: Filter blockers in the iterable --- setuptools/command/easy_install.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 9f480f05..531ac8ff 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -200,8 +200,11 @@ class easy_install(Command): ) def delete_blockers(self, blockers): - for filename in blockers: - if os.path.exists(filename) or os.path.islink(filename): + extant_blockers = ( + filename for filename in blockers + if os.path.exists(filename) or os.path.islink(filename) + ) + for filename in extant_blockers: log.info("Deleting %s", filename) if not self.dry_run: if (os.path.isdir(filename) and -- cgit v1.2.1 From f9fd181f25d50bd149c715c7ac52827da34d0e59 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:31:49 -0500 Subject: Extract method for filename deletion. --- setuptools/command/easy_install.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 531ac8ff..01c67ccc 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -204,7 +204,9 @@ class easy_install(Command): filename for filename in blockers if os.path.exists(filename) or os.path.islink(filename) ) - for filename in extant_blockers: + list(map(self._delete_filename, extant_blockers)) + + def _delete_filename(self, filename): log.info("Deleting %s", filename) if not self.dry_run: if (os.path.isdir(filename) and -- cgit v1.2.1 From 7ab342a1ed684563ee7742fc3f7fd04fac5b7fc2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:35:27 -0500 Subject: Remove excess indent --- setuptools/command/easy_install.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 01c67ccc..7dbbc878 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -207,13 +207,13 @@ class easy_install(Command): list(map(self._delete_filename, extant_blockers)) def _delete_filename(self, filename): - log.info("Deleting %s", filename) - if not self.dry_run: - if (os.path.isdir(filename) and - not os.path.islink(filename)): - rmtree(filename) - else: - os.unlink(filename) + log.info("Deleting %s", filename) + if not self.dry_run: + if (os.path.isdir(filename) and + not os.path.islink(filename)): + rmtree(filename) + else: + os.unlink(filename) def finalize_options(self): if self.version: -- cgit v1.2.1 From e4fe5c76f89d0249ff7035a38795fa5ae1e38f09 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:36:10 -0500 Subject: Short circuit on dry run --- setuptools/command/easy_install.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 7dbbc878..7f360e05 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -208,12 +208,14 @@ class easy_install(Command): def _delete_filename(self, filename): log.info("Deleting %s", filename) - if not self.dry_run: - if (os.path.isdir(filename) and - not os.path.islink(filename)): - rmtree(filename) - else: - os.unlink(filename) + if self.dry_run: + return + + if (os.path.isdir(filename) and + not os.path.islink(filename)): + rmtree(filename) + else: + os.unlink(filename) def finalize_options(self): if self.version: -- cgit v1.2.1 From 16060fd91b26126c6f1fce2c1dba4a79cf85177e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:36:45 -0500 Subject: Extract variable for is_tree --- setuptools/command/easy_install.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 7f360e05..bf380f13 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -211,8 +211,8 @@ class easy_install(Command): if self.dry_run: return - if (os.path.isdir(filename) and - not os.path.islink(filename)): + is_tree = os.path.isdir(filename) and not os.path.islink(filename) + if is_tree: rmtree(filename) else: os.unlink(filename) -- cgit v1.2.1 From 16a4240286b5202e2a52c22efb63fc3c1ba7ab02 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:39:36 -0500 Subject: More concisely describe the removal. --- setuptools/command/easy_install.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index bf380f13..0828be84 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -212,10 +212,8 @@ class easy_install(Command): return is_tree = os.path.isdir(filename) and not os.path.islink(filename) - if is_tree: - rmtree(filename) - else: - os.unlink(filename) + remover = rmtree if is_tree else os.unlink + remover(filename) def finalize_options(self): if self.version: -- cgit v1.2.1 From cbc3c959feecae75c1ce7864543c7f3a14b65ab0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 6 Mar 2015 23:40:47 -0500 Subject: Use 'path' to describe a file or directory. --- setuptools/command/easy_install.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 0828be84..276b6f99 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -204,16 +204,16 @@ class easy_install(Command): filename for filename in blockers if os.path.exists(filename) or os.path.islink(filename) ) - list(map(self._delete_filename, extant_blockers)) + list(map(self._delete_path, extant_blockers)) - def _delete_filename(self, filename): - log.info("Deleting %s", filename) + def _delete_path(self, path): + log.info("Deleting %s", path) if self.dry_run: return - is_tree = os.path.isdir(filename) and not os.path.islink(filename) + is_tree = os.path.isdir(path) and not os.path.islink(path) remover = rmtree if is_tree else os.unlink - remover(filename) + remover(path) def finalize_options(self): if self.version: -- cgit v1.2.1 From 0721693f695db566cb7f8253cdcd50d21559ac94 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 9 Mar 2015 08:38:48 +0100 Subject: fix makefile s/setuptools/pkg_resources/ --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ab60b882..37dd26eb 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,6 @@ empty: exit 1 update-vendored: - rm -rf setuptools/_vendor/packaging - pip install -r setuptools/_vendor/vendored.txt -t setuptools/_vendor/ - rm -rf setuptools/_vendor/*.{egg,dist}-info + rm -rf pkg_resources/_vendor/packaging + pip install -r pkg_resources/_vendor/vendored.txt -t pkg_resources/_vendor/ + rm -rf pkg_resources/_vendor/*.{egg,dist}-info -- cgit v1.2.1 From 170af2c8010aa7e7ff0d1c71d8ee6bcb2aea51cf Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Mar 2015 21:26:16 -0400 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 611b0124..6c2ff946 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +---- +14.1 +---- + +* Pull Request #125: Add ``__ne__`` to Requirement class. +* Various refactoring of easy_install. + ---- 14.0 ---- -- cgit v1.2.1 From 12a9c92696884ea7a3a63ac57abbe8fafdad501e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Mar 2015 21:31:11 -0400 Subject: Added tag 14.1 for changeset 9751a1671a12 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 256a8171..83bc4f5a 100644 --- a/.hgtags +++ b/.hgtags @@ -200,3 +200,4 @@ df34cc18624279faffdbc729c0a11e6ab0f46572 13.0 ae1a5c5cf78f4f9f98c054f1c8cec6168d1d19b4 13.0.1 e22a1d613bddf311e125eecd9c1e1cad02ab5063 13.0.2 a3a105f795f8362f26e84e9acbc237ee2d6bcca4 14.0 +9751a1671a124e30ae344d1510b9c1dbb14f2775 14.1 -- cgit v1.2.1 From 09c966b75de843ec24c6fbababdc19772b24268d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Mar 2015 21:31:50 -0400 Subject: Bumped to 14.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 3374c36f..913a4ceb 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.1" +DEFAULT_VERSION = "14.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 2ac79c23..a52fd832 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.1' +__version__ = '14.2' -- cgit v1.2.1 From 1919a4358eebcfd48e24756e0bb68035e8750800 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Mar 2015 22:09:26 -0400 Subject: Remove regression test for Distribute issue #318. The continuing relevance of this test is questionnaible, given that user installs of setuptools no longer imply user installs of other packages. Ref #360. --- setuptools/tests/test_easy_install.py | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 7d61fb83..c5714998 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -232,26 +232,6 @@ class TestUserInstallTest: self.user_install_setup_context, ) - def test_setup_requires(self): - """Regression test for Distribute issue #318 - - Ensure that a package with setup_requires can be installed when - setuptools is installed in the user site-packages without causing a - SandboxViolation. - """ - - test_pkg = create_setup_requires_package(os.getcwd()) - test_setup_py = os.path.join(test_pkg, 'setup.py') - - try: - with contexts.quiet(): - with self.patched_setup_context(): - run_setup(test_setup_py, ['install']) - except IndexError: - # Test fails in some cases due to bugs in Python - # See https://bitbucket.org/pypa/setuptools/issue/201 - pass - @pytest.yield_fixture def distutils_package(): -- cgit v1.2.1 From 24b1723a48ef5ba95afeabf96f8021b939d8391a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Mar 2015 22:40:27 -0400 Subject: Bypass the checking of site-packages when asserting not user install in site-packages. Fixes #360. --- setuptools/tests/test_easy_install.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index c5714998..e71bbfc9 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -154,13 +154,23 @@ def setup_context(tmpdir): @pytest.mark.usefixtures("setup_context") class TestUserInstallTest: + # prevent check that site-packages is writable. easy_install + # shouldn't be writing to system site-packages during finalize + # options, but while it does, bypass the behavior. + prev_sp_write = mock.patch( + 'setuptools.command.easy_install.easy_install.check_site_dir', + mock.Mock(), + ) + # simulate setuptools installed in user site packages @mock.patch('setuptools.command.easy_install.__file__', site.USER_SITE) @mock.patch('site.ENABLE_USER_SITE', True) + @prev_sp_write def test_user_install_not_implied_user_site_enabled(self): self.assert_not_user_site() @mock.patch('site.ENABLE_USER_SITE', False) + @prev_sp_write def test_user_install_not_implied_user_site_disabled(self): self.assert_not_user_site() -- cgit v1.2.1 From 6ef3f6262aac874f61483a3cc96da1e2a0b1a362 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Mar 2015 22:41:54 -0400 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 6c2ff946..3e72eaa1 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +------ +14.1.1 +------ + +* Issue #360: Removed undesirable behavior from test runs, preventing + write tests and installation to system site packages. + ---- 14.1 ---- -- cgit v1.2.1 From aba25cd363c6f7dc9469f00a1c56ef8f4ffc6f17 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Mar 2015 22:44:48 -0400 Subject: Bumped to 14.1.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 913a4ceb..c5a256a7 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.2" +DEFAULT_VERSION = "14.1.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index a52fd832..8800c207 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.2' +__version__ = '14.1.1' -- cgit v1.2.1 From a9cb52adc1ce9337e4c5c2602c48ab6daba680a9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Mar 2015 22:44:50 -0400 Subject: Added tag 14.1.1 for changeset 07fcc3226782 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 83bc4f5a..59901580 100644 --- a/.hgtags +++ b/.hgtags @@ -201,3 +201,4 @@ ae1a5c5cf78f4f9f98c054f1c8cec6168d1d19b4 13.0.1 e22a1d613bddf311e125eecd9c1e1cad02ab5063 13.0.2 a3a105f795f8362f26e84e9acbc237ee2d6bcca4 14.0 9751a1671a124e30ae344d1510b9c1dbb14f2775 14.1 +07fcc3226782b979cedaaf456c7f1c5b2fdafd2c 14.1.1 -- cgit v1.2.1 From 0e0db0408fbcbb0a0a6de45a70dca32f5d91170b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Mar 2015 22:45:30 -0400 Subject: Bumped to 14.1.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index c5a256a7..d4fd86c4 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.1.1" +DEFAULT_VERSION = "14.1.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 8800c207..134b5685 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.1.1' +__version__ = '14.1.2' -- cgit v1.2.1 From 4a4ca5aefb4d78046f16adbdcc2ce96f262522b2 Mon Sep 17 00:00:00 2001 From: MinRK Date: Thu, 5 Feb 2015 11:48:02 -0800 Subject: ensure py_version and platform are str in hashcmp avoids unorderable None, str when sorting dists on Python 3 --- pkg_resources/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 7701292b..a1dce2d8 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2448,8 +2448,8 @@ class Distribution(object): self.precedence, self.key, _remove_md5_fragment(self.location), - self.py_version, - self.platform, + self.py_version or '', + self.platform or '', ) def __hash__(self): -- cgit v1.2.1 From 4ffb1b7d89010474216e3baabef175c139aa4522 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 15 Mar 2015 08:15:36 -0400 Subject: Update changelog --- CHANGES.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 3e72eaa1..ca15f587 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +---- +14.2 +---- + +* Issue #137: Update ``Distribution.hashcmp`` so that Distributions with + None for pyversion or platform can be compared against Distributions + defining those attributes. + ------ 14.1.1 ------ -- cgit v1.2.1 From 6301007c244531948add7852db54045e9c3a11ce Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 15 Mar 2015 08:18:41 -0400 Subject: Bumped to 14.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index d4fd86c4..913a4ceb 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.1.2" +DEFAULT_VERSION = "14.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 134b5685..a52fd832 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.1.2' +__version__ = '14.2' -- cgit v1.2.1 From dd8c2936e235a91a62f5ee3a8045614184f0c108 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 15 Mar 2015 08:18:43 -0400 Subject: Added tag 14.2 for changeset d714fb731de7 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 59901580..8508404c 100644 --- a/.hgtags +++ b/.hgtags @@ -202,3 +202,4 @@ e22a1d613bddf311e125eecd9c1e1cad02ab5063 13.0.2 a3a105f795f8362f26e84e9acbc237ee2d6bcca4 14.0 9751a1671a124e30ae344d1510b9c1dbb14f2775 14.1 07fcc3226782b979cedaaf456c7f1c5b2fdafd2c 14.1.1 +d714fb731de779a1337d2d78cd413931f1f06193 14.2 -- cgit v1.2.1 From 6d69e5a0d777c6a564ec32f9b726da64f2a5ad9c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 15 Mar 2015 08:19:20 -0400 Subject: Bumped to 14.3 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 913a4ceb..54283750 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.2" +DEFAULT_VERSION = "14.3" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index a52fd832..89a024f0 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.2' +__version__ = '14.3' -- cgit v1.2.1 From e4a80d4fdf2871f538716034aa539014aea7abd9 Mon Sep 17 00:00:00 2001 From: Volker Braun Date: Thu, 5 Mar 2015 01:42:38 +0100 Subject: Default to 755 permissions since checks later on test for non-group-writability --- pkg_resources/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index a1dce2d8..0e32f452 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2958,7 +2958,7 @@ def ensure_directory(path): os.makedirs(dirname) -def _bypass_ensure_directory(path, mode=0o777): +def _bypass_ensure_directory(path, mode=0o755): """Sandbox-bypassing version of ensure_directory()""" if not WRITE_SUPPORT: raise IOError('"os.mkdir" not supported on this platform.') -- cgit v1.2.1 From 729daffe61a5e6c5705ddf2aba36f9e0caf42f37 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 15 Mar 2015 09:35:09 -0400 Subject: Remove unused parameter. --- pkg_resources/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 0e32f452..c3686f88 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2958,14 +2958,14 @@ def ensure_directory(path): os.makedirs(dirname) -def _bypass_ensure_directory(path, mode=0o755): +def _bypass_ensure_directory(path): """Sandbox-bypassing version of ensure_directory()""" if not WRITE_SUPPORT: raise IOError('"os.mkdir" not supported on this platform.') dirname, filename = split(path) if dirname and filename and not isdir(dirname): _bypass_ensure_directory(dirname) - mkdir(dirname, mode) + mkdir(dirname, 0o755) def split_sections(s): -- cgit v1.2.1 From 1a4c6632a304225cfd797d5a1d6881578cb81af1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 15 Mar 2015 09:42:23 -0400 Subject: Update changelog. Fixes #254. --- CHANGES.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index ca15f587..fa161fc6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +---- +14.3 +---- + +* Issue #254: When creating temporary egg cache on Unix, use mode 755 + for creating the directory to avoid the subsequent warning if + the directory is group writable. + ---- 14.2 ---- -- cgit v1.2.1 From 482a2457aa5b28d1223cfb4f9130585bf8c9e8fe Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 15 Mar 2015 09:47:06 -0400 Subject: Added tag 14.3 for changeset e3c635a7d463 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 8508404c..ff5c6433 100644 --- a/.hgtags +++ b/.hgtags @@ -203,3 +203,4 @@ a3a105f795f8362f26e84e9acbc237ee2d6bcca4 14.0 9751a1671a124e30ae344d1510b9c1dbb14f2775 14.1 07fcc3226782b979cedaaf456c7f1c5b2fdafd2c 14.1.1 d714fb731de779a1337d2d78cd413931f1f06193 14.2 +e3c635a7d463c7713c647d1aa560f83fd8e27ef0 14.3 -- cgit v1.2.1 From 1581c8404e12f32190d3bc29825b9910a46f2347 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 15 Mar 2015 09:47:40 -0400 Subject: Bumped to 14.4 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 54283750..c8549761 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.3" +DEFAULT_VERSION = "14.4" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 89a024f0..5b9a2bc6 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.3' +__version__ = '14.4' -- cgit v1.2.1 From 2283fc214217e5c3dca8cc65045271ab5d0ea522 Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Thu, 19 Mar 2015 09:48:18 -0700 Subject: DistributionNotFound: Show requirers It is very helpful to know who required the missing package. E.g.: pkg_resources.DistributionNotFound: The 'colorama>=0.3.1' distribution was not found and is required by smlib.log. Note that there was a comment: "unfortunately, zc.buildout uses a str(err) to get the name of the distribution here..", but I did a search in the `buildout` code and I think that is no longer true, so I think that we're free to make the exception message more helpful without risk of breaking buildout: # In clone from https://github.com/buildout/buildout $ ag DistributionNotFound src/zc/buildout/buildout.py 686: except (ImportError, pkg_resources.DistributionNotFound): $ pip install --download=. --no-install zc.buildout ... Saved ./zc.buildout-2.3.1.tar.gz ... $ tar xf zc.buildout-2.3.1.tar.gz $ ag DistributionNotFound zc.buildout-2.3.1 zc.buildout-2.3.1/src/zc/buildout/buildout.py 686: except (ImportError, pkg_resources.DistributionNotFound): --HG-- branch : DistributionNotFound_list_requirers --- pkg_resources/__init__.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index c3686f88..4e820c09 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -798,13 +798,16 @@ class WorkingSet(object): ws = WorkingSet([]) dist = best[req.key] = env.best_match(req, ws, installer) if dist is None: - #msg = ("The '%s' distribution was not found on this " - # "system, and is required by this application.") - #raise DistributionNotFound(msg % req) - - # unfortunately, zc.buildout uses a str(err) - # to get the name of the distribution here.. - raise DistributionNotFound(req) + requirers = required_by.get(req, None) + if requirers: + requirers_str = ', '.join(requirers) + else: + requirers_str = 'this application' + msg = ("The '%s' distribution was not found " + "and is required by %s." + % (req, requirers_str)) + warnings.warn(msg) + raise DistributionNotFound(msg) to_activate.append(dist) if dist not in req: # Oops, the "best" so far conflicts with a dependency -- cgit v1.2.1 From 3ff70513dceb10287c79ca9eb902e42b74f3e55f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 19 Mar 2015 14:10:49 -0400 Subject: Replace deprecated usage with preferred usage. Fixes #364. --- setuptools/command/egg_info.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index a9940677..50f3d5c0 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -168,7 +168,8 @@ class egg_info(Command): self.mkpath(self.egg_info) installer = self.distribution.fetch_build_egg for ep in iter_entry_points('egg_info.writers'): - writer = ep.load(installer=installer) + ep.require(installer=installer) + writer = ep.resolve() writer(self, ep.name, os.path.join(self.egg_info, ep.name)) # Get rid of native_libs.txt if it was put there by older bdist_egg -- cgit v1.2.1 From a54a764326d516950861d2d317150e7e172bd99f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 11:26:02 -0400 Subject: Add test capturing failure to parse package names with hyphens. Ref #307 --- pkg_resources/tests/test_resources.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index a55478a2..92f076a1 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -207,6 +207,16 @@ class TestDistro: with pytest.raises(pkg_resources.UnknownExtra): d.requires(["foo"]) + def test_pkg_name_with_hyphen(self): + "Package names with hyphens are supported" + name = 'setuptools-markdown-1.0.egg' + dist = Distribution.from_filename(name) + assert dist.project_name == "setuptools-markdown" + assert dist.key == "setuptools-markdown" + assert dist.version == "1.0" + assert dist.py_version is None + assert dist.platform is None + class TestWorkingSet: def test_find_conflicting(self): -- cgit v1.2.1 From a074b625e3c765ac62cb4240d5c8d1d35152f8f4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 12:34:02 -0400 Subject: Update EGG_NAME regular expression matcher to allow names to include dashes. Fixes failing test and fixes #307. --- pkg_resources/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index c3686f88..4cdb40dc 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2267,8 +2267,8 @@ OBRACKET = re.compile(r"\s*\[").match CBRACKET = re.compile(r"\s*\]").match MODULE = re.compile(r"\w+(\.\w+)*$").match EGG_NAME = re.compile( - r"(?P[^-]+)" - r"( -(?P[^-]+) (-py(?P[^-]+) (-(?P.+))? )? )?", + r"(?P.*?)" + r"( -(?P[^-]+) (-py(?P[^-]+) (-(?P.+))? )? )?$", re.VERBOSE | re.IGNORECASE ).match -- cgit v1.2.1 From e1c326e105c1bbd3585e5867973b8d54dc9d4929 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 12:41:00 -0400 Subject: Reindent EGG_NAME to reflect structure. --- pkg_resources/__init__.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 4cdb40dc..507bacc6 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2267,9 +2267,17 @@ OBRACKET = re.compile(r"\s*\[").match CBRACKET = re.compile(r"\s*\]").match MODULE = re.compile(r"\w+(\.\w+)*$").match EGG_NAME = re.compile( - r"(?P.*?)" - r"( -(?P[^-]+) (-py(?P[^-]+) (-(?P.+))? )? )?$", - re.VERBOSE | re.IGNORECASE + r""" + (?P.*?) ( + -(?P[^-]+) ( + -py(?P[^-]+) ( + -(?P.+) + )? + )? + )? + $ + """, + re.VERBOSE | re.IGNORECASE, ).match -- cgit v1.2.1 From a631a0700d2ebcc9ee98c91d474f351974cc0b92 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 13:30:51 -0400 Subject: Match Python 3 for bdist_dumb. --- setuptools/package_index.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 5ed19130..963b4b41 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -140,8 +140,9 @@ def interpret_distro_name( parts = basename.split('-') if not py_version: for i,p in enumerate(parts[2:]): - if len(p)==5 and p.startswith('py2.'): - return # It's a bdist_dumb, not an sdist -- bail out + if p.match('py\d\.\d'): + # It's a bdist_dumb, not an sdist -- bail out + return for p in range(1,len(parts)+1): yield Distribution( -- cgit v1.2.1 From 00477b5b3e1f42b5ad9cdc553652e04beb675dbb Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 13:31:38 -0400 Subject: Remove unused variable --- setuptools/package_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 963b4b41..c117cb62 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -139,7 +139,7 @@ def interpret_distro_name( parts = basename.split('-') if not py_version: - for i,p in enumerate(parts[2:]): + for p in parts[2:]: if p.match('py\d\.\d'): # It's a bdist_dumb, not an sdist -- bail out return -- cgit v1.2.1 From edf097e299d4382700f819288cb08390c53e109d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 13:34:15 -0400 Subject: Flat is better than nested. --- setuptools/package_index.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index c117cb62..51769cdf 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -138,11 +138,9 @@ def interpret_distro_name( # versions in distribution archive names (sdist and bdist). parts = basename.split('-') - if not py_version: - for p in parts[2:]: - if p.match('py\d\.\d'): - # It's a bdist_dumb, not an sdist -- bail out - return + if not py_version and any(p.match('py\d\.\d') for p in parts[2:]): + # it is a bdist_dumb, not an sdist -- bail out + return for p in range(1,len(parts)+1): yield Distribution( -- cgit v1.2.1 From c21f34b66f67d7948d2f99143636cd1dab7734a6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 15:29:44 -0400 Subject: Extract method for warning of legacy version --- pkg_resources/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 507bacc6..1bb67a71 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2500,6 +2500,11 @@ class Distribution(object): def parsed_version(self): if not hasattr(self, "_parsed_version"): self._parsed_version = parse_version(self.version) + self._warn_legacy_version() + + return self._parsed_version + + def _warn_legacy_version(self): if isinstance( self._parsed_version, packaging.version.LegacyVersion): # While an empty version is techincally a legacy version and @@ -2520,7 +2525,6 @@ class Distribution(object): PEP440Warning, ) - return self._parsed_version @property def version(self): -- cgit v1.2.1 From acd20ca332bb3f0ad48c7d92f832bfb2121decc1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 15:34:18 -0400 Subject: Reindent warning and use short circuits for flatter implementation. --- pkg_resources/__init__.py | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 1bb67a71..f7611472 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -36,6 +36,7 @@ import collections import plistlib import email.parser import tempfile +import textwrap from pkgutil import get_importer PY3 = sys.version_info > (3,) @@ -2505,26 +2506,29 @@ class Distribution(object): return self._parsed_version def _warn_legacy_version(self): - if isinstance( - self._parsed_version, packaging.version.LegacyVersion): - # While an empty version is techincally a legacy version and - # is not a valid PEP 440 version, it's also unlikely to - # actually come from someone and instead it is more likely that - # it comes from setuptools attempting to parse a filename and - # including it in the list. So for that we'll gate this warning - # on if the version is anything at all or not. - if self.version: - warnings.warn( - "'%s (%s)' is being parsed as a legacy, non PEP 440, " - "version. You may find odd behavior and sort order. " - "In particular it will be sorted as less than 0.0. It " - "is recommend to migrate to PEP 440 compatible " - "versions." % ( - self.project_name, self.version, - ), - PEP440Warning, - ) + LV = packaging.version.LegacyVersion + is_legacy = isinstance(self._parsed_version, LV) + if not is_legacy: + return + + # While an empty version is techincally a legacy version and + # is not a valid PEP 440 version, it's also unlikely to + # actually come from someone and instead it is more likely that + # it comes from setuptools attempting to parse a filename and + # including it in the list. So for that we'll gate this warning + # on if the version is anything at all or not. + if not self.version: + return + + tmpl = textwrap.dedent(""" + '%s (%s)' is being parsed as a legacy, non PEP 440, + version. You may find odd behavior and sort order. + In particular it will be sorted as less than 0.0. It + is recommend to migrate to PEP 440 compatible + versions. + """).strip().replace('\n', ' ') + warnings.warn(tmpl % (self.project_name, self.version), PEP440Warning) @property def version(self): -- cgit v1.2.1 From 80c6b750898c53a0f627c64a0b953ae0e5fdb9d7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 15:38:04 -0400 Subject: Prefer new string formatting. Re-use variable names. --- pkg_resources/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index f7611472..607d0eec 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2521,14 +2521,15 @@ class Distribution(object): return tmpl = textwrap.dedent(""" - '%s (%s)' is being parsed as a legacy, non PEP 440, + '{project_name} ({version})' is being parsed as a legacy, + non PEP 440, version. You may find odd behavior and sort order. In particular it will be sorted as less than 0.0. It is recommend to migrate to PEP 440 compatible versions. """).strip().replace('\n', ' ') - warnings.warn(tmpl % (self.project_name, self.version), PEP440Warning) + warnings.warn(tmpl.format(**vars(self)), PEP440Warning) @property def version(self): -- cgit v1.2.1 From 5e00a02ea1f7473c952d4d359891db4f53ac1778 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 15:48:38 -0400 Subject: Disable warning of LegacyVersion in parsed_version. This functionality should be called explicitly at whatever times are appropriate for the warning. Fixes #307. --- pkg_resources/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 607d0eec..6aac8296 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2501,7 +2501,6 @@ class Distribution(object): def parsed_version(self): if not hasattr(self, "_parsed_version"): self._parsed_version = parse_version(self.version) - self._warn_legacy_version() return self._parsed_version -- cgit v1.2.1 From 8ae39ab3a0bb12f17d2cabfdc27725b0992ba3c3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 15:53:44 -0400 Subject: Backed out changeset 6e045b2724d0 and 56d7ea3d42b2. Ref #307. --- pkg_resources/__init__.py | 4 ++-- pkg_resources/tests/test_resources.py | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 4cdb40dc..c3686f88 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2267,8 +2267,8 @@ OBRACKET = re.compile(r"\s*\[").match CBRACKET = re.compile(r"\s*\]").match MODULE = re.compile(r"\w+(\.\w+)*$").match EGG_NAME = re.compile( - r"(?P.*?)" - r"( -(?P[^-]+) (-py(?P[^-]+) (-(?P.+))? )? )?$", + r"(?P[^-]+)" + r"( -(?P[^-]+) (-py(?P[^-]+) (-(?P.+))? )? )?", re.VERBOSE | re.IGNORECASE ).match diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 92f076a1..a55478a2 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -207,16 +207,6 @@ class TestDistro: with pytest.raises(pkg_resources.UnknownExtra): d.requires(["foo"]) - def test_pkg_name_with_hyphen(self): - "Package names with hyphens are supported" - name = 'setuptools-markdown-1.0.egg' - dist = Distribution.from_filename(name) - assert dist.project_name == "setuptools-markdown" - assert dist.key == "setuptools-markdown" - assert dist.version == "1.0" - assert dist.py_version is None - assert dist.platform is None - class TestWorkingSet: def test_find_conflicting(self): -- cgit v1.2.1 From 01bb6e0e9217255cd835cefb8162463dac5d8e6d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 15:58:37 -0400 Subject: Correct regex usage --- setuptools/package_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 963b4b41..95eb1cf3 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -140,7 +140,7 @@ def interpret_distro_name( parts = basename.split('-') if not py_version: for i,p in enumerate(parts[2:]): - if p.match('py\d\.\d'): + if re.match('py\d\.\d$', p): # It's a bdist_dumb, not an sdist -- bail out return -- cgit v1.2.1 From 94a92f47c4b323c3897a83dae6b91f524f0e2c25 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 16:02:05 -0400 Subject: Update changelog --- CHANGES.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index fa161fc6..018407fa 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,15 @@ CHANGES ======= +------ +14.3.1 +------ + +* Issue #307: Removed PEP-440 warning during parsing of versions + in ``pkg_resources.Distribution``. +* Issue #364: Replace deprecated usage with recommended usage of + ``EntryPoint.load``. + ---- 14.3 ---- -- cgit v1.2.1 From fcb4bf6759c8fa674d749f2129f833195cd50431 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 16:08:27 -0400 Subject: Bumped to 14.3.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index c8549761..0dab29fc 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.4" +DEFAULT_VERSION = "14.3.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 5b9a2bc6..5fed68f1 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.4' +__version__ = '14.3.1' -- cgit v1.2.1 From 6feb154a786c35872a90269990999fe140bc71a3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 16:08:30 -0400 Subject: Added tag 14.3.1 for changeset 608948cef7e0 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index ff5c6433..07885aa3 100644 --- a/.hgtags +++ b/.hgtags @@ -204,3 +204,4 @@ a3a105f795f8362f26e84e9acbc237ee2d6bcca4 14.0 07fcc3226782b979cedaaf456c7f1c5b2fdafd2c 14.1.1 d714fb731de779a1337d2d78cd413931f1f06193 14.2 e3c635a7d463c7713c647d1aa560f83fd8e27ef0 14.3 +608948cef7e0ab8951691b149f5b6f0184a5635e 14.3.1 -- cgit v1.2.1 From f0b26583b2abdfba057dc199d31701497ad894c1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 20 Mar 2015 16:09:13 -0400 Subject: Bumped to 14.3.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 0dab29fc..683aeef4 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.3.1" +DEFAULT_VERSION = "14.3.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 5fed68f1..a2f34e92 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.3.1' +__version__ = '14.3.2' -- cgit v1.2.1 From e1f0b4019be6efa9c20f0f0dae13009f071ff2a0 Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Tue, 24 Mar 2015 08:20:42 -0700 Subject: DistributionNotFound: Move message template to class --HG-- branch : DistributionNotFound_list_requirers --- pkg_resources/__init__.py | 34 +++++++++++++++++++++++++--------- setuptools/command/easy_install.py | 4 +--- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 4e820c09..6f1ab9b7 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -368,6 +368,30 @@ class ContextualVersionConflict(VersionConflict): class DistributionNotFound(ResolutionError): """A requested distribution was not found""" + _template = ("The '{self.req}' distribution was not found " + "and is required by {self.requirers_str}") + + @property + def req(self): + return self.args[0] + + @property + def requirers(self): + return self.args[1] + + @property + def requirers_str(self): + if not self.requirers: + return 'the application' + return ', '.join(self.requirers) + + def report(self): + return self._template.format(**locals()) + + def __str__(self): + return self.report() + + class UnknownExtra(ResolutionError): """Distribution doesn't have an "extra feature" of the given name""" _provider_factories = {} @@ -799,15 +823,7 @@ class WorkingSet(object): dist = best[req.key] = env.best_match(req, ws, installer) if dist is None: requirers = required_by.get(req, None) - if requirers: - requirers_str = ', '.join(requirers) - else: - requirers_str = 'this application' - msg = ("The '%s' distribution was not found " - "and is required by %s." - % (req, requirers_str)) - warnings.warn(msg) - raise DistributionNotFound(msg) + raise DistributionNotFound(req, requirers) to_activate.append(dist) if dist not in req: # Oops, the "best" so far conflicts with a dependency diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 276b6f99..f2bfa68d 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -709,9 +709,7 @@ class easy_install(Command): [requirement], self.local_index, self.easy_install ) except DistributionNotFound as e: - raise DistutilsError( - "Could not find required distribution %s" % e.args - ) + raise DistutilsError(str(e)) except VersionConflict as e: raise DistutilsError(e.report()) if self.always_copy or self.always_copy_from: -- cgit v1.2.1 From 34e0ed958b2a56ceb394e15f189ea9f932af0785 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Mar 2015 11:05:47 -0400 Subject: Update changelog --- CHANGES.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 018407fa..61fd91df 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,20 @@ CHANGES ======= +---- +15.0 +---- + +* Pull Request #126: DistributionNotFound message now lists the package or + packages that required it. E.g.:: + + pkg_resources.DistributionNotFound: The 'colorama>=0.3.1' distribution was not found and is required by smlib.log. + + Note that zc.buildout once dependended on the string rendering of this + message to determine the package that was not found. This expectation + has since been changed, but older versions of buildout may experience + problems. + ------ 14.3.1 ------ -- cgit v1.2.1 From 9a33ea35df1a77e721ebeb1700acaa74ca28a430 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Mar 2015 11:07:10 -0400 Subject: Bumped to 15.0 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 683aeef4..a3e69dc1 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "14.3.2" +DEFAULT_VERSION = "15.0" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index a2f34e92..60d8514e 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '14.3.2' +__version__ = '15.0' -- cgit v1.2.1 From 8cff8857708d580441192c02af9dab910ba11ebb Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Mar 2015 11:07:31 -0400 Subject: Added tag 15.0b1 for changeset 617699fd3e44 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 07885aa3..778682e1 100644 --- a/.hgtags +++ b/.hgtags @@ -205,3 +205,4 @@ a3a105f795f8362f26e84e9acbc237ee2d6bcca4 14.0 d714fb731de779a1337d2d78cd413931f1f06193 14.2 e3c635a7d463c7713c647d1aa560f83fd8e27ef0 14.3 608948cef7e0ab8951691b149f5b6f0184a5635e 14.3.1 +617699fd3e44e54b6f95b80bfcf78164df37f266 15.0b1 -- cgit v1.2.1 From 933e26cd75231ba6402c38e4044e001a5d47fa3f Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Mon, 30 Mar 2015 03:40:43 +0200 Subject: Fix some typos. --- pkg_resources/__init__.py | 4 ++-- pkg_resources/_vendor/packaging/specifiers.py | 2 +- setuptools/command/easy_install.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index a8a16942..f033c10e 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2528,7 +2528,7 @@ class Distribution(object): if not is_legacy: return - # While an empty version is techincally a legacy version and + # While an empty version is technically a legacy version and # is not a valid PEP 440 version, it's also unlikely to # actually come from someone and instead it is more likely that # it comes from setuptools attempting to parse a filename and @@ -2542,7 +2542,7 @@ class Distribution(object): non PEP 440, version. You may find odd behavior and sort order. In particular it will be sorted as less than 0.0. It - is recommend to migrate to PEP 440 compatible + is recommended to migrate to PEP 440 compatible versions. """).strip().replace('\n', ' ') diff --git a/pkg_resources/_vendor/packaging/specifiers.py b/pkg_resources/_vendor/packaging/specifiers.py index 9ad0a635..77516cf4 100644 --- a/pkg_resources/_vendor/packaging/specifiers.py +++ b/pkg_resources/_vendor/packaging/specifiers.py @@ -502,7 +502,7 @@ class Specifier(_IndividualSpecifier): return False # Ensure that we do not allow a local version of the version mentioned - # in the specifier, which is techincally greater than, to match. + # in the specifier, which is technically greater than, to match. if prospective.local is not None: if Version(prospective.base_version) == Version(spec.base_version): return False diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index f2bfa68d..74803b59 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -152,7 +152,7 @@ class easy_install(Command): create_index = PackageIndex def initialize_options(self): - # the --user option seemst to be an opt-in one, + # the --user option seems to be an opt-in one, # so the default should be False. self.user = 0 self.zip_ok = self.local_snapshots_ok = None -- cgit v1.2.1 From 8fe7605a2787648a23c28741e20ba403e95a357b Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Mon, 30 Mar 2015 04:26:56 +0200 Subject: Fix setuptools.sandbox._execfile() with Python 3.1. It fixes failure of setuptools.tests.test_sandbox.TestSandbox.test_setup_py_with_CRLF() with Python 3.1. --- setuptools/sandbox.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 67255123..31e3eb2d 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -34,12 +34,12 @@ def _execfile(filename, globals, locals=None): Python 3 implementation of execfile. """ mode = 'rb' - # Python 2.6 compile requires LF for newlines, so use deprecated - # Universal newlines support. - if sys.version_info < (2, 7): - mode += 'U' with open(filename, mode) as stream: script = stream.read() + # compile() function in Python 2.6 and 3.1 requires LF line endings. + if sys.version_info[:2] < (2, 7) or sys.version_info[:2] >= (3, 0) and sys.version_info[:2] < (3, 2): + script = script.replace(b'\r\n', b'\n') + script = script.replace(b'\r', b'\n') if locals is None: locals = globals code = compile(script, filename, 'exec') -- cgit v1.2.1 From dface890cfe4a198b9271a5800e9d494f79e85b9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 3 Apr 2015 18:25:40 -0400 Subject: Update changelog. --- CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 61fd91df..9670846f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,7 +14,7 @@ CHANGES Note that zc.buildout once dependended on the string rendering of this message to determine the package that was not found. This expectation has since been changed, but older versions of buildout may experience - problems. + problems. See Buildout #242 for details. ------ 14.3.1 -- cgit v1.2.1 From 9e41a767df241615b024236f579bb62673f9f4a7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 3 Apr 2015 18:26:05 -0400 Subject: Added tag 15.0 for changeset d2c4d8486715 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 778682e1..acdb85de 100644 --- a/.hgtags +++ b/.hgtags @@ -206,3 +206,4 @@ d714fb731de779a1337d2d78cd413931f1f06193 14.2 e3c635a7d463c7713c647d1aa560f83fd8e27ef0 14.3 608948cef7e0ab8951691b149f5b6f0184a5635e 14.3.1 617699fd3e44e54b6f95b80bfcf78164df37f266 15.0b1 +d2c4d84867154243993876d6248aafec1fd12679 15.0 -- cgit v1.2.1 From 56e49ec7d8b1c9fd7f2c36d041a87bb756baa2a3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 3 Apr 2015 18:26:41 -0400 Subject: Bumped to 15.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index a3e69dc1..36ea3c24 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "15.0" +DEFAULT_VERSION = "15.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 60d8514e..1b29a7b4 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '15.0' +__version__ = '15.1' -- cgit v1.2.1 -- cgit v1.2.1 From 82d003629ef23fd7f0dc2fb71d5edc937271ffd8 Mon Sep 17 00:00:00 2001 From: Thomas Bechtold Date: Sun, 5 Apr 2015 08:39:18 +0200 Subject: Fix TypeError for pytest.skip() pytests skip() method doesn't have a 'reason' parameter. This fixes: TypeError: skip() got an unexpected keyword argument 'reason' --HG-- branch : fix-type-error-skip-reason --- setuptools/tests/test_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/test_integration.py b/setuptools/tests/test_integration.py index 90bb4313..07f06db2 100644 --- a/setuptools/tests/test_integration.py +++ b/setuptools/tests/test_integration.py @@ -28,7 +28,7 @@ def setup_module(module): try: urlopen('https://pypi.python.org/pypi') except Exception as exc: - pytest.skip(reason=str(exc)) + pytest.skip(str(exc)) @pytest.fixture -- cgit v1.2.1 From d8fda18abfeff18dd1b1588fbca707d1b2b14214 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 15 Apr 2015 08:58:22 -0400 Subject: Bump packaging version to 15.1 --- CHANGES.txt | 6 ++++ docs/conf.py | 4 +++ pkg_resources/_vendor/packaging/__about__.py | 2 +- pkg_resources/_vendor/packaging/specifiers.py | 48 +++++++++++---------------- pkg_resources/_vendor/vendored.txt | 2 +- 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 9670846f..012d8593 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,12 @@ CHANGES ======= +---- +15.1 +---- + +* Updated Packaging to 15.1 to address Packaging #28. + ---- 15.0 ---- diff --git a/docs/conf.py b/docs/conf.py index 24830987..ba3a35bc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -242,6 +242,10 @@ link_files = { pattern=r"Pip #(?P\d+)", url='{GH}/pypa/pip/issues/{pip}', ), + dict( + pattern=r"Packaging #(?P\d+)", + url='{GH}/pypa/packaging/issues/{packaging}', + ), ], ), } diff --git a/pkg_resources/_vendor/packaging/__about__.py b/pkg_resources/_vendor/packaging/__about__.py index 36f1a35c..d5243995 100644 --- a/pkg_resources/_vendor/packaging/__about__.py +++ b/pkg_resources/_vendor/packaging/__about__.py @@ -22,7 +22,7 @@ __title__ = "packaging" __summary__ = "Core utilities for Python packages" __uri__ = "https://github.com/pypa/packaging" -__version__ = "15.0" +__version__ = "15.1" __author__ = "Donald Stufft" __email__ = "donald@stufft.io" diff --git a/pkg_resources/_vendor/packaging/specifiers.py b/pkg_resources/_vendor/packaging/specifiers.py index 77516cf4..d5d8a956 100644 --- a/pkg_resources/_vendor/packaging/specifiers.py +++ b/pkg_resources/_vendor/packaging/specifiers.py @@ -502,7 +502,7 @@ class Specifier(_IndividualSpecifier): return False # Ensure that we do not allow a local version of the version mentioned - # in the specifier, which is technically greater than, to match. + # in the specifier, which is techincally greater than, to match. if prospective.local is not None: if Version(prospective.base_version) == Version(spec.base_version): return False @@ -673,10 +673,14 @@ class SpecifierSet(BaseSpecifier): if self._prereleases is not None: return self._prereleases + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + # Otherwise we'll see if any of the given specifiers accept # prereleases, if any of them do we'll return True, otherwise False. - # Note: The use of any() here means that an empty set of specifiers - # will always return False, this is an explicit design decision. return any(s.prereleases for s in self._specs) @prereleases.setter @@ -688,27 +692,21 @@ class SpecifierSet(BaseSpecifier): if not isinstance(item, (LegacyVersion, Version)): item = parse(item) + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + # We can determine if we're going to allow pre-releases by looking to # see if any of the underlying items supports them. If none of them do # and this item is a pre-release then we do not allow it and we can # short circuit that here. # Note: This means that 1.0.dev1 would not be contained in something # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 - if (not (self.prereleases or prereleases)) and item.is_prerelease: + if not prereleases and item.is_prerelease: return False - # Determine if we're forcing a prerelease or not, we bypass - # self.prereleases here and use self._prereleases because we want to - # only take into consideration actual *forced* values. The underlying - # specifiers will handle the other logic. - # The logic here is: If prereleases is anything but None, we'll just - # go aheand and continue to use that. However if - # prereleases is None, then we'll use whatever the - # value of self._prereleases is as long as it is not - # None itself. - if prereleases is None and self._prereleases is not None: - prereleases = self._prereleases - # We simply dispatch to the underlying specs here to make sure that the # given version is contained within all of them. # Note: This use of all() here means that an empty set of specifiers @@ -719,24 +717,18 @@ class SpecifierSet(BaseSpecifier): ) def filter(self, iterable, prereleases=None): - # Determine if we're forcing a prerelease or not, we bypass - # self.prereleases here and use self._prereleases because we want to - # only take into consideration actual *forced* values. The underlying - # specifiers will handle the other logic. - # The logic here is: If prereleases is anything but None, we'll just - # go aheand and continue to use that. However if - # prereleases is None, then we'll use whatever the - # value of self._prereleases is as long as it is not - # None itself. - if prereleases is None and self._prereleases is not None: - prereleases = self._prereleases + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases # If we have any specifiers, then we want to wrap our iterable in the # filter method for each one, this will act as a logical AND amongst # each specifier. if self._specs: for spec in self._specs: - iterable = spec.filter(iterable, prereleases=prereleases) + iterable = spec.filter(iterable, prereleases=bool(prereleases)) return iterable # If we do not have any specifiers, then we need to have a rough filter # which will filter out any pre-releases, unless there are no final diff --git a/pkg_resources/_vendor/vendored.txt b/pkg_resources/_vendor/vendored.txt index 75a31670..28da4226 100644 --- a/pkg_resources/_vendor/vendored.txt +++ b/pkg_resources/_vendor/vendored.txt @@ -1 +1 @@ -packaging==15.0 +packaging==15.1 -- cgit v1.2.1 From 66ec87700c358bcce3805f6be6da3e7d71519e03 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 15 Apr 2015 09:01:42 -0400 Subject: Update changelog --- CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.txt b/CHANGES.txt index 012d8593..50064f68 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -7,6 +7,7 @@ CHANGES ---- * Updated Packaging to 15.1 to address Packaging #28. +* Fix ``setuptools.sandbox._execfile()`` with Python 3.1. ---- 15.0 -- cgit v1.2.1 From 3da4cd143348c46a7fc5469bf3d4b4008201e5c5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 15 Apr 2015 09:16:21 -0400 Subject: Added tag 15.1 for changeset 10fde952613b --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index acdb85de..75e65cd6 100644 --- a/.hgtags +++ b/.hgtags @@ -207,3 +207,4 @@ e3c635a7d463c7713c647d1aa560f83fd8e27ef0 14.3 608948cef7e0ab8951691b149f5b6f0184a5635e 14.3.1 617699fd3e44e54b6f95b80bfcf78164df37f266 15.0b1 d2c4d84867154243993876d6248aafec1fd12679 15.0 +10fde952613b7a3f650fb1f6b6ed58cbd232fa3c 15.1 -- cgit v1.2.1 From c2cc7435a96775ef4cd018930fdd83b8ba1dd45d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 15 Apr 2015 09:17:24 -0400 Subject: Bumped to 15.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 36ea3c24..6804679b 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "15.1" +DEFAULT_VERSION = "15.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 1b29a7b4..2771d939 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '15.1' +__version__ = '15.2' -- cgit v1.2.1 From 2039b2aeba48685275bd2b341bf69d3f3f63786b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Tue, 21 Apr 2015 22:24:09 +0300 Subject: Check for Jython using sys.platform, not os.name --- setuptools/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 31e3eb2d..213cebff 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -10,7 +10,7 @@ import pickle import pkg_resources -if os.name == "java": +if sys.platform.startswith('java'): import org.python.modules.posix.PosixModule as _os else: _os = sys.modules[os.name] -- cgit v1.2.1 From 0e2d03c65eee67b2357069bd0de3eda453d8a319 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Apr 2015 10:14:37 -0400 Subject: Extract function for initializing the master working set. Fixes #373. --- pkg_resources/__init__.py | 48 ++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index f033c10e..0721baa8 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -3053,20 +3053,34 @@ def _initialize(g): g[name] = getattr(_manager, name) _initialize(globals()) -# Prepare the master working set and make the ``require()`` API available -working_set = WorkingSet._build_master() -_declare_state('object', working_set=working_set) - -require = working_set.require -iter_entry_points = working_set.iter_entry_points -add_activation_listener = working_set.subscribe -run_script = working_set.run_script -# backward compatibility -run_main = run_script -# Activate all distributions already on sys.path, and ensure that -# all distributions added to the working set in the future (e.g. by -# calling ``require()``) will get activated as well. -add_activation_listener(lambda dist: dist.activate()) -working_set.entries=[] -# match order -list(map(working_set.add_entry, sys.path)) + +def _initialize_master_working_set(): + """ + Prepare the master working set and make the ``require()`` + API available. + + This function has explicit effects on the global state + of pkg_resources. It is intended to be invoked once at + the initialization of this module. + + Invocation by other packages is unsupported and done + at their own risk. + """ + working_set = WorkingSet._build_master() + _declare_state('object', working_set=working_set) + + require = working_set.require + iter_entry_points = working_set.iter_entry_points + add_activation_listener = working_set.subscribe + run_script = working_set.run_script + # backward compatibility + run_main = run_script + # Activate all distributions already on sys.path, and ensure that + # all distributions added to the working set in the future (e.g. by + # calling ``require()``) will get activated as well. + add_activation_listener(lambda dist: dist.activate()) + working_set.entries=[] + # match order + list(map(working_set.add_entry, sys.path)) + globals().update(locals()) +_initialize_master_working_set() -- cgit v1.2.1 From a78cfe13a10e176f867d8a7b20f70ccfbbaa0d8d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Apr 2015 10:44:13 -0400 Subject: Declare variables for nicer linting. --- pkg_resources/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 0721baa8..17dcbe99 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -89,6 +89,12 @@ except ImportError: import packaging.specifiers +# declare some globals that will be defined later to +# satisfy the linters. +require = None +working_set = None + + class PEP440Warning(RuntimeWarning): """ Used when there is an issue with a version or specifier not complying with -- cgit v1.2.1 From bb239c08fbfcb689ef743786c70f655d8a3f9035 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Apr 2015 10:46:47 -0400 Subject: Use _call_aside to signal early that the function is called immediately. --- pkg_resources/__init__.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 17dcbe99..f2b13d99 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -3051,15 +3051,23 @@ def _mkstemp(*args,**kw): warnings.filterwarnings("ignore", category=PEP440Warning, append=True) -# Set up global resource manager (deliberately not state-saved) -_manager = ResourceManager() +# from jaraco.functools 1.3 +def _call_aside(f, *args, **kwargs): + f(*args, **kwargs) + return f + + +@functools.partial(_call_aside, globals()) def _initialize(g): - for name in dir(_manager): + "Set up global resource manager (deliberately not state-saved)" + manager = ResourceManager() + g['_manager'] = manager + for name in dir(manager): if not name.startswith('_'): - g[name] = getattr(_manager, name) -_initialize(globals()) + g[name] = getattr(manager, name) +@_call_aside def _initialize_master_working_set(): """ Prepare the master working set and make the ``require()`` @@ -3089,4 +3097,3 @@ def _initialize_master_working_set(): # match order list(map(working_set.add_entry, sys.path)) globals().update(locals()) -_initialize_master_working_set() -- cgit v1.2.1 From ba2699fae236a351cc4d3acf7a7a7d50bb614722 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Apr 2015 10:50:53 -0400 Subject: Update changelog --- CHANGES.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 50064f68..d10e2188 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +---- +15.2 +---- + +* Issue #373: Provisionally expose + ``pkg_resources._initialize_master_working_set``, allowing for + imperative re-initialization of the master working set. + ---- 15.1 ---- -- cgit v1.2.1 From f0f8bf5b6deedb85e7b4b120e30c6d90891c9baf Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Apr 2015 10:58:40 -0400 Subject: Partial appears to behave differently on Python 2.6. Also, this syntax is more congruent and easier to read. --- pkg_resources/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index f2b13d99..412e64c4 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -3057,8 +3057,8 @@ def _call_aside(f, *args, **kwargs): return f -@functools.partial(_call_aside, globals()) -def _initialize(g): +@_call_aside +def _initialize(g=globals()): "Set up global resource manager (deliberately not state-saved)" manager = ResourceManager() g['_manager'] = manager -- cgit v1.2.1 From 11117b86c94d37c4cdc8607fa8aa125b51b9e9de Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Apr 2015 11:02:09 -0400 Subject: Added tag 15.2 for changeset df5dc9c7aa75 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 75e65cd6..88e9fa67 100644 --- a/.hgtags +++ b/.hgtags @@ -208,3 +208,4 @@ e3c635a7d463c7713c647d1aa560f83fd8e27ef0 14.3 617699fd3e44e54b6f95b80bfcf78164df37f266 15.0b1 d2c4d84867154243993876d6248aafec1fd12679 15.0 10fde952613b7a3f650fb1f6b6ed58cbd232fa3c 15.1 +df5dc9c7aa7521f552824dee1ed1315cfe180844 15.2 -- cgit v1.2.1 From 42c62a7a344e2139f285c571930d179866167bd5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Apr 2015 11:02:44 -0400 Subject: Bumped to 15.3 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 6804679b..89970943 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "15.2" +DEFAULT_VERSION = "15.3" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 2771d939..f0d1b4d4 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '15.2' +__version__ = '15.3' -- cgit v1.2.1 From 498414b82737a860bb94d787dd426a430ef9de1e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Apr 2015 15:11:58 -0400 Subject: Remove use of deprecated imp module, avoiding deprecation warnings. --- pkg_resources/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 412e64c4..51c2bb00 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -21,7 +21,8 @@ import os import io import time import re -import imp +import _imp +import types import zipfile import zipimport import warnings @@ -2163,7 +2164,7 @@ def _handle_ns(packageName, path_item): return None module = sys.modules.get(packageName) if module is None: - module = sys.modules[packageName] = imp.new_module(packageName) + module = sys.modules[packageName] = types.ModuleType(packageName) module.__path__ = [] _set_parent_ns(packageName) elif not hasattr(module,'__path__'): @@ -2182,7 +2183,7 @@ def _handle_ns(packageName, path_item): def declare_namespace(packageName): """Declare that package 'packageName' is a namespace package""" - imp.acquire_lock() + _imp.acquire_lock() try: if packageName in _namespace_packages: return @@ -2209,18 +2210,18 @@ def declare_namespace(packageName): _handle_ns(packageName, path_item) finally: - imp.release_lock() + _imp.release_lock() def fixup_namespace_packages(path_item, parent=None): """Ensure that previously-declared namespace packages include path_item""" - imp.acquire_lock() + _imp.acquire_lock() try: for package in _namespace_packages.get(parent,()): subpath = _handle_ns(package, path_item) if subpath: fixup_namespace_packages(subpath, package) finally: - imp.release_lock() + _imp.release_lock() def file_ns_handler(importer, path_item, packageName, module): """Compute an ns-package subpath for a filesystem or zipfile importer""" -- cgit v1.2.1 From cbb12f9391afee2012a22bb5a95027b09a5713bf Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Apr 2015 20:07:23 -0400 Subject: Restore compatibility for Python 3.2 and earlier. --- pkg_resources/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 51c2bb00..79384174 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -21,7 +21,6 @@ import os import io import time import re -import _imp import types import zipfile import zipimport @@ -40,6 +39,12 @@ import tempfile import textwrap from pkgutil import get_importer +try: + import _imp +except ImportError: + # Python 3.2 compatibility + import imp as _imp + PY3 = sys.version_info > (3,) PY2 = not PY3 -- cgit v1.2.1 From 33544f0bf806d73495b00b9f8a0e45c25742fbc1 Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Fri, 1 May 2015 08:23:57 -0700 Subject: Nicer error when problem in install_requires Instead of: $ python setup.py egg_info error in adminweb setup command: 'install_requires' must be a string or list of strings containing valid project/version requirement specifiers We now have the more helpful: $ python setup.py egg_info error in adminweb setup command: 'install_requires' must be a string or list of strings containing valid project/version requirement specifiers. Error: Expected version spec in smsdk.authsvc>=0.0.8,2.0 at 2.0 It took me longer than it should to find the problem with the old error message. The new error message would've helped greatly. --- setuptools/dist.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index ffbc7c48..220bcf8c 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -122,11 +122,15 @@ def check_requirements(dist, attr, value): """Verify that install_requires is a valid requirements list""" try: list(pkg_resources.parse_requirements(value)) - except (TypeError,ValueError): + except (TypeError, ValueError) as e: raise DistutilsSetupError( "%r must be a string or list of strings " - "containing valid project/version requirement specifiers" % (attr,) + "containing valid project/version requirement specifiers.\n" + "Error: %s" + % (attr, ' '.join(e.args)) ) + + def check_entry_points(dist, attr, value): """Verify that entry_points map is parseable""" try: -- cgit v1.2.1 From fb27525a41a3f941aac906564d144d7177d35a79 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 May 2015 11:59:38 -0400 Subject: Let the exception render itself. --- setuptools/dist.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index 220bcf8c..892044dd 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -126,8 +126,8 @@ def check_requirements(dist, attr, value): raise DistutilsSetupError( "%r must be a string or list of strings " "containing valid project/version requirement specifiers.\n" - "Error: %s" - % (attr, ' '.join(e.args)) + "%s" + % (attr, e) ) -- cgit v1.2.1 From cd79379c95051b94a7facf56ac09c99f7cd31da0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 May 2015 12:27:10 -0400 Subject: Replace ValueErrors containing implicit contract about the structure of the message with a RequirementParseError explicitly joining arguments for the string representation. --- pkg_resources/__init__.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 79384174..4ed71329 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -21,7 +21,7 @@ import os import io import time import re -import types +import imp import zipfile import zipimport import warnings @@ -39,12 +39,6 @@ import tempfile import textwrap from pkgutil import get_importer -try: - import _imp -except ImportError: - # Python 3.2 compatibility - import imp as _imp - PY3 = sys.version_info > (3,) PY2 = not PY3 @@ -2169,7 +2163,7 @@ def _handle_ns(packageName, path_item): return None module = sys.modules.get(packageName) if module is None: - module = sys.modules[packageName] = types.ModuleType(packageName) + module = sys.modules[packageName] = imp.new_module(packageName) module.__path__ = [] _set_parent_ns(packageName) elif not hasattr(module,'__path__'): @@ -2188,7 +2182,7 @@ def _handle_ns(packageName, path_item): def declare_namespace(packageName): """Declare that package 'packageName' is a namespace package""" - _imp.acquire_lock() + imp.acquire_lock() try: if packageName in _namespace_packages: return @@ -2215,18 +2209,18 @@ def declare_namespace(packageName): _handle_ns(packageName, path_item) finally: - _imp.release_lock() + imp.release_lock() def fixup_namespace_packages(path_item, parent=None): """Ensure that previously-declared namespace packages include path_item""" - _imp.acquire_lock() + imp.acquire_lock() try: for package in _namespace_packages.get(parent,()): subpath = _handle_ns(package, path_item) if subpath: fixup_namespace_packages(subpath, package) finally: - _imp.release_lock() + imp.release_lock() def file_ns_handler(importer, path_item, packageName, module): """Compute an ns-package subpath for a filesystem or zipfile importer""" @@ -2859,6 +2853,11 @@ def issue_warning(*args,**kw): warnings.warn(stacklevel=level + 1, *args, **kw) +class RequirementParseError(ValueError): + def __str__(self): + return ' '.join(self.args) + + def parse_requirements(strs): """Yield ``Requirement`` objects for each specification in `strs` @@ -2877,14 +2876,14 @@ def parse_requirements(strs): line = next(lines) p = 0 except StopIteration: - raise ValueError( + raise RequirementParseError( "\\ must not appear on the last nonblank line" ) match = ITEM(line, p) if not match: msg = "Expected " + item_name + " in" - raise ValueError(msg, line, "at", line[p:]) + raise RequirementParseError(msg, line, "at", line[p:]) items.append(match.group(*groups)) p = match.end() @@ -2895,7 +2894,7 @@ def parse_requirements(strs): p = match.end() elif not TERMINATOR(line, p): msg = "Expected ',' or end-of-list in" - raise ValueError(msg, line, "at", line[p:]) + raise RequirementParseError(msg, line, "at", line[p:]) match = TERMINATOR(line, p) # skip the terminator, if any @@ -2906,7 +2905,7 @@ def parse_requirements(strs): for line in lines: match = DISTRO(line) if not match: - raise ValueError("Missing distribution spec", line) + raise RequirementParseError("Missing distribution spec", line) project_name = match.group(1) p = match.end() extras = [] -- cgit v1.2.1 From 95a68afdf62f63e044f600ab87a4410db6bdf128 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 May 2015 12:34:02 -0400 Subject: Render the error message as a single line without a period (for consistency with other usage). --- setuptools/dist.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index 892044dd..05669366 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -123,13 +123,11 @@ def check_requirements(dist, attr, value): try: list(pkg_resources.parse_requirements(value)) except (TypeError, ValueError) as e: - raise DistutilsSetupError( + tmpl = ( "%r must be a string or list of strings " - "containing valid project/version requirement specifiers.\n" - "%s" - % (attr, e) + "containing valid project/version requirement specifiers; %s" ) - + raise DistutilsSetupError(tmpl % (attr, e)) def check_entry_points(dist, attr, value): """Verify that entry_points map is parseable""" -- cgit v1.2.1 From e55483f33a61c302461ed480a3556d746b8aba40 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 May 2015 12:35:19 -0400 Subject: Extract variable for clarity. --- pkg_resources/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 4ed71329..779bd367 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2876,9 +2876,8 @@ def parse_requirements(strs): line = next(lines) p = 0 except StopIteration: - raise RequirementParseError( - "\\ must not appear on the last nonblank line" - ) + msg = "\\ must not appear on the last nonblank line" + raise RequirementParseError(msg) match = ITEM(line, p) if not match: -- cgit v1.2.1 From 0cc8362038f6feb3ede00ee9ce8ba8c7d04940d9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 May 2015 12:39:16 -0400 Subject: Use new string formatting --- setuptools/dist.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index 05669366..d7ad4655 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -115,19 +115,20 @@ def check_extras(dist, attr, value): def assert_bool(dist, attr, value): """Verify that value is True, False, 0, or 1""" if bool(value) != value: - raise DistutilsSetupError( - "%r must be a boolean value (got %r)" % (attr,value) - ) + tmpl = "{attr!r} must be a boolean value (got {value!r})" + raise DistutilsSetupError(tmpl.format(attr=attr, value=value)) + + def check_requirements(dist, attr, value): """Verify that install_requires is a valid requirements list""" try: list(pkg_resources.parse_requirements(value)) - except (TypeError, ValueError) as e: + except (TypeError, ValueError) as error: tmpl = ( - "%r must be a string or list of strings " - "containing valid project/version requirement specifiers; %s" + "{attr!r} must be a string or list of strings " + "containing valid project/version requirement specifiers; {error}" ) - raise DistutilsSetupError(tmpl % (attr, e)) + raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) def check_entry_points(dist, attr, value): """Verify that entry_points map is parseable""" -- cgit v1.2.1 From 0e086ac6e1b12a1db040e1852ca524c625bc53fe Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 3 May 2015 12:56:24 -0400 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index d10e2188..089077b4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +---- +15.3 +---- + +* Pull Request #130: Better error messages for errors in + parsed requirements. + ---- 15.2 ---- -- cgit v1.2.1 From 8b78e4b3bb977323247073fa99de62fdf8571630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Sat, 16 May 2015 15:56:43 +0300 Subject: Don't install tests in site-packages --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 234a7885..afaf9f61 100755 --- a/setup.py +++ b/setup.py @@ -80,7 +80,7 @@ setup_params = dict( keywords="CPAN PyPI distutils eggs package management", url="https://bitbucket.org/pypa/setuptools", src_root=src_root, - packages=setuptools.find_packages(), + packages=setuptools.find_packages(exclude=['*.tests']), package_data=package_data, py_modules=['easy_install'], -- cgit v1.2.1 From bdb02cc81b0caee69db336b0093cbc7243a25879 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 18 May 2015 15:03:59 +0800 Subject: Update changelog --- CHANGES.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 089077b4..6d3466a9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,11 +3,13 @@ CHANGES ======= ---- -15.3 +16.0 ---- * Pull Request #130: Better error messages for errors in parsed requirements. +* Pull Request #133: Removed ``setuptools.tests`` from the + installed packages. ---- 15.2 -- cgit v1.2.1 From c7a68c40760615084c2f3cd4db4158cd248af3aa Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 18 May 2015 15:07:22 +0800 Subject: Bumped to 16.0 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 89970943..14aef949 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "15.3" +DEFAULT_VERSION = "16.0" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index f0d1b4d4..fd4afc5a 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '15.3' +__version__ = '16.0' -- cgit v1.2.1 From d6edbf0cbf36901fea369cafa5c6c3577591eeb4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 18 May 2015 15:08:31 +0800 Subject: Added tag 16.0 for changeset e0825f0c7d59 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 88e9fa67..86037d84 100644 --- a/.hgtags +++ b/.hgtags @@ -209,3 +209,4 @@ e3c635a7d463c7713c647d1aa560f83fd8e27ef0 14.3 d2c4d84867154243993876d6248aafec1fd12679 15.0 10fde952613b7a3f650fb1f6b6ed58cbd232fa3c 15.1 df5dc9c7aa7521f552824dee1ed1315cfe180844 15.2 +e0825f0c7d5963c498266fe3c175220c695ae83b 16.0 -- cgit v1.2.1 From 1f7177fc0f54fac1d76ee8a1c77f93cb2f6f7dc1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 18 May 2015 15:09:52 +0800 Subject: Bumped to 16.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 14aef949..e2b35663 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "16.0" +DEFAULT_VERSION = "16.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index fd4afc5a..aeccd8e3 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '16.0' +__version__ = '16.1' -- cgit v1.2.1 From 6debf8d3d7c4ad63d2aae277fc9b4581c851548e Mon Sep 17 00:00:00 2001 From: James Polley Date: Fri, 22 May 2015 14:54:34 -0700 Subject: Expand the range of valid operators to include comparators --- pkg_resources/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 779bd367..b4029c4a 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -1489,6 +1489,10 @@ class MarkerEvaluation(object): 'in': lambda x, y: x in y, '==': operator.eq, '!=': operator.ne, + '<': operator.lt, + '>': operator.gt, + '<=': operator.le, + '>=': operator.ge, } if hasattr(symbol, 'or_test'): ops[symbol.or_test] = cls.test -- cgit v1.2.1 From 16da5eac3a04bc4224082ee54f5f0f5b1c8d92db Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 27 May 2015 18:12:23 -0400 Subject: extract variable for nicer indentation --- setuptools/command/easy_install.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 74803b59..515c89d5 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -2024,8 +2024,8 @@ class ScriptWriter(object): group = type_ + '_scripts' for name, ep in dist.get_entry_map(group).items(): script_text = cls.template % locals() - for res in cls._get_script_args(type_, name, header, - script_text): + args = cls._get_script_args(type_, name, header, script_text) + for res in args: yield res @classmethod -- cgit v1.2.1 From 7ee56c5270d979f73c248c3ef5bac48793cd77d6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 27 May 2015 18:14:16 -0400 Subject: Update docstring to include the actual entry point names (for hits when grepping). --- setuptools/command/easy_install.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 515c89d5..2c127126 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -2015,7 +2015,8 @@ class ScriptWriter(object): @classmethod def get_args(cls, dist, header=None): """ - Yield write_script() argument tuples for a distribution's entrypoints + Yield write_script() argument tuples for a distribution's + console_scripts and gui_scripts entry points. """ if header is None: header = cls.get_header() -- cgit v1.2.1 From b2847255769f7e40fa757c830020cb2daad7860d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 27 May 2015 18:40:01 -0400 Subject: Disallow path separators in script names. Fixes #390 --- setuptools/command/easy_install.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 2c127126..1b32b1c8 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -2024,11 +2024,21 @@ class ScriptWriter(object): for type_ in 'console', 'gui': group = type_ + '_scripts' for name, ep in dist.get_entry_map(group).items(): + cls._ensure_safe_name(name) script_text = cls.template % locals() args = cls._get_script_args(type_, name, header, script_text) for res in args: yield res + @staticmethod + def _ensure_safe_name(name): + """ + Prevent paths in *_scripts entry point names. + """ + has_path_sep = re.search(r'[\\/]', name) + if has_path_sep: + raise ValueError("Path separators not allowed in script names") + @classmethod def get_writer(cls, force_windows): # for backward compatibility -- cgit v1.2.1 From c87fd7aa8017f31ccf42ed66bae1f31f1cfef642 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 27 May 2015 18:42:49 -0400 Subject: Update changelog --- CHANGES.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 6d3466a9..4ea74081 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +---- +17.0 +---- + +* Issue #390: Disallow console scripts with path separators in + the name. Removes unintended functionality and brings behavior + into parity wih pip. + ---- 16.0 ---- -- cgit v1.2.1 From 75d108c95186aef502333c471ab103baa0602871 Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Thu, 28 May 2015 15:28:22 +0200 Subject: Issue #378: Do not use internal importlib._bootstrap module. --- CHANGES.txt | 1 + pkg_resources/__init__.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 4ea74081..08879612 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -6,6 +6,7 @@ CHANGES 17.0 ---- +* Issue #378: Do not use internal importlib._bootstrap module. * Issue #390: Disallow console scripts with path separators in the name. Removes unintended functionality and brings behavior into parity wih pip. diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 779bd367..7bb0bdb3 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -69,9 +69,9 @@ from os.path import isdir, split # Avoid try/except due to potential problems with delayed import mechanisms. if sys.version_info >= (3, 3) and sys.implementation.name == "cpython": - import importlib._bootstrap as importlib_bootstrap + import importlib.machinery as importlib_machinery else: - importlib_bootstrap = None + importlib_machinery = None try: import parser @@ -1720,8 +1720,8 @@ class DefaultProvider(EggProvider): register_loader_type(type(None), DefaultProvider) -if importlib_bootstrap is not None: - register_loader_type(importlib_bootstrap.SourceFileLoader, DefaultProvider) +if importlib_machinery is not None: + register_loader_type(importlib_machinery.SourceFileLoader, DefaultProvider) class EmptyProvider(NullProvider): @@ -2128,8 +2128,8 @@ def find_on_path(importer, path_item, only=False): break register_finder(pkgutil.ImpImporter, find_on_path) -if importlib_bootstrap is not None: - register_finder(importlib_bootstrap.FileFinder, find_on_path) +if importlib_machinery is not None: + register_finder(importlib_machinery.FileFinder, find_on_path) _declare_state('dict', _namespace_handlers={}) _declare_state('dict', _namespace_packages={}) @@ -2237,8 +2237,8 @@ def file_ns_handler(importer, path_item, packageName, module): register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) register_namespace_handler(zipimport.zipimporter, file_ns_handler) -if importlib_bootstrap is not None: - register_namespace_handler(importlib_bootstrap.FileFinder, file_ns_handler) +if importlib_machinery is not None: + register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) def null_ns_handler(importer, path_item, packageName, module): -- cgit v1.2.1 From 13cf22d8341ebc19d4d43a2b66101192abdfd380 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 28 May 2015 17:54:02 -0400 Subject: Correct typo --- CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 08879612..92cb6a4f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,7 +9,7 @@ CHANGES * Issue #378: Do not use internal importlib._bootstrap module. * Issue #390: Disallow console scripts with path separators in the name. Removes unintended functionality and brings behavior - into parity wih pip. + into parity with pip. ---- 16.0 -- cgit v1.2.1 From 664646d91c8af89509193c747916eb3f4d920db8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 28 May 2015 17:54:28 -0400 Subject: Bumped to 17.0 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index e2b35663..ca42b878 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "16.1" +DEFAULT_VERSION = "17.0" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index aeccd8e3..f4fad79b 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '16.1' +__version__ = '17.0' -- cgit v1.2.1 From f5e82ccfefafe8ab8373db980e47bc23f3b601dc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 28 May 2015 22:22:30 -0400 Subject: Added tag 17.0 for changeset 8e5624096101 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 86037d84..a797d4e6 100644 --- a/.hgtags +++ b/.hgtags @@ -210,3 +210,4 @@ d2c4d84867154243993876d6248aafec1fd12679 15.0 10fde952613b7a3f650fb1f6b6ed58cbd232fa3c 15.1 df5dc9c7aa7521f552824dee1ed1315cfe180844 15.2 e0825f0c7d5963c498266fe3c175220c695ae83b 16.0 +8e56240961015347fed477f00ca6a0783e81d3a2 17.0 -- cgit v1.2.1 From 435745ff2ff4be11ba68c41f297fbcbc3ee1fed5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 28 May 2015 22:23:34 -0400 Subject: Bumped to 17.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index ca42b878..7966a1da 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "17.0" +DEFAULT_VERSION = "17.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index f4fad79b..f57a6fba 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '17.0' +__version__ = '17.1' -- cgit v1.2.1 From 90a3e3b896d4f86337692f361a5a1bdcbf310bf9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 7 Jun 2015 10:05:00 -0400 Subject: Add tests capturing expectation for range comparison operators (Ref #380). --- pkg_resources/api_tests.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg_resources/api_tests.txt b/pkg_resources/api_tests.txt index a6c25a37..fc645d48 100644 --- a/pkg_resources/api_tests.txt +++ b/pkg_resources/api_tests.txt @@ -417,3 +417,9 @@ Environment Markers >>> em("'yx' in 'x'") False + + >>> em("python_version >= '2.6'") + True + + >>> em("python_version > '2.5'") + True -- cgit v1.2.1 From c3bf0dd4521637a1301187af0aa8732613674561 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 7 Jun 2015 10:22:01 -0400 Subject: Remove now deprecated test capturing failure of range comparison operators (Ref #380). --- pkg_resources/api_tests.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg_resources/api_tests.txt b/pkg_resources/api_tests.txt index fc645d48..1c852e81 100644 --- a/pkg_resources/api_tests.txt +++ b/pkg_resources/api_tests.txt @@ -364,9 +364,6 @@ Environment Markers >>> print(im("'x'=='x' or os.open('foo')=='y'")) # no short-circuit! Language feature not supported in environment markers - >>> print(im("'x' < 'y'")) - '<' operator not allowed in environment markers - >>> print(im("'x' < 'y' < 'z'")) Chained comparison not allowed in environment markers -- cgit v1.2.1 From 208af4d231da879174ba189c2f756360ae6dca0a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 7 Jun 2015 10:34:17 -0400 Subject: Add test capturing possible violation in expectation due to new Python 2.7.10 release. Ref #380. --- pkg_resources/tests/test_markers.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 pkg_resources/tests/test_markers.py diff --git a/pkg_resources/tests/test_markers.py b/pkg_resources/tests/test_markers.py new file mode 100644 index 00000000..d8844e74 --- /dev/null +++ b/pkg_resources/tests/test_markers.py @@ -0,0 +1,16 @@ +try: + import unittest.mock as mock +except ImportError: + import mock + +from pkg_resources import evaluate_marker + + +@mock.patch.dict('pkg_resources.MarkerEvaluation.values', + python_full_version=mock.Mock(return_value='2.7.10')) +def test_lexicographic_ordering(): + """ + Although one might like 2.7.10 to be greater than 2.7.3, + the marker spec only supports lexicographic ordering. + """ + assert evaluate_marker("python_full_version > '2.7.3'") is False -- cgit v1.2.1 From 3ab82175e1d843d8f09f69f2d82ffc5d7d9a03df Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 7 Jun 2015 10:37:34 -0400 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 92cb6a4f..4734ff04 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +---- +17.1 +---- + +* Issue #380: Add support for range operators on environment + marker evaluation. + ---- 17.0 ---- -- cgit v1.2.1 From f7a6205b6145e5ba29d3be6b05d923ea50bab9c2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 7 Jun 2015 10:38:05 -0400 Subject: Added tag 17.1 for changeset a37bcaaeab36 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index a797d4e6..d554dc63 100644 --- a/.hgtags +++ b/.hgtags @@ -211,3 +211,4 @@ d2c4d84867154243993876d6248aafec1fd12679 15.0 df5dc9c7aa7521f552824dee1ed1315cfe180844 15.2 e0825f0c7d5963c498266fe3c175220c695ae83b 16.0 8e56240961015347fed477f00ca6a0783e81d3a2 17.0 +a37bcaaeab367f2364ed8c070659d52a4c0ae38e 17.1 -- cgit v1.2.1 From 77b0d0176a4c26de3121d135853b28c3f290c3c7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 7 Jun 2015 10:39:14 -0400 Subject: Bumped to 17.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 7966a1da..dd5bf5b9 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "17.1" +DEFAULT_VERSION = "17.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index f57a6fba..7da47b5e 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '17.1' +__version__ = '17.2' -- cgit v1.2.1 From c1044e3706ed28a6913e0dfcb4f7eec713af34c1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 8 Jun 2015 13:22:43 -0400 Subject: Backed out unintended changes made in f572ec9, restoring use of 'imp' module for dynamic module creation originally committed in 06ac3674 and 4c121bd24f. --- pkg_resources/__init__.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 4ed71329..c3b3d7af 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -21,7 +21,7 @@ import os import io import time import re -import imp +import types import zipfile import zipimport import warnings @@ -39,6 +39,12 @@ import tempfile import textwrap from pkgutil import get_importer +try: + import _imp +except ImportError: + # Python 3.2 compatibility + import imp as _imp + PY3 = sys.version_info > (3,) PY2 = not PY3 @@ -2163,7 +2169,7 @@ def _handle_ns(packageName, path_item): return None module = sys.modules.get(packageName) if module is None: - module = sys.modules[packageName] = imp.new_module(packageName) + module = sys.modules[packageName] = types.ModuleType(packageName) module.__path__ = [] _set_parent_ns(packageName) elif not hasattr(module,'__path__'): @@ -2182,7 +2188,7 @@ def _handle_ns(packageName, path_item): def declare_namespace(packageName): """Declare that package 'packageName' is a namespace package""" - imp.acquire_lock() + _imp.acquire_lock() try: if packageName in _namespace_packages: return @@ -2209,18 +2215,18 @@ def declare_namespace(packageName): _handle_ns(packageName, path_item) finally: - imp.release_lock() + _imp.release_lock() def fixup_namespace_packages(path_item, parent=None): """Ensure that previously-declared namespace packages include path_item""" - imp.acquire_lock() + _imp.acquire_lock() try: for package in _namespace_packages.get(parent,()): subpath = _handle_ns(package, path_item) if subpath: fixup_namespace_packages(subpath, package) finally: - imp.release_lock() + _imp.release_lock() def file_ns_handler(importer, path_item, packageName, module): """Compute an ns-package subpath for a filesystem or zipfile importer""" -- cgit v1.2.1 From 9b9c404a50c48e9be857c8743f80c7f8398d9d85 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 8 Jun 2015 13:29:05 -0400 Subject: Update changelog --- CHANGES.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 4734ff04..9ca376fa 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +------ +17.1.1 +------ + +* Backed out unintended changes to pkg_resources, restoring removal of + deprecated imp module (`ref + `_). + ---- 17.1 ---- -- cgit v1.2.1 From bcd3e0055d24ea0b0077a2d986f6c4090489a644 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 8 Jun 2015 13:36:25 -0400 Subject: Bumped to 17.1.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index dd5bf5b9..46cd2099 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "17.2" +DEFAULT_VERSION = "17.1.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 7da47b5e..6c8b4c2b 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '17.2' +__version__ = '17.1.1' -- cgit v1.2.1 From 805f39c73599c71536a8c62e5d67506d830c799a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 8 Jun 2015 13:36:26 -0400 Subject: Added tag 17.1.1 for changeset 4a0d01d690ff --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index d554dc63..ebbc6a12 100644 --- a/.hgtags +++ b/.hgtags @@ -212,3 +212,4 @@ df5dc9c7aa7521f552824dee1ed1315cfe180844 15.2 e0825f0c7d5963c498266fe3c175220c695ae83b 16.0 8e56240961015347fed477f00ca6a0783e81d3a2 17.0 a37bcaaeab367f2364ed8c070659d52a4c0ae38e 17.1 +4a0d01d690ff184904293e7a3244ac24ec060a73 17.1.1 -- cgit v1.2.1 From c1d71724e6f73eec022cb86161cf777ff37b009b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 8 Jun 2015 13:37:34 -0400 Subject: Bumped to 17.1.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 46cd2099..07e4f6d8 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "17.1.1" +DEFAULT_VERSION = "17.1.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 6c8b4c2b..a9da9717 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '17.1.1' +__version__ = '17.1.2' -- cgit v1.2.1 From a811c089a4362c0dc6c4a84b708953dde9ebdbf8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 10 Jun 2015 12:33:54 -0400 Subject: Detect Cython later in the build process, allowing the library to be specified in setup_requires. Fixes #288. --- CHANGES.txt | 24 ++++++++++++++++++++++++ setuptools/command/build_ext.py | 15 +++------------ setuptools/extension.py | 21 ++++++++++----------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 9ca376fa..5a1c7493 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,30 @@ CHANGES ======= +---- +18.0 +---- + +* Dropped support for builds with Pyrex. Only Cython is supported. +* Issue #288: Detect Cython later in the build process, after + ``setup_requires`` dependencies are resolved. + Projects backed by Cython can now be readily built + with a ``setup_requires`` dependency. For example:: + + ext = setuptools.Extension('mylib', ['src/CythonStuff.pyx', 'src/CStuff.c']) + setuptools.setup( + ... + ext_modules=[ext], + setup_requires=['cython'], + ) + + For compatibility with older versions of setuptools, packagers should + still include ``src/CythonMod.c`` in the source distributions or + require that Cython be present before building source distributions. + However, for systems with this build of setuptools, Cython will be + downloaded on demand. + + ------ 17.1.1 ------ diff --git a/setuptools/command/build_ext.py b/setuptools/command/build_ext.py index e4b2c593..92e4a189 100644 --- a/setuptools/command/build_ext.py +++ b/setuptools/command/build_ext.py @@ -11,8 +11,8 @@ import itertools from setuptools.extension import Library try: - # Attempt to use Pyrex for building extensions, if available - from Pyrex.Distutils.build_ext import build_ext as _build_ext + # Attempt to use Cython for building extensions, if available + from Cython.Distutils.build_ext import build_ext as _build_ext except ImportError: _build_ext = _du_build_ext @@ -42,7 +42,6 @@ elif os.name != 'nt': if_dl = lambda s: s if have_rtld else '' - class build_ext(_build_ext): def run(self): """Build extensions in build directory, then copy if --inplace""" @@ -74,15 +73,6 @@ class build_ext(_build_ext): if ext._needs_stub: self.write_stub(package_dir or os.curdir, ext, True) - if _build_ext is not _du_build_ext and not hasattr(_build_ext, - 'pyrex_sources'): - # Workaround for problems using some Pyrex versions w/SWIG and/or 2.4 - def swig_sources(self, sources, *otherargs): - # first do any Pyrex processing - sources = _build_ext.swig_sources(self, sources) or sources - # Then do any actual SWIG stuff on the remainder - return _du_build_ext.swig_sources(self, sources, *otherargs) - def get_ext_filename(self, fullname): filename = _build_ext.get_ext_filename(self, fullname) if fullname in self.ext_map: @@ -176,6 +166,7 @@ class build_ext(_build_ext): return _build_ext.get_export_symbols(self, ext) def build_extension(self, ext): + ext._convert_pyx_sources_to_lang() _compiler = self.compiler try: if isinstance(ext, Library): diff --git a/setuptools/extension.py b/setuptools/extension.py index 8178ed33..a7c40f86 100644 --- a/setuptools/extension.py +++ b/setuptools/extension.py @@ -12,35 +12,34 @@ _Extension = _get_unpatched(distutils.core.Extension) msvc9_support.patch_for_specialized_compiler() -def have_pyrex(): +def _have_cython(): """ - Return True if Cython or Pyrex can be imported. + Return True if Cython can be imported. """ - pyrex_impls = 'Cython.Distutils.build_ext', 'Pyrex.Distutils.build_ext' - for pyrex_impl in pyrex_impls: + cython_impls = 'Cython.Distutils.build_ext', + for cython_impl in cython_impls: try: - # from (pyrex_impl) import build_ext - __import__(pyrex_impl, fromlist=['build_ext']).build_ext + # from (cython_impl) import build_ext + __import__(cython_impl, fromlist=['build_ext']).build_ext return True except Exception: pass return False +# for compatibility +have_pyrex = _have_cython + class Extension(_Extension): """Extension that uses '.c' files in place of '.pyx' files""" - def __init__(self, *args, **kw): - _Extension.__init__(self, *args, **kw) - self._convert_pyx_sources_to_lang() - def _convert_pyx_sources_to_lang(self): """ Replace sources with .pyx extensions to sources with the target language extension. This mechanism allows language authors to supply pre-converted sources but to prefer the .pyx sources. """ - if have_pyrex(): + if _have_cython(): # the build has Cython, so allow it to compile the .pyx files return lang = self.language or '' -- cgit v1.2.1 From 7bbbe8f420a1d52652eca080b3302f2fa64d9c30 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 10 Jun 2015 12:46:41 -0400 Subject: Bumped to 18.0 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 07e4f6d8..6db030d7 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "17.1.2" +DEFAULT_VERSION = "18.0" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index a9da9717..407a82bc 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '17.1.2' +__version__ = '18.0' -- cgit v1.2.1 From 8c428b55cd4649bea3092f134bda8c919b96fe94 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 10 Jun 2015 12:47:02 -0400 Subject: Added tag 18.0b1 for changeset fac98a49bd98 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index ebbc6a12..1c413807 100644 --- a/.hgtags +++ b/.hgtags @@ -213,3 +213,4 @@ e0825f0c7d5963c498266fe3c175220c695ae83b 16.0 8e56240961015347fed477f00ca6a0783e81d3a2 17.0 a37bcaaeab367f2364ed8c070659d52a4c0ae38e 17.1 4a0d01d690ff184904293e7a3244ac24ec060a73 17.1.1 +fac98a49bd984ef5accf7177674d693277bfbaef 18.0b1 -- cgit v1.2.1 From 3c047624cfa74a42320334ed6ec0dd7b6bd789b6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 10 Jun 2015 14:56:52 -0400 Subject: Remove loop, made unnecessary by removal of support for Pyrex --- setuptools/extension.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/setuptools/extension.py b/setuptools/extension.py index a7c40f86..35eb7c7c 100644 --- a/setuptools/extension.py +++ b/setuptools/extension.py @@ -16,14 +16,13 @@ def _have_cython(): """ Return True if Cython can be imported. """ - cython_impls = 'Cython.Distutils.build_ext', - for cython_impl in cython_impls: - try: - # from (cython_impl) import build_ext - __import__(cython_impl, fromlist=['build_ext']).build_ext - return True - except Exception: - pass + cython_impl = 'Cython.Distutils.build_ext', + try: + # from (cython_impl) import build_ext + __import__(cython_impl, fromlist=['build_ext']).build_ext + return True + except Exception: + pass return False # for compatibility -- cgit v1.2.1 From e5588b705a2418bd7c46aeae4971f7ebe4bd6ead Mon Sep 17 00:00:00 2001 From: Stephen Drake Date: Thu, 11 Jun 2015 03:22:51 +0000 Subject: Don't quote executable name twice in script headers Don't quote the executable name in JythonCommandSpec.from_environment() since it is quoted if necessary in CommandSpec._render(). With the executable quoted on initialisation of JythonCommandSpec, the quotes get escaped in the resulting header, eg: #!/usr/bin/env \"/path/to/jython\" --- setuptools/command/easy_install.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 1b32b1c8..df1655bf 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1944,15 +1944,6 @@ class JythonCommandSpec(CommandSpec): __import__('java').lang.System.getProperty('os.name') != 'Linux' ) - @classmethod - def from_environment(cls): - string = '"' + cls._sys_executable() + '"' - return cls.from_string(string) - - @classmethod - def from_string(cls, string): - return cls([string]) - def as_header(self): """ Workaround Jython's sys.executable being a .sh (an invalid -- cgit v1.2.1 From 79e447fcc29d4591f1a4b3403840357e8bccb234 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 13 Jun 2015 11:05:37 -0400 Subject: Fix test failure when __PYVENV_LAUNCHER__ is set. Fixes #396. --- setuptools/tests/test_easy_install.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index e71bbfc9..a690315d 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -488,9 +488,11 @@ class TestCommandSpec: cmd_new = ei.CommandSpec.from_param(cmd) assert cmd is cmd_new + @mock.patch('sys.executable', TestScriptHeader.exe_with_spaces) + @mock.patch.dict(os.environ) def test_from_environment_with_spaces_in_executable(self): - with mock.patch('sys.executable', TestScriptHeader.exe_with_spaces): - cmd = ei.CommandSpec.from_environment() + del os.environ['__PYVENV_LAUNCHER__'] + cmd = ei.CommandSpec.from_environment() assert len(cmd) == 1 assert cmd.as_header().startswith('#!"') -- cgit v1.2.1 From ca3a52c7b79fa6d8279c2c5eea739414dd481aee Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 13 Jun 2015 11:10:46 -0400 Subject: Update changelog --- CHANGES.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 5a1c7493..8b229910 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -24,7 +24,9 @@ CHANGES require that Cython be present before building source distributions. However, for systems with this build of setuptools, Cython will be downloaded on demand. - +* Issue #396: Fixed test failure on OS X. +* Pull Request #136: Remove excessive quoting from shebang headers + for Jython. ------ 17.1.1 -- cgit v1.2.1 From 01c1e7b38b4017e705c8a42b72281b1048afeec2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 23 Jun 2015 18:51:26 -0400 Subject: Added tag 18.0 for changeset 0a49ee524b0a --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 1c413807..5e08eb8a 100644 --- a/.hgtags +++ b/.hgtags @@ -214,3 +214,4 @@ e0825f0c7d5963c498266fe3c175220c695ae83b 16.0 a37bcaaeab367f2364ed8c070659d52a4c0ae38e 17.1 4a0d01d690ff184904293e7a3244ac24ec060a73 17.1.1 fac98a49bd984ef5accf7177674d693277bfbaef 18.0b1 +0a49ee524b0a1d67d2a11c8c22f082b57acd7ae1 18.0 -- cgit v1.2.1 From 47413a2792fb772f4bdcf7a61a843b495464feae Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 23 Jun 2015 18:52:38 -0400 Subject: Bumped to 18.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 6db030d7..cc8da01e 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.0" +DEFAULT_VERSION = "18.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 407a82bc..92f36007 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.0' +__version__ = '18.1' -- cgit v1.2.1 From ea96c15d03dea659cb3cd572e1246bb15ec68e1c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 23 Jun 2015 20:20:13 -0400 Subject: Conditionally remove __PYVENV_LAUNCHER__ --- setuptools/tests/test_easy_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index a690315d..66601bfe 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -491,7 +491,7 @@ class TestCommandSpec: @mock.patch('sys.executable', TestScriptHeader.exe_with_spaces) @mock.patch.dict(os.environ) def test_from_environment_with_spaces_in_executable(self): - del os.environ['__PYVENV_LAUNCHER__'] + os.environ.pop('__PYVENV_LAUNCHER__', None) cmd = ei.CommandSpec.from_environment() assert len(cmd) == 1 assert cmd.as_header().startswith('#!"') -- cgit v1.2.1 From a23e95f499849815db5c852a4983388c8a27b0cb Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 24 Jun 2015 16:59:21 -0400 Subject: Update changelog. Along with f44e81f2f62f, fixes #401. --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 8b229910..58c72312 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,12 @@ CHANGES ======= +------ +18.0.1 +------ + +* Issue #401: Fix failure in test suite. + ---- 18.0 ---- -- cgit v1.2.1 From fc350581c83b27d5846b192016f7525059790f5e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 24 Jun 2015 16:59:48 -0400 Subject: Bumped to 18.0.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index cc8da01e..3762bd80 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.1" +DEFAULT_VERSION = "18.0.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 92f36007..0c6e893f 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.1' +__version__ = '18.0.1' -- cgit v1.2.1 From bf0d9092a69ecbdcf5e5a768bdd892b616ce11bb Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 24 Jun 2015 16:59:50 -0400 Subject: Added tag 18.0.1 for changeset e364795c1b09 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 5e08eb8a..2b76cd27 100644 --- a/.hgtags +++ b/.hgtags @@ -215,3 +215,4 @@ a37bcaaeab367f2364ed8c070659d52a4c0ae38e 17.1 4a0d01d690ff184904293e7a3244ac24ec060a73 17.1.1 fac98a49bd984ef5accf7177674d693277bfbaef 18.0b1 0a49ee524b0a1d67d2a11c8c22f082b57acd7ae1 18.0 +e364795c1b09c70b6abb53770e09763b52bf807d 18.0.1 -- cgit v1.2.1 From d215171466c4c7511044f92337e215ceda26d07f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 24 Jun 2015 17:01:04 -0400 Subject: Bumped to 18.0.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 3762bd80..4fea4ec3 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.0.1" +DEFAULT_VERSION = "18.0.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 0c6e893f..0767a409 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.0.1' +__version__ = '18.0.2' -- cgit v1.2.1 From e0beae7ae0bea46e4af3892bd4d9298d256d3205 Mon Sep 17 00:00:00 2001 From: vrutsky Date: Thu, 2 Jul 2015 11:00:57 +0000 Subject: fix typo: "a a" --- docs/setuptools.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/setuptools.txt b/docs/setuptools.txt index 89c08e23..0feb09ea 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -1467,7 +1467,7 @@ are included in any source distribution you build. This is a big improvement over having to manually write a ``MANIFEST.in`` file and try to keep it in sync with your project. So, if you are using CVS or Subversion, and your source distributions only need to include files that you're tracking in -revision control, don't create a a ``MANIFEST.in`` file for your project. +revision control, don't create a ``MANIFEST.in`` file for your project. (And, if you already have one, you might consider deleting it the next time you would otherwise have to change it.) -- cgit v1.2.1 From d51ba2d7a8850a7fb56a6572b372626dd1cd3631 Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Mon, 20 Jul 2015 16:35:49 +0100 Subject: Big performance fix for find_packages by ignoring hidden dirs earlier --- setuptools/__init__.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 8188f125..f6536359 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -81,10 +81,20 @@ class PackageFinder(object): for dir in dirs: yield os.path.relpath(os.path.join(root, dir), base_path) + @staticmethod + def _suitable_dirs(base_path): + """ + Return all suitable package dirs in base_path, relative to base_path + """ + for root, dirs, files in os.walk(base_path, followlinks=True): + # Mutate dirs to trim the search: + dirs[:] = filterfalse(lambda n: '.' in n, dirs) + for dir in dirs: + yield os.path.relpath(os.path.join(root, dir), base_path) + @classmethod def _find_packages_iter(cls, base_path): - dirs = cls._all_dirs(base_path) - suitable = filterfalse(lambda n: '.' in n, dirs) + suitable = cls._suitable_dirs(base_path) return ( path.replace(os.path.sep, '.') for path in suitable -- cgit v1.2.1 From e3886227ec1c8db491f79eaf46500d65b81b7d6d Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Sat, 1 Aug 2015 20:13:21 -0400 Subject: Upgrade packaging to 15.3 --- pkg_resources/_vendor/packaging/__about__.py | 2 +- pkg_resources/_vendor/packaging/specifiers.py | 24 ++++++++++++++++++++++-- pkg_resources/_vendor/packaging/version.py | 2 ++ pkg_resources/_vendor/vendored.txt | 2 +- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/pkg_resources/_vendor/packaging/__about__.py b/pkg_resources/_vendor/packaging/__about__.py index d5243995..eadb794e 100644 --- a/pkg_resources/_vendor/packaging/__about__.py +++ b/pkg_resources/_vendor/packaging/__about__.py @@ -22,7 +22,7 @@ __title__ = "packaging" __summary__ = "Core utilities for Python packages" __uri__ = "https://github.com/pypa/packaging" -__version__ = "15.1" +__version__ = "15.3" __author__ = "Donald Stufft" __email__ = "donald@stufft.io" diff --git a/pkg_resources/_vendor/packaging/specifiers.py b/pkg_resources/_vendor/packaging/specifiers.py index d5d8a956..891664f0 100644 --- a/pkg_resources/_vendor/packaging/specifiers.py +++ b/pkg_resources/_vendor/packaging/specifiers.py @@ -151,6 +151,14 @@ class _IndividualSpecifier(BaseSpecifier): version = parse(version) return version + @property + def operator(self): + return self._spec[0] + + @property + def version(self): + return self._spec[1] + @property def prereleases(self): return self._prereleases @@ -159,6 +167,9 @@ class _IndividualSpecifier(BaseSpecifier): def prereleases(self, value): self._prereleases = value + def __contains__(self, item): + return self.contains(item) + def contains(self, item, prereleases=None): # Determine if prereleases are to be allowed or not. if prereleases is None: @@ -176,7 +187,7 @@ class _IndividualSpecifier(BaseSpecifier): # Actually do the comparison to determine if this item is contained # within this Specifier or not. - return self._get_operator(self._spec[0])(item, self._spec[1]) + return self._get_operator(self.operator)(item, self.version) def filter(self, iterable, prereleases=None): yielded = False @@ -526,7 +537,7 @@ class Specifier(_IndividualSpecifier): # operators, and if they are if they are including an explicit # prerelease. operator, version = self._spec - if operator in ["==", ">=", "<=", "~="]: + if operator in ["==", ">=", "<=", "~=", "==="]: # The == specifier can include a trailing .*, if it does we # want to remove before parsing. if operator == "==" and version.endswith(".*"): @@ -666,6 +677,12 @@ class SpecifierSet(BaseSpecifier): return self._specs != other._specs + def __len__(self): + return len(self._specs) + + def __iter__(self): + return iter(self._specs) + @property def prereleases(self): # If we have been given an explicit prerelease modifier, then we'll @@ -687,6 +704,9 @@ class SpecifierSet(BaseSpecifier): def prereleases(self, value): self._prereleases = value + def __contains__(self, item): + return self.contains(item) + def contains(self, item, prereleases=None): # Ensure that our item is a Version or LegacyVersion instance. if not isinstance(item, (LegacyVersion, Version)): diff --git a/pkg_resources/_vendor/packaging/version.py b/pkg_resources/_vendor/packaging/version.py index cf8afb16..4ba574b9 100644 --- a/pkg_resources/_vendor/packaging/version.py +++ b/pkg_resources/_vendor/packaging/version.py @@ -324,6 +324,8 @@ def _parse_letter_version(letter, number): letter = "b" elif letter in ["c", "pre", "preview"]: letter = "rc" + elif letter in ["rev", "r"]: + letter = "post" return letter, int(number) if not letter and number: diff --git a/pkg_resources/_vendor/vendored.txt b/pkg_resources/_vendor/vendored.txt index 28da4226..4cf7664e 100644 --- a/pkg_resources/_vendor/vendored.txt +++ b/pkg_resources/_vendor/vendored.txt @@ -1 +1 @@ -packaging==15.1 +packaging==15.3 -- cgit v1.2.1 From 8a65cea4898dcbdf26ac5b9488964b59a8724a5f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 2 Aug 2015 14:51:26 -0400 Subject: Update changelog --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 58c72312..6dda9dbb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,12 @@ CHANGES ======= +---- +18.1 +---- + +* Upgrade to vendored packaging 15.3. + ------ 18.0.1 ------ -- cgit v1.2.1 From 35bd5713397e0a25eaf1d79230fd1f119838f109 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 2 Aug 2015 14:51:39 -0400 Subject: Bumped to 18.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 4fea4ec3..cc8da01e 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.0.2" +DEFAULT_VERSION = "18.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 0767a409..92f36007 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.0.2' +__version__ = '18.1' -- cgit v1.2.1 From cacab2e858037a14060925d3422bc32c152719b3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 2 Aug 2015 14:51:41 -0400 Subject: Added tag 18.1 for changeset c0395f556c35 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 2b76cd27..51ada8d7 100644 --- a/.hgtags +++ b/.hgtags @@ -216,3 +216,4 @@ a37bcaaeab367f2364ed8c070659d52a4c0ae38e 17.1 fac98a49bd984ef5accf7177674d693277bfbaef 18.0b1 0a49ee524b0a1d67d2a11c8c22f082b57acd7ae1 18.0 e364795c1b09c70b6abb53770e09763b52bf807d 18.0.1 +c0395f556c35d8311fdfe2bda6846b91149819cd 18.1 -- cgit v1.2.1 From 30ece5ff98b651251c491ecf9c7f8c12ebe0f6b8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 2 Aug 2015 14:52:45 -0400 Subject: Bumped to 18.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index cc8da01e..f46e986b 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.1" +DEFAULT_VERSION = "18.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 92f36007..715ea4a6 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.1' +__version__ = '18.2' -- cgit v1.2.1 From 504d4012293d09847e02d5aa5b495db730077f4f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 7 Aug 2015 14:06:28 -0400 Subject: Remove unused _all_dirs. Prefer 'candidate' to 'suitable'. Update documentation. --- setuptools/__init__.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index f6536359..2c492446 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -73,31 +73,24 @@ class PackageFinder(object): yield pkg @staticmethod - def _all_dirs(base_path): + def _candidate_dirs(base_path): """ - Return all dirs in base_path, relative to base_path + Return all dirs in base_path that might be packages. """ + has_dot = lambda name: '.' in name for root, dirs, files in os.walk(base_path, followlinks=True): - for dir in dirs: - yield os.path.relpath(os.path.join(root, dir), base_path) - - @staticmethod - def _suitable_dirs(base_path): - """ - Return all suitable package dirs in base_path, relative to base_path - """ - for root, dirs, files in os.walk(base_path, followlinks=True): - # Mutate dirs to trim the search: - dirs[:] = filterfalse(lambda n: '.' in n, dirs) + # Exclude directories that contain a period, as they cannot be + # packages. Mutate the list to avoid traversal. + dirs[:] = filterfalse(has_dot, dirs) for dir in dirs: yield os.path.relpath(os.path.join(root, dir), base_path) @classmethod def _find_packages_iter(cls, base_path): - suitable = cls._suitable_dirs(base_path) + candidates = cls._candidate_dirs(base_path) return ( path.replace(os.path.sep, '.') - for path in suitable + for path in candidates if cls._looks_like_package(os.path.join(base_path, path)) ) -- cgit v1.2.1 From e999c1c445b3891e972ad9353cca334e82621363 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 7 Aug 2015 14:18:54 -0400 Subject: Update changelog. Fixes #412. --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 6dda9dbb..e95f616b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,12 @@ CHANGES ======= +---- +18.2 +---- + +* Issue #412: More efficient directory search in ``find_packages``. + ---- 18.1 ---- -- cgit v1.2.1 From 2271e6d1d51c694a73a541b497fb26cc506516d5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 17:43:21 +0100 Subject: Link packaging versions to CHANGELOG in packaging project. Fixes #416. --- docs/conf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index ba3a35bc..c2a63873 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -246,6 +246,10 @@ link_files = { pattern=r"Packaging #(?P\d+)", url='{GH}/pypa/packaging/issues/{packaging}', ), + dict( + pattern=r"[Pp]ackaging (?P\d+(\.\d+)+)", + url='{GH}/pypa/packaging/blob/{packaging_ver}/CHANGELOG.rst', + ), ], ), } -- cgit v1.2.1 From 595ed8baab48541dd1bbb2c6907c5463305b646b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 17:46:00 +0100 Subject: Rephrase to allow link --- CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index e95f616b..10027a90 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -91,7 +91,7 @@ CHANGES 15.1 ---- -* Updated Packaging to 15.1 to address Packaging #28. +* Updated to Packaging 15.1 to address Packaging #28. * Fix ``setuptools.sandbox._execfile()`` with Python 3.1. ---- -- cgit v1.2.1 From 831d2feb383f0d1699582e265e931cf435421741 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 17:46:14 +0100 Subject: Added tag 18.2 for changeset 1a981f2e5031 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 51ada8d7..447b5cdb 100644 --- a/.hgtags +++ b/.hgtags @@ -217,3 +217,4 @@ fac98a49bd984ef5accf7177674d693277bfbaef 18.0b1 0a49ee524b0a1d67d2a11c8c22f082b57acd7ae1 18.0 e364795c1b09c70b6abb53770e09763b52bf807d 18.0.1 c0395f556c35d8311fdfe2bda6846b91149819cd 18.1 +1a981f2e5031f55267dc2a28fa1b42274a1b64b2 18.2 -- cgit v1.2.1 From 413d2abe55dc436b22516ac663f14dd85987d3d9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 17:47:20 +0100 Subject: Bumped to 18.3 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index f46e986b..a13ce156 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.2" +DEFAULT_VERSION = "18.3" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 715ea4a6..861921f0 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.2' +__version__ = '18.3' -- cgit v1.2.1 From 1f9c2b756ae6050e11d2dfde03a48df354fb0835 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 19:33:55 +0100 Subject: Extract variable --- setuptools/command/easy_install.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index df1655bf..dfdd757e 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1530,7 +1530,8 @@ class PthDistributions(Environment): if not self.dirty: return - data = '\n'.join(map(self.make_relative, self.paths)) + rel_paths = map(self.make_relative, self.paths) + data = '\n'.join(rel_paths) if data: log.debug("Saving %s", self.filename) data = ( -- cgit v1.2.1 From 9dc51a56c6133f2b115bc8133236e25cd2bb0a31 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 19:36:06 +0100 Subject: Do join late --- setuptools/command/easy_install.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index dfdd757e..4688cc42 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1530,9 +1530,8 @@ class PthDistributions(Environment): if not self.dirty: return - rel_paths = map(self.make_relative, self.paths) - data = '\n'.join(rel_paths) - if data: + rel_paths = list(map(self.make_relative, self.paths)) + if rel_paths: log.debug("Saving %s", self.filename) data = ( "import sys; sys.__plen = len(sys.path)\n" @@ -1541,7 +1540,7 @@ class PthDistributions(Environment): " del sys.path[sys.__plen:];" " p=getattr(sys,'__egginsert',0); sys.path[p:p]=new;" " sys.__egginsert = p+len(new)\n" - ) % data + ) % '\n'.join(rel_paths) if os.path.islink(self.filename): os.unlink(self.filename) -- cgit v1.2.1 From 3f2ccea66a3deee1e4a4234d695dd94282ec3819 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 19:46:57 +0100 Subject: Extract method for wrapping lines --- setuptools/command/easy_install.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 4688cc42..15b260dd 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1533,14 +1533,8 @@ class PthDistributions(Environment): rel_paths = list(map(self.make_relative, self.paths)) if rel_paths: log.debug("Saving %s", self.filename) - data = ( - "import sys; sys.__plen = len(sys.path)\n" - "%s\n" - "import sys; new=sys.path[sys.__plen:];" - " del sys.path[sys.__plen:];" - " p=getattr(sys,'__egginsert',0); sys.path[p:p]=new;" - " sys.__egginsert = p+len(new)\n" - ) % '\n'.join(rel_paths) + lines = self._wrap_lines(rel_paths) + data = '\n'.join(lines) + '\n' if os.path.islink(self.filename): os.unlink(self.filename) @@ -1554,6 +1548,26 @@ class PthDistributions(Environment): self.dirty = False + def _wrap_lines(self, lines): + yield self._inline(""" + import sys + sys.__plen = len(sys.path) + """) + for line in lines: + yield line + yield self._inline(""" + import sys + new = sys.path[sys.__plen:] + del sys.path[sys.__plen:] + p = getattr(sys, '__egginsert', 0) + sys.path[p:p] = new + sys.__egginsert = p + len(new) + """) + + @staticmethod + def _inline(text): + return textwrap.dedent(text).strip().replace('\n', '; ') + def add(self, dist): """Add `dist` to the distribution map""" new_path = ( -- cgit v1.2.1 From 50aaf9938a4437db7f2949df6ecb6460c789ff28 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 19:47:55 +0100 Subject: Open file in context manager --- setuptools/command/easy_install.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 15b260dd..0e912156 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1538,9 +1538,8 @@ class PthDistributions(Environment): if os.path.islink(self.filename): os.unlink(self.filename) - f = open(self.filename, 'wt') - f.write(data) - f.close() + with open(self.filename, 'wt') as f: + f.write(data) elif os.path.exists(self.filename): log.debug("Deleting empty %s", self.filename) -- cgit v1.2.1 From 5cbb2ada2e22f95b1dd0cd8ed14643a8cb3766cd Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 19:58:12 +0100 Subject: Calculate prelude and postlude early --- setuptools/command/easy_install.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 0e912156..b6b0cffd 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1547,25 +1547,26 @@ class PthDistributions(Environment): self.dirty = False - def _wrap_lines(self, lines): - yield self._inline(""" - import sys - sys.__plen = len(sys.path) - """) + @classmethod + def _wrap_lines(cls, lines): + yield cls.prelude for line in lines: yield line - yield self._inline(""" - import sys - new = sys.path[sys.__plen:] - del sys.path[sys.__plen:] - p = getattr(sys, '__egginsert', 0) - sys.path[p:p] = new - sys.__egginsert = p + len(new) - """) + yield cls.postlude - @staticmethod - def _inline(text): - return textwrap.dedent(text).strip().replace('\n', '; ') + _inline = lambda text: textwrap.dedent(text).strip().replace('\n', '; ') + prelude = _inline(""" + import sys + sys.__plen = len(sys.path) + """) + postlude = _inline(""" + import sys + new = sys.path[sys.__plen:] + del sys.path[sys.__plen:] + p = getattr(sys, '__egginsert', 0) + sys.path[p:p] = new + sys.__egginsert = p + len(new) + """) def add(self, dist): """Add `dist` to the distribution map""" -- cgit v1.2.1 From e2124f4d4c74770ccc0b9fc5f0e17becda578063 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 20:29:08 +0100 Subject: Extract a class for the behavior that rewrites the sys.path --- setuptools/command/easy_install.py | 50 +++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index b6b0cffd..2b639c1b 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1547,26 +1547,9 @@ class PthDistributions(Environment): self.dirty = False - @classmethod - def _wrap_lines(cls, lines): - yield cls.prelude - for line in lines: - yield line - yield cls.postlude - - _inline = lambda text: textwrap.dedent(text).strip().replace('\n', '; ') - prelude = _inline(""" - import sys - sys.__plen = len(sys.path) - """) - postlude = _inline(""" - import sys - new = sys.path[sys.__plen:] - del sys.path[sys.__plen:] - p = getattr(sys, '__egginsert', 0) - sys.path[p:p] = new - sys.__egginsert = p + len(new) - """) + @staticmethod + def _wrap_lines(lines): + return lines def add(self, dist): """Add `dist` to the distribution map""" @@ -1605,6 +1588,33 @@ class PthDistributions(Environment): return path +class RewritePthDistributions(PthDistributions): + + @classmethod + def _wrap_lines(cls, lines): + yield cls.prelude + for line in lines: + yield line + yield cls.postlude + + _inline = lambda text: textwrap.dedent(text).strip().replace('\n', '; ') + prelude = _inline(""" + import sys + sys.__plen = len(sys.path) + """) + postlude = _inline(""" + import sys + new = sys.path[sys.__plen:] + del sys.path[sys.__plen:] + p = getattr(sys, '__egginsert', 0) + sys.path[p:p] = new + sys.__egginsert = p + len(new) + """) + + +PthDistributions = RewritePthDistributions + + def _first_line_re(): """ Return a regular expression based on first_line_re suitable for matching -- cgit v1.2.1 From b0b9dae622b4bcebf96555753d1310319a90bbbe Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 19 Aug 2015 20:47:45 +0100 Subject: Allow disabling of the sys.path rewrite technique using an environment variable. --- CHANGES.txt | 15 +++++++++++++++ setuptools/command/easy_install.py | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 10027a90..2ad565bc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,21 @@ CHANGES ======= +---- +18.3 +---- + +* Setuptools now allows disabling of the manipulation of the sys.path + during the processing of the easy-install.pth file. To do so, set + the environment variable ``SETUPTOOLS_SYS_PATH_TECHNIQUE`` to + anything but "rewrite" (consider "raw"). During any install operation + with manipulation disabled, setuptools packages will be appended to + sys.path naturally. + + Future versions may change the default behavior to disable + manipulation. If so, the default behavior can be retained by setting + the variable to "rewrite". + ---- 18.2 ---- diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 2b639c1b..7c0dfa99 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1612,7 +1612,8 @@ class RewritePthDistributions(PthDistributions): """) -PthDistributions = RewritePthDistributions +if os.environ.get('SETUPTOOLS_SYS_PATH_TECHNIQUE', 'rewrite') == 'rewrite': + PthDistributions = RewritePthDistributions def _first_line_re(): -- cgit v1.2.1 From e5c83ccacb4e61147cb75f4edbe15d68b304b1c5 Mon Sep 17 00:00:00 2001 From: grizzlynyo Date: Sat, 29 Aug 2015 17:29:49 +0300 Subject: update dependency links --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index afaf9f61..4a487924 100755 --- a/setup.py +++ b/setup.py @@ -151,10 +151,10 @@ setup_params = dict( """).strip().splitlines(), extras_require={ "ssl:sys_platform=='win32'": "wincertstore==0.2", - "certs": "certifi==1.0.1", + "certs": "certifi==2015.04.28", }, dependency_links=[ - 'https://pypi.python.org/packages/source/c/certifi/certifi-1.0.1.tar.gz#md5=45f5cb94b8af9e1df0f9450a8f61b790', + 'https://pypi.python.org/packages/source/c/certifi/certifi-2015.04.28.tar.gz#md5=12c7c3a063b2ff97a0f8291d8de41e8c', 'https://pypi.python.org/packages/source/w/wincertstore/wincertstore-0.2.zip#md5=ae728f2f007185648d0c7a8679b361e2', ], scripts=[], -- cgit v1.2.1 From 4e854d1e6ffd5ee1adffd8750589b0a16517d67c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 30 Aug 2015 11:12:58 -0400 Subject: Allow dict.update to do the iteration --- setuptools/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 2c492446..f1798328 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -124,9 +124,8 @@ class Command(_Command): def __init__(self, dist, **kw): # Add support for keyword arguments - _Command.__init__(self,dist) - for k,v in kw.items(): - setattr(self,k,v) + _Command.__init__(self, dist) + vars(self).update(kw) def reinitialize_command(self, command, reinit_subcommands=0, **kw): cmd = _Command.reinitialize_command(self, command, reinit_subcommands) -- cgit v1.2.1 From af9943a4906a808c8d7c2b5004ba48f32400f1d3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 30 Aug 2015 11:14:45 -0400 Subject: Replace comment with docstring. Fixes #423 --- setuptools/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index f1798328..1f421da4 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -123,7 +123,10 @@ class Command(_Command): command_consumes_arguments = False def __init__(self, dist, **kw): - # Add support for keyword arguments + """ + Construct the command for dist, updating + vars(self) with any keyword parameters. + """ _Command.__init__(self, dist) vars(self).update(kw) -- cgit v1.2.1 From 028ae1a595c08c581fff6ff52883d2719d8f8160 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 30 Aug 2015 11:15:46 -0400 Subject: Allow dict.update to do the iteration --- setuptools/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 1f421da4..9e76ae11 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -132,8 +132,7 @@ class Command(_Command): def reinitialize_command(self, command, reinit_subcommands=0, **kw): cmd = _Command.reinitialize_command(self, command, reinit_subcommands) - for k,v in kw.items(): - setattr(cmd,k,v) # update command with keywords + vars(cmd).update(kw) return cmd distutils.core.Command = Command # we can't patch distutils.cmd, alas -- cgit v1.2.1 From 29b422607f3083b9ffebba57fc255f45a20353f3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 30 Aug 2015 11:16:34 -0400 Subject: Prefer preceding line comments --- setuptools/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 9e76ae11..9bbc06bb 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -135,7 +135,8 @@ class Command(_Command): vars(cmd).update(kw) return cmd -distutils.core.Command = Command # we can't patch distutils.cmd, alas +# we can't patch distutils.cmd, alas +distutils.core.Command = Command def findall(dir = os.curdir): """Find all files under 'dir' and return the list of full filenames @@ -150,4 +151,5 @@ def findall(dir = os.curdir): all_files.extend(filter(os.path.isfile, files)) return all_files -distutils.filelist.findall = findall # fix findall bug in distutils. +# fix findall bug in distutils. +distutils.filelist.findall = findall -- cgit v1.2.1 From e8ffa23f83d13de6ef3e4fe61b5e481c5e6c1d5b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 30 Aug 2015 11:34:32 -0400 Subject: Add reference to bug report --- setuptools/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 9bbc06bb..39dd60c6 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -151,5 +151,5 @@ def findall(dir = os.curdir): all_files.extend(filter(os.path.isfile, files)) return all_files -# fix findall bug in distutils. +# fix findall bug in distutils (http://bugs.python.org/issue12885) distutils.filelist.findall = findall -- cgit v1.2.1 From c05680c5d1b4f0a688a4e560fabde6aa3022596d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 30 Aug 2015 13:53:14 -0400 Subject: Replace initialize/inject loop with a list comprehension --- setuptools/__init__.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 39dd60c6..a884d2d3 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -1,6 +1,7 @@ """Extensions to the 'distutils' for large or complex distributions""" import os +import functools import distutils.core import distutils.filelist from distutils.core import Command as _Command @@ -138,18 +139,24 @@ class Command(_Command): # we can't patch distutils.cmd, alas distutils.core.Command = Command -def findall(dir = os.curdir): +def findall(dir=os.curdir): """Find all files under 'dir' and return the list of full filenames (relative to 'dir'). """ - all_files = [] - 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: - files = [os.path.join(base, f) for f in files] - all_files.extend(filter(os.path.isfile, files)) - return all_files + def _strip_leading_curdir(base): + do_strip = base == os.curdir or base.startswith(os.curdir + os.sep) + return base[2:] if do_strip else base + + def _base_prepend(base): + base = _strip_leading_curdir(base) + return functools.partial(os.path.join, base) + + return [ + file + for base, dirs, files in os.walk(dir, followlinks=True) + for file in map(_base_prepend(base), files) + if os.path.isfile(file) + ] # fix findall bug in distutils (http://bugs.python.org/issue12885) distutils.filelist.findall = findall -- cgit v1.2.1 From 8496cfb24aa20109e64a3b03c972792cd911c086 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 30 Aug 2015 13:56:54 -0400 Subject: Use relpath to produce results relative to 'dir' --- setuptools/__init__.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index a884d2d3..0d1994dc 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -143,18 +143,13 @@ def findall(dir=os.curdir): """Find all files under 'dir' and return the list of full filenames (relative to 'dir'). """ - def _strip_leading_curdir(base): - do_strip = base == os.curdir or base.startswith(os.curdir + os.sep) - return base[2:] if do_strip else base - - def _base_prepend(base): - base = _strip_leading_curdir(base) - return functools.partial(os.path.join, base) + def _prepend(base): + return functools.partial(os.path.join, os.path.relpath(base, dir)) return [ file for base, dirs, files in os.walk(dir, followlinks=True) - for file in map(_base_prepend(base), files) + for file in map(_prepend(base), files) if os.path.isfile(file) ] -- cgit v1.2.1 From 56afdde1131d3d67360c4032a518b59007255579 Mon Sep 17 00:00:00 2001 From: Ankur Dedania Date: Mon, 31 Aug 2015 20:10:01 +0000 Subject: Adds #257, pip style version --HG-- branch : AbsoluteMSTR/adds-257-pip-style-version-1441051798003 --- setuptools/command/easy_install.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 7c0dfa99..62c24d77 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -217,7 +217,9 @@ class easy_install(Command): def finalize_options(self): if self.version: - print('setuptools %s' % get_distribution('setuptools').version) + dist = get_distribution('setuptools') + print('setuptools %s from %s (python %s)' % ( + dist.version, dist.location, sys.version[:3])) sys.exit() py_version = sys.version.split()[0] -- cgit v1.2.1 From e2e71004c87d3afa3dc8692739b477d2d70aa2e6 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Tue, 1 Sep 2015 14:59:18 -0400 Subject: Look deeper at .egg-info files for package name and version information when available. --- pkg_resources/__init__.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index d09e0b6f..938f4818 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2466,6 +2466,13 @@ def _remove_md5_fragment(location): return location +def _version_from_file(fid): + for line in fid: + if line.lower().startswith('version:'): + version = safe_version(line.split(':', 1)[1].strip()) + return version + + class Distribution(object): """Wrap an actual or potential sys.path entry w/metadata""" PKG_INFO = 'PKG-INFO' @@ -2483,7 +2490,7 @@ class Distribution(object): self._provider = metadata or empty_provider @classmethod - def from_location(cls, location, basename, metadata=None,**kw): + def from_location(cls, location, basename, metadata=None, **kw): project_name, version, py_version, platform = [None]*4 basename, ext = os.path.splitext(basename) if ext.lower() in _distributionImpl: @@ -2491,9 +2498,25 @@ class Distribution(object): match = EGG_NAME(basename) if match: project_name, version, py_version, platform = match.group( - 'name','ver','pyver','plat' + 'name', 'ver', 'pyver', 'plat' ) cls = _distributionImpl[ext.lower()] + + # Some packages e.g. numpy and scipy use distutils instead of + # setuptools, and their version numbers can get mangled when + # converted to filenames (e.g., 1.11.0.dev0+2329eae to + # 1.11.0.dev0_2329eae). These will not be parsed properly + # downstream by Distribution and safe_version, so we need to + # take an extra step and try to get the version number from + # the file itself instead of the filename. + if ext == '.egg-info': + full_name = os.path.join(location, basename + ext) + try: + with open(full_name, 'r') as fid: + version_ = _version_from_file(fid) + version = version_ if version_ is not None else version + except IOError: + pass return cls( location, metadata, project_name=project_name, version=version, py_version=py_version, platform=platform, **kw @@ -2584,13 +2607,11 @@ class Distribution(object): try: return self._version except AttributeError: - for line in self._get_metadata(self.PKG_INFO): - if line.lower().startswith('version:'): - self._version = safe_version(line.split(':',1)[1].strip()) - return self._version - else: + version = _version_from_file(self._get_metadata(self.PKG_INFO)) + if version is None: tmpl = "Missing 'Version:' header and/or %s file" raise ValueError(tmpl % self.PKG_INFO, self) + return version @property def _dep_map(self): -- cgit v1.2.1 From 7f8157b378c7e03ef332a59b63c08b375876b976 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 3 Sep 2015 09:46:44 -0400 Subject: Setuptools supports Python 3.5 and 3.6 --- setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.py b/setup.py index 4a487924..1a425747 100755 --- a/setup.py +++ b/setup.py @@ -144,6 +144,8 @@ setup_params = dict( Programming Language :: Python :: 3.2 Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.4 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 Topic :: Software Development :: Libraries :: Python Modules Topic :: System :: Archiving :: Packaging Topic :: System :: Systems Administration -- cgit v1.2.1 From 41ec7a69440cf0dd489c57c015521503d797636e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 5 Sep 2015 13:20:48 -0400 Subject: Update python3 docs to indicate that 2to3 is mildly deprecated, and removing legacy details. --- docs/python3.txt | 74 +++++++++++++++++--------------------------------------- 1 file changed, 22 insertions(+), 52 deletions(-) diff --git a/docs/python3.txt b/docs/python3.txt index df173000..d550cb68 100644 --- a/docs/python3.txt +++ b/docs/python3.txt @@ -5,16 +5,22 @@ Supporting both Python 2 and Python 3 with Setuptools Starting with Distribute version 0.6.2 and Setuptools 0.7, the Setuptools project supported Python 3. Installing and using setuptools for Python 3 code works exactly the same as for Python 2 -code, but Setuptools also helps you to support Python 2 and Python 3 from -the same source code by letting you run 2to3 on the code as a part of the -build process, by setting the keyword parameter ``use_2to3`` to True. +code. +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 `_, +`future `_, or another compatibility +library. -Setuptools as help during porting -================================= -Setuptools can make the porting process much easier by automatically running -2to3 as a part of the test running. To do this you need to configure the +Using 2to3 +========== + +Setuptools attempts to make the porting process easier by automatically +running +2to3 as a part of running tests. To do so, you need to configure the setup.py so that you can run the unit tests with ``python setup.py test``. See :ref:`test` for more information on this. @@ -37,23 +43,23 @@ to a list of names of packages containing fixers. To exclude fixers, the parameter ``use_2to3_exclude_fixers`` can be set to fixer names to be skipped. -A typical setup.py can look something like this:: +An example setup.py might look something like this:: from setuptools import setup setup( name='your.module', - version = '1.0', + version='1.0', description='This is your awesome module', author='You', author_email='your@email', - package_dir = {'': 'src'}, - packages = ['your', 'you.module'], - test_suite = 'your.module.tests', - use_2to3 = True, - convert_2to3_doctests = ['src/your/module/README.txt'], - use_2to3_fixers = ['your.fixers'], - use_2to3_exclude_fixers = ['lib2to3.fixes.fix_import'], + package_dir={'': 'src'}, + packages=['your', 'you.module'], + test_suite='your.module.tests', + use_2to3=True, + convert_2to3_doctests=['src/your/module/README.txt'], + use_2to3_fixers=['your.fixers'], + use_2to3_exclude_fixers=['lib2to3.fixes.fix_import'], ) Differential conversion @@ -86,39 +92,3 @@ Advanced features If you don't want to run the 2to3 conversion on the doctests in Python files, you can turn that off by setting ``setuptools.use_2to3_on_doctests = False``. - -Note on compatibility with older versions of setuptools -======================================================= - -Setuptools earlier than 0.7 does not know about the new keyword parameters to -support Python 3. -As a result it will warn about the unknown keyword parameters if you use -those versions of setuptools instead of Distribute under Python 2. This output -is not an error, and -install process will continue as normal, but if you want to get rid of that -error this is easy. Simply conditionally add the new parameters into an extra -dict and pass that dict into setup():: - - from setuptools import setup - import sys - - extra = {} - if sys.version_info >= (3,): - extra['use_2to3'] = True - extra['convert_2to3_doctests'] = ['src/your/module/README.txt'] - extra['use_2to3_fixers'] = ['your.fixers'] - - setup( - name='your.module', - version = '1.0', - description='This is your awesome module', - author='You', - author_email='your@email', - package_dir = {'': 'src'}, - packages = ['your', 'you.module'], - test_suite = 'your.module.tests', - **extra - ) - -This way the parameters will only be used under Python 3, where Distribute or -Setuptools 0.7 or later is required. -- cgit v1.2.1 From 0f3521f227793e2707b682d23f5cce36983e07a1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 5 Sep 2015 13:28:01 -0400 Subject: Remove documentation on merge, now relevant only for posterity (reference in the source tree). --- docs/index.txt | 1 - docs/merge-faq.txt | 80 ----------------------------------- docs/merge.txt | 122 ----------------------------------------------------- 3 files changed, 203 deletions(-) delete mode 100644 docs/merge-faq.txt delete mode 100644 docs/merge.txt diff --git a/docs/index.txt b/docs/index.txt index 529f08f3..6ac37252 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -23,4 +23,3 @@ Documentation content: easy_install pkg_resources development - merge diff --git a/docs/merge-faq.txt b/docs/merge-faq.txt deleted file mode 100644 index ea45f30c..00000000 --- a/docs/merge-faq.txt +++ /dev/null @@ -1,80 +0,0 @@ -Setuptools/Distribute Merge FAQ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -How do I upgrade from Distribute? -================================= - -Distribute specifically prohibits installation of Setuptools 0.7 from Distribute 0.6. There are then two options for upgrading. - -Note that after upgrading using either technique, the only option to downgrade to either version is to completely uninstall Distribute and Setuptools 0.7 versions before reinstalling an 0.6 release. - -Use Distribute 0.7 ------------------- - -The PYPA has put together a compatibility wrapper, a new release of Distribute version 0.7. This package will install over Distribute 0.6.x installations and will replace Distribute with a simple wrapper that requires Setuptools 0.7 or later. This technique is experimental, but initial results indicate this technique is the easiest upgrade path. - - -Uninstall ---------- - -First, completely uninstall Distribute. Since Distribute does not have an automated installation routine, this process is manual. Follow the instructions in the README for uninstalling. - - -How do I upgrade from Setuptools 0.6? -===================================== - -There are no special instructions for upgrading over older versions of Setuptools. Simply use `easy_install -U` or run the latest `ez_setup.py`. - -Where does the merge occur? -======================================================== - -The merge is occurring between the heads of the default branch of Distribute and the setuptools-0.6 branch of Setuptools. The Setuptools SVN repo has been converted to a Mercurial repo hosted on Bitbucket. The work is still underway, so the exact changesets included may change, although the anticipated merge targets are Setuptools at 0.6c12 and Distribute at 0.6.35. - -What happens to other branches? -======================================================== - -Distribute 0.7 was abandoned long ago and won't be included in the resulting code tree, but may be retained for posterity in the original repo. - -Setuptools default branch (also 0.7 development) may also be abandoned or may be incorporated into the new merged line if desirable (and as resources allow). - -What history is lost/changed? -======================================================== - -As setuptools was not on Mercurial when the fork occurred and as Distribute did not include the full setuptools history (prior to the creation of the setuptools-0.6 branch), the two source trees were not compatible. In order to most effectively communicate the code history, the Distribute code was grafted onto the (originally private) setuptools Mercurial repo. Although this grafting maintained the full code history with names, dates, and changes, it did lose the original hashes of those changes. Therefore, references to changes by hash (including tags) are lost. - -Additionally, any heads that were not actively merged into the Distribute 0.6.35 release were also omitted. As a result, the changesets included in the merge repo are those from the original setuptools repo and all changesets ancestral to the Distribute 0.6.35 release. - -What features will be in the merged code base? -======================================================== - -In general, all "features" added in distribute will be included in setuptools. Where there exist conflicts or undesirable features, we will be explicit about what these limitations are. Changes that are backward-incompatible from setuptools 0.6 to distribute will likely be removed, and these also will be well documented. - -Bootstrapping scripts (ez_setup/distribute_setup) and docs, as with distribute, will be maintained in the repository and built as part of the release process. Documentation and bootstrapping scripts will be hosted at python.org, as they are with distribute now. Documentation at telecommunity will be updated to refer or redirect to the new, merged docs. - -On the whole, the merged setuptools should be largely compatible with the latest releases of both setuptools and distribute and will be an easy transition for users of either library. - -Who is invited to contribute? Who is excluded? -======================================================== - -While we've worked privately to initiate this merge due to the potential sensitivity of the topic, no one is excluded from this effort. We invite all members of the community, especially those most familiar with Python packaging and its challenges to join us in the effort. - -We have lots of ideas for how we'd like to improve the codebase, release process, everything. Like distribute, the post-merge setuptools will have its source hosted on Bitbucket. (So if you're currently a distribute contributor, about the only thing that's going to change is the URL of the repository you follow.) Also like distribute, it'll support Python 3, and hopefully we'll soon merge Vinay Sajip's patches to make it run on Python 3 without needing 2to3 to be run on the code first. - -While we've worked privately to initiate this merge due to the potential sensitivity of the topic, no one is excluded from this effort. We invite all members of the community, especially those most familiar with Python packaging and its challenges to join us in the effort. - -Why Setuptools and not Distribute or another name? -======================================================== - -We do, however, understand that this announcement might be unsettling for some. The setuptools name has been subjected to a lot of deprecation in recent years, so the idea that it will now be the preferred name instead of distribute might be somewhat difficult or disorienting for some. We considered use of another name (Distribute or an entirely new name), but that would serve to only complicate matters further. Instead, our goal is to simplify the packaging landscape but without losing any hard-won advancements. We hope that the people who worked to spread the first message will be equally enthusiastic about spreading the new one, and we especially look forward to seeing the new posters and slogans celebrating setuptools. - -What is the timeframe of release? -======================================================== - -There are no hard timeframes for any of this effort, although progress is underway and a draft merge is underway and being tested privately. As an unfunded volunteer effort, our time to put in on it is limited, and we've both had some recent health and other challenges that have made working on this difficult, which in part explains why we haven't met our original deadline of a completed merge before PyCon. - -The final Setuptools 0.7 was cut on June 1, 2013 and will be released to PyPI shortly thereafter. - -What version number can I expect for the new release? -======================================================== - -The new release will roughly follow the previous trend for setuptools and release the new release as 0.7. This number is somewhat arbitrary, but we wanted something other than 0.6 to distinguish it from its ancestor forks but not 1.0 to avoid putting too much emphasis on the release itself and to focus on merging the functionality. In the future, the project will likely adopt a versioning scheme similar to semver to convey semantic meaning about the release in the version number. diff --git a/docs/merge.txt b/docs/merge.txt deleted file mode 100644 index ba37d6e4..00000000 --- a/docs/merge.txt +++ /dev/null @@ -1,122 +0,0 @@ -Merge with Distribute -~~~~~~~~~~~~~~~~~~~~~ - -In 2013, the fork of Distribute was merged back into Setuptools. This -document describes some of the details of the merge. - -.. toctree:: - :maxdepth: 2 - - merge-faq - -Process -======= - -In order to try to accurately reflect the fork and then re-merge of the -projects, the merge process brought both code trees together into one -repository and grafted the Distribute fork onto the Setuptools development -line (as if it had been created as a branch in the first place). - -The rebase to get distribute onto setuptools went something like this:: - - hg phase -d -f -r 26b4c29b62db - hg rebase -s 26b4c29b62db -d 7a5cf59c78d7 - -The technique required a late version of mercurial (2.5) to work correctly. - -The only code that was included was the code that was ancestral to the public -releases of Distribute 0.6. Additionally, because Setuptools was not hosted -on Mercurial at the time of the fork and because the Distribute fork did not -include a complete conversion of the Setuptools history, the Distribute -changesets had to be re-applied to a new, different conversion of the -Setuptools SVN repository. As a result, all of the hashes have changed. - -Distribute was grafted in a 'distribute' branch and the 'setuptools-0.6' -branch was targeted for the merge. The 'setuptools' branch remains with -unreleased code and may be incorporated in the future. - -Reconciling Differences -======================= - -There were both technical and philosophical differences between Setuptools -and Distribute. To reconcile these differences in a manageable way, the -following technique was undertaken: - -Create a 'Setuptools-Distribute merge' branch, based on a late release of -Distribute (0.6.35). This was done with a00b441856c4. - -In that branch, first remove code that is no longer relevant to -Setuptools (such as the setuptools patching code). - -Next, in the the merge branch, create another base from at the point where the -fork occurred (such that the code is still essentially an older but pristine -setuptools). This base can be found as 955792b069d0. This creates two heads -in the merge branch, each with a basis in the fork. - -Then, repeatedly copy changes for a -single file or small group of files from a late revision of that file in the -'setuptools-0.6' branch (1aae1efe5733 was used) and commit those changes on -the setuptools-only head. That head is then merged with the head with -Distribute changes. It is in this Mercurial -merge operation that the fundamental differences between Distribute and -Setuptools are reconciled, but since only a single file or small set of files -are used, the scope is limited. - -Finally, once all the challenging files have been reconciled and merged, the -remaining changes from the setuptools-0.6 branch are merged, deferring to the -reconciled changes (a1fa855a5a62 and 160ccaa46be0). - -Originally, jaraco attempted all of this using anonymous heads in the -Distribute branch, but later realized this technique made for a somewhat -unclear merge process, so the changes were re-committed as described above -for clarity. In this way, the "distribute" and "setuptools" branches can -continue to track the official Distribute changesets. - -Concessions -=========== - -With the merge of Setuptools and Distribute, the following concessions were -made: - -Differences from setuptools 0.6c12: - -Major Changes -------------- - -* Python 3 support. -* Improved support for GAE. -* Support `PEP-370 `_ per-user site - packages. -* Sort order of Distributions in pkg_resources now prefers PyPI to external - links (Distribute issue 163). -* Python 2.4 or greater is required (drop support for Python 2.3). - -Minor Changes -------------- - -* Wording of some output has changed to replace contractions with their - canonical form (i.e. prefer "could not" to "couldn't"). -* Manifest files are only written for 32-bit .exe launchers. - -Differences from Distribute 0.6.36: - -Major Changes -------------- - -* The _distribute property of the setuptools module has been removed. -* Distributions are once again installed as zipped eggs by default, per the - rationale given in `the seminal bug report - `_ indicates that the feature - should remain and no substantial justification was given in the `Distribute - report `_. - -Minor Changes -------------- - -* The patch for `#174 `_ - has been rolled-back, as the comment on the ticket indicates that the patch - addressed a symptom and not the fundamental issue. -* ``easy_install`` (the command) once again honors setup.cfg if found in the - current directory. The "mis-behavior" characterized in `#99 - `_ is actually intended - behavior, and no substantial rationale was given for the deviation. -- cgit v1.2.1 From ceb604c40ef9d095942952e7bb535bf8dd3295ed Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 5 Sep 2015 13:36:04 -0400 Subject: Update documentation to reflect no integrated SCM support. --- docs/setuptools.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/setuptools.txt b/docs/setuptools.txt index 0feb09ea..0646eff5 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -2595,8 +2595,8 @@ those methods' docstrings for more details. Adding Support for Other Revision Control Systems ------------------------------------------------- -If you would like to create a plugin for ``setuptools`` to find files in other -source control systems besides CVS and Subversion, you can do so by adding an +If you would like to create a plugin for ``setuptools`` to find files in +source control systems, you can do so by adding an entry point to the ``setuptools.file_finders`` group. The entry point should be a function accepting a single directory name, and should yield all the filenames within that directory (and any subdirectories thereof) that -- cgit v1.2.1 From 5fcd56e4962e04ba01c278f492f4a95e581d5882 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 5 Sep 2015 13:37:35 -0400 Subject: Remove cruft from Subclassing section --- docs/setuptools.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/setuptools.txt b/docs/setuptools.txt index 0646eff5..e2753cba 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -2652,9 +2652,7 @@ Subclassing ``Command`` ----------------------- Sorry, this section isn't written yet, and neither is a lot of what's below -this point, except for the change log. You might want to `subscribe to changes -in this page `_ to see when new documentation is -added or updated. +this point. XXX -- cgit v1.2.1 From abf566993bb10869d6003279bff292e0e5044120 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Sep 2015 13:30:29 -0400 Subject: Update changelog --- CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 2ad565bc..bce05c5e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -17,6 +17,9 @@ CHANGES manipulation. If so, the default behavior can be retained by setting the variable to "rewrite". +* Issue #257: ``easy_install --version`` now shows more detail + about the installation location and Python version. + ---- 18.2 ---- -- cgit v1.2.1 From bbb481088c030bed9c837068d0a3b956c2e26446 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Sep 2015 13:45:21 -0400 Subject: Extract version handling as a separate method --- setuptools/command/easy_install.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 62c24d77..45d180bb 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -215,12 +215,19 @@ class easy_install(Command): remover = rmtree if is_tree else os.unlink remover(path) + @staticmethod + def _render_version(): + """ + Render the Setuptools version and installation details, then exit. + """ + ver = sys.version[:3] + dist = get_distribution('setuptools') + tmpl = 'setuptools {dist.version} from {dist.location} (Python {ver})' + print(tmpl.format(**locals())) + raise SystemExit() + def finalize_options(self): - if self.version: - dist = get_distribution('setuptools') - print('setuptools %s from %s (python %s)' % ( - dist.version, dist.location, sys.version[:3])) - sys.exit() + self.version and self._render_version() py_version = sys.version.split()[0] prefix, exec_prefix = get_config_vars('prefix', 'exec_prefix') -- cgit v1.2.1 From 421db46870409b6b0cf797dac8869fddc8156191 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Sep 2015 13:59:27 -0400 Subject: Python 3.6 isn't yet a thing, apparently. --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 1a425747..2b367a6d 100755 --- a/setup.py +++ b/setup.py @@ -145,7 +145,6 @@ setup_params = dict( Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 - Programming Language :: Python :: 3.6 Topic :: Software Development :: Libraries :: Python Modules Topic :: System :: Archiving :: Packaging Topic :: System :: Systems Administration -- cgit v1.2.1 From aba8a0c034fb9a0917d5a7d3508c87a800666718 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Sep 2015 14:02:32 -0400 Subject: Added tag 18.3 for changeset b59320212c83 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 447b5cdb..40769986 100644 --- a/.hgtags +++ b/.hgtags @@ -218,3 +218,4 @@ fac98a49bd984ef5accf7177674d693277bfbaef 18.0b1 e364795c1b09c70b6abb53770e09763b52bf807d 18.0.1 c0395f556c35d8311fdfe2bda6846b91149819cd 18.1 1a981f2e5031f55267dc2a28fa1b42274a1b64b2 18.2 +b59320212c8371d0be9e5e6c5f7eec392124c009 18.3 -- cgit v1.2.1 From c8364b9cf2eeccf684777e53ae4abad2e4fc30b3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Sep 2015 14:06:13 -0400 Subject: Bumped to 18.4 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index a13ce156..53988038 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.3" +DEFAULT_VERSION = "18.4" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 861921f0..0cf7321a 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.3' +__version__ = '18.4' -- cgit v1.2.1 From 9366bb0996cd7c8d3f77ee45f84ddd77f7ded8b7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Sep 2015 22:30:23 -0400 Subject: Add tests capturing expected behavior, including failure to match expectation indicated in docstring. --- setuptools/tests/test_setuptools.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 setuptools/tests/test_setuptools.py diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py new file mode 100644 index 00000000..f6bec644 --- /dev/null +++ b/setuptools/tests/test_setuptools.py @@ -0,0 +1,24 @@ +import pytest + +import setuptools + + +@pytest.fixture +def example_source(tmpdir): + tmpdir.mkdir('foo') + (tmpdir / 'foo/bar.py').write('') + (tmpdir / 'readme.txt').write('') + return tmpdir + + +def test_findall(example_source): + found = list(setuptools.findall(str(example_source))) + expected = ['readme.txt', 'foo/bar.py'] + assert found == expected + + +def test_findall_curdir(example_source): + with example_source.as_cwd(): + found = list(setuptools.findall()) + expected = ['readme.txt', 'foo/bar.py'] + assert found == expected -- cgit v1.2.1 From 3c0d3a91f64a9174f6e3473bbcea3be42045004a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Sep 2015 22:35:48 -0400 Subject: Update docstring and test to match long-standing expectation in behavior. --- setuptools/__init__.py | 5 +++-- setuptools/tests/test_setuptools.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 2c492446..63ee15ed 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -137,8 +137,9 @@ class Command(_Command): distutils.core.Command = Command # we can't patch distutils.cmd, alas def findall(dir = os.curdir): - """Find all files under 'dir' and return the list of full filenames - (relative to 'dir'). + """ + Find all files under 'dir' and return the list of full filenames. + Unless dir is '.', return full filenames with dir prepended. """ all_files = [] for base, dirs, files in os.walk(dir, followlinks=True): diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py index f6bec644..e1a06c96 100644 --- a/setuptools/tests/test_setuptools.py +++ b/setuptools/tests/test_setuptools.py @@ -14,6 +14,7 @@ def example_source(tmpdir): def test_findall(example_source): found = list(setuptools.findall(str(example_source))) expected = ['readme.txt', 'foo/bar.py'] + expected = [example_source.join(fn) for fn in expected] assert found == expected -- cgit v1.2.1 From 32a47417750420524e1270cc5e3fc749eb9e5a89 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Sep 2015 22:58:47 -0400 Subject: Restore old behavior for calculating the base. Fixes failing test and fixes #425. --- setuptools/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index e9390336..49002619 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -145,7 +145,9 @@ def findall(dir=os.curdir): Unless dir is '.', return full filenames with dir prepended. """ def _prepend(base): - return functools.partial(os.path.join, os.path.relpath(base, dir)) + if base == os.curdir or base.startswith(os.curdir + os.sep): + base = base[2:] + return functools.partial(os.path.join, base) return [ file -- cgit v1.2.1 From 38a40150670a18742a85435ed2baba422c002a68 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 7 Sep 2015 01:16:14 -0400 Subject: Another refactor of findall, this time separating the simple walk / join operation from the conditional relative path. --- setuptools/__init__.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 49002619..a7d75ed4 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -139,22 +139,29 @@ class Command(_Command): # we can't patch distutils.cmd, alas distutils.core.Command = Command + +def _find_all_simple(path): + """ + Find all files under 'path' + """ + return ( + os.path.join(base, file) + for base, dirs, files in os.walk(path, followlinks=True) + for file in files + ) + + def findall(dir=os.curdir): """ Find all files under 'dir' and return the list of full filenames. Unless dir is '.', return full filenames with dir prepended. """ - def _prepend(base): - if base == os.curdir or base.startswith(os.curdir + os.sep): - base = base[2:] - return functools.partial(os.path.join, base) - - return [ - file - for base, dirs, files in os.walk(dir, followlinks=True) - for file in map(_prepend(base), files) - if os.path.isfile(file) - ] + files = _find_all_simple(dir) + if dir == os.curdir: + make_rel = functools.partial(os.path.relpath, start=dir) + files = map(make_rel, files) + return list(files) + # fix findall bug in distutils (http://bugs.python.org/issue12885) distutils.filelist.findall = findall -- cgit v1.2.1 From a56aee24962dea7f9d8b46fbedb79fec988ee246 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 7 Sep 2015 02:23:09 -0400 Subject: Update changelog --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index bce05c5e..4700f067 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,12 @@ CHANGES ======= +------ +18.3.1 +------ + +* Issue #425: Correct regression in setuptools.findall. + ---- 18.3 ---- -- cgit v1.2.1 From 9aec33a0cf4a3bcd152d3d142946a98530588af4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 7 Sep 2015 02:23:25 -0400 Subject: Bumped to 18.3.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 53988038..15104c59 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.4" +DEFAULT_VERSION = "18.3.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 0cf7321a..12568fa2 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.4' +__version__ = '18.3.1' -- cgit v1.2.1 From eb749460d656527d90322f380730e01362c254d1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 7 Sep 2015 09:15:48 +0200 Subject: Added tag 18.3.1 for changeset 7a705b610abb --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 40769986..e225e369 100644 --- a/.hgtags +++ b/.hgtags @@ -219,3 +219,4 @@ e364795c1b09c70b6abb53770e09763b52bf807d 18.0.1 c0395f556c35d8311fdfe2bda6846b91149819cd 18.1 1a981f2e5031f55267dc2a28fa1b42274a1b64b2 18.2 b59320212c8371d0be9e5e6c5f7eec392124c009 18.3 +7a705b610abb1177ca169311c4ee261f3e4f0957 18.3.1 -- cgit v1.2.1 From 94416707fd59a65f4a8f7f70541d6b3fc018b626 Mon Sep 17 00:00:00 2001 From: Andy Freeland Date: Thu, 10 Sep 2015 01:03:42 -0400 Subject: Add support for python_platform_implementation environment marker This patch adds support for the 'python_platform_implementation' environment marker as defined by PEP-0426: https://www.python.org/dev/peps/pep-0426/#environment-markers --- pkg_resources/__init__.py | 1 + pkg_resources/api_tests.txt | 3 +++ 2 files changed, 4 insertions(+) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 42ddcf7c..639dc4a6 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -1403,6 +1403,7 @@ class MarkerEvaluation(object): 'python_version': lambda: platform.python_version()[:3], 'platform_version': platform.version, 'platform_machine': platform.machine, + 'platform_python_implementation': platform.python_implementation, 'python_implementation': platform.python_implementation, } diff --git a/pkg_resources/api_tests.txt b/pkg_resources/api_tests.txt index 1c852e81..d28db0f5 100644 --- a/pkg_resources/api_tests.txt +++ b/pkg_resources/api_tests.txt @@ -420,3 +420,6 @@ Environment Markers >>> em("python_version > '2.5'") True + + >>> im("platform_python_implementation=='CPython'") + False -- cgit v1.2.1 From 0c984fb56249c3d58cf1be3015e36afab77c184c Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Sun, 13 Sep 2015 18:01:43 +0000 Subject: Add the PyPA Code of Conduct --- README.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.txt b/README.txt index e21c4069..799ad008 100755 --- a/README.txt +++ b/README.txt @@ -223,3 +223,14 @@ Credits the Python Packaging Authority (PyPA) and the larger Python community. .. _files: + + +--------------- +Code of Conduct +--------------- + +Everyone interacting in the setuptools project's codebases, issue trackers, +chat rooms, and mailing lists is expected to follow the +`PyPA Code of Conduct`_. + +.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ -- cgit v1.2.1 From 30a15dcce774cd9ed2a3f09644aea42fb9f1e819 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 19 Sep 2015 18:00:22 +0200 Subject: Add another test capturing issue described in http://bugs.python.org/issue12885 --- setuptools/tests/test_setuptools.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py index f6bec644..83c42e3e 100644 --- a/setuptools/tests/test_setuptools.py +++ b/setuptools/tests/test_setuptools.py @@ -1,3 +1,5 @@ +import os + import pytest import setuptools @@ -22,3 +24,24 @@ def test_findall_curdir(example_source): found = list(setuptools.findall()) expected = ['readme.txt', 'foo/bar.py'] assert found == expected + + +@pytest.fixture +def can_symlink(tmpdir): + """ + Skip if cannot create a symbolic link + """ + link_fn = 'link' + target_fn = 'target' + try: + os.symlink(target_fn, link_fn) + except (OSError, NotImplementedError, AttributeError): + pytest.skip("Cannot create symbolic links") + os.remove(link_fn) + + +def test_findall_missing_symlink(tmpdir, can_symlink): + with tmpdir.as_cwd(): + os.symlink('foo', 'bar') + found = list(setuptools.findall()) + assert found == [] -- cgit v1.2.1 From 22a8ace27c7d7aadfa0fa9311686541a2169092c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 19 Sep 2015 18:07:48 +0200 Subject: Only return results that are files. Fixes failing test and corrects additional regression in 18.3. --- setuptools/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/__init__.py b/setuptools/__init__.py index a7d75ed4..712ec082 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -144,11 +144,12 @@ def _find_all_simple(path): """ Find all files under 'path' """ - return ( + results = ( os.path.join(base, file) for base, dirs, files in os.walk(path, followlinks=True) for file in files ) + return filter(os.path.isfile, results) def findall(dir=os.curdir): -- cgit v1.2.1 From 7e28912d0cfd017577df59c465bf770a8182d232 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 19 Sep 2015 18:26:38 +0200 Subject: Update changelog --- CHANGES.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 4700f067..32dd4486 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +------ +18.3.2 +------ + +* Correct another regression in setuptools.findall + where the fix for Python #12885 was lost. + ------ 18.3.1 ------ @@ -26,6 +33,9 @@ CHANGES * Issue #257: ``easy_install --version`` now shows more detail about the installation location and Python version. +* Refactor setuptools.findall in preparation for re-submission + back to distutils. + ---- 18.2 ---- -- cgit v1.2.1 From ec01ecef42dd6f9813a9beca71dfdb92fb539719 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 19 Sep 2015 18:27:06 +0200 Subject: Bumped to 18.3.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 15104c59..a07dd4d5 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.3.1" +DEFAULT_VERSION = "18.3.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 12568fa2..787141c7 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.3.1' +__version__ = '18.3.2' -- cgit v1.2.1 From 2bec03891c629702face5f7f1cace2e73e6b8fe5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 19 Sep 2015 18:27:10 +0200 Subject: Added tag 18.3.2 for changeset 1e120f04bcaa --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index e225e369..c72034f4 100644 --- a/.hgtags +++ b/.hgtags @@ -220,3 +220,4 @@ c0395f556c35d8311fdfe2bda6846b91149819cd 18.1 1a981f2e5031f55267dc2a28fa1b42274a1b64b2 18.2 b59320212c8371d0be9e5e6c5f7eec392124c009 18.3 7a705b610abb1177ca169311c4ee261f3e4f0957 18.3.1 +1e120f04bcaa2421c4df0eb6678c3019ba4a82f6 18.3.2 -- cgit v1.2.1 From 351f51dcefd0fc260f005d30eb60f23a4fcd3ac1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 19 Sep 2015 18:33:23 +0200 Subject: Bumped to 18.3.3 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index a07dd4d5..2247dd79 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.3.2" +DEFAULT_VERSION = "18.3.3" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 787141c7..79dd2dab 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.3.2' +__version__ = '18.3.3' -- cgit v1.2.1 From 9f5f2ac2aa55dbac1dfe9da6c7a46d82355c75fa Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 27 Sep 2015 07:29:18 -0400 Subject: Simplify implementation of Requirement.parse. --- pkg_resources/__init__.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 42ddcf7c..ce8f2e98 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2983,12 +2983,8 @@ class Requirement: @staticmethod def parse(s): - reqs = list(parse_requirements(s)) - if reqs: - if len(reqs) == 1: - return reqs[0] - raise ValueError("Expected only one requirement", s) - raise ValueError("No requirements found", s) + req, = parse_requirements(s) + return req def _get_mro(cls): -- cgit v1.2.1 From bc3389a6048b23871e50eaab20d8df06ba3ff53d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 27 Sep 2015 07:50:30 -0400 Subject: Extract _requirement_spec method for rendering the requirement specification for scripts. Ref #439. --- setuptools/command/easy_install.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 45d180bb..2faff4c2 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -766,7 +766,7 @@ class easy_install(Command): def install_script(self, dist, script_name, script_text, dev_path=None): """Generate a legacy script wrapper and install it""" - spec = str(dist.as_requirement()) + spec = self._requirement_spec(dist) is_script = is_python_script(script_text, script_name) if is_script: @@ -774,6 +774,10 @@ class easy_install(Command): self._load_template(dev_path) % locals()) self.write_script(script_name, _to_ascii(script_text), 'b') + @staticmethod + def _requirement_spec(dist): + return str(dist.as_requirement()) + @staticmethod def _load_template(dev_path): """ -- cgit v1.2.1 From b9e23adff55624ba2c3527c9f807ec7962b58c5f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 27 Sep 2015 08:07:30 -0400 Subject: Backed out changeset 38b415c244b8 --- setuptools/command/easy_install.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 2faff4c2..45d180bb 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -766,7 +766,7 @@ class easy_install(Command): def install_script(self, dist, script_name, script_text, dev_path=None): """Generate a legacy script wrapper and install it""" - spec = self._requirement_spec(dist) + spec = str(dist.as_requirement()) is_script = is_python_script(script_text, script_name) if is_script: @@ -774,10 +774,6 @@ class easy_install(Command): self._load_template(dev_path) % locals()) self.write_script(script_name, _to_ascii(script_text), 'b') - @staticmethod - def _requirement_spec(dist): - return str(dist.as_requirement()) - @staticmethod def _load_template(dev_path): """ -- cgit v1.2.1 From 0a30d49169f5e73c86f452f284d10ed4b1646ff4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 19:59:20 -0400 Subject: Calculate test_args on demand rather than setting an attribute. --- setuptools/command/test.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 42689f70..a80d91ad 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -72,10 +72,6 @@ class test(Command): "You may specify a module or a suite, but not both" ) - self.test_args = [self.test_suite] - - if self.verbose: - self.test_args.insert(0, '--verbose') if self.test_loader is None: self.test_loader = getattr(self.distribution, 'test_loader', None) if self.test_loader is None: @@ -83,6 +79,11 @@ class test(Command): if self.test_runner is None: self.test_runner = getattr(self.distribution, 'test_runner', None) + @property + def test_args(self): + verbose = ['--verbose'] if self.verbose else [] + return verbose + [self.test_suite] + def with_project_on_sys_path(self, func): with_2to3 = PY3 and getattr(self.distribution, 'use_2to3', False) -- cgit v1.2.1 From a33e201d1a86dd108e8641f641ff24c7f00ba054 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:03:33 -0400 Subject: Move value checking into its own block. --- setuptools/command/test.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index a80d91ad..4d859808 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -62,15 +62,16 @@ class test(Command): def finalize_options(self): + if self.test_suite and self.test_module: + raise DistutilsOptionError( + "You may specify a module or a suite, but not both" + ) + if self.test_suite is None: if self.test_module is None: self.test_suite = self.distribution.test_suite else: self.test_suite = self.test_module + ".test_suite" - elif self.test_module: - raise DistutilsOptionError( - "You may specify a module or a suite, but not both" - ) if self.test_loader is None: self.test_loader = getattr(self.distribution, 'test_loader', None) -- cgit v1.2.1 From 82f3e20506b4e2646880ec7ac5bb6b10e03e8c40 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:03:59 -0400 Subject: Extract variable for nicer indentation --- setuptools/command/test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 4d859808..225f4673 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -63,9 +63,8 @@ class test(Command): def finalize_options(self): if self.test_suite and self.test_module: - raise DistutilsOptionError( - "You may specify a module or a suite, but not both" - ) + msg = "You may specify a module or a suite, but not both" + raise DistutilsOptionError(msg) if self.test_suite is None: if self.test_module is None: -- cgit v1.2.1 From 552ca4d4c712c68c90601ff3f70cf4115b1636ac Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:12:12 -0400 Subject: Resolve test_suite directly rather than referencing test_args --- setuptools/command/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 225f4673..3e9f5f72 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -147,7 +147,7 @@ class test(Command): # re-import them from the build location. Required when 2to3 is used # with namespace packages. if PY3 and getattr(self.distribution, 'use_2to3', False): - module = self.test_args[-1].split('.')[0] + module = self.test_suite.split('.')[0] if module in _namespace_packages: del_modules = [] if module in sys.modules: -- cgit v1.2.1 From 476381578991476afeca2e28a96b51fdbef50c13 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:15:25 -0400 Subject: Just pass 'unittest' as argv[0] - the full path to the file shouldn't be relevant --- setuptools/command/test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 3e9f5f72..5f93d92e 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -1,6 +1,5 @@ from distutils.errors import DistutilsOptionError from unittest import TestLoader -import unittest import sys from pkg_resources import (resource_listdir, resource_exists, normalize_path, @@ -159,7 +158,7 @@ class test(Command): list(map(sys.modules.__delitem__, del_modules)) unittest_main( - None, None, [unittest.__file__] + self.test_args, + None, None, ['unittest'] + self.test_args, testLoader=self._resolve_as_ep(self.test_loader), testRunner=self._resolve_as_ep(self.test_runner), ) -- cgit v1.2.1 From 0f14cd9c52944d924c7d9ac350e4f904b0edb0af Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:16:23 -0400 Subject: Extract _argv property. --- setuptools/command/test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 5f93d92e..549cfb21 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -158,11 +158,15 @@ class test(Command): list(map(sys.modules.__delitem__, del_modules)) unittest_main( - None, None, ['unittest'] + self.test_args, + None, None, self._argv, testLoader=self._resolve_as_ep(self.test_loader), testRunner=self._resolve_as_ep(self.test_runner), ) + @property + def _argv(self): + return ['unittest'] + self.test_args + @staticmethod def _resolve_as_ep(val): """ -- cgit v1.2.1 From 9c9bfb0fc0f1f667bdabf220e939349143e0d9ec Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:17:37 -0400 Subject: Re-use _argv for the announcement --- setuptools/command/test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 549cfb21..75d55bad 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -134,11 +134,11 @@ class test(Command): self.distribution.fetch_build_eggs(self.distribution.tests_require) if self.test_suite: - cmd = ' '.join(self.test_args) + cmd = ' '.join(self._argv) if self.dry_run: - self.announce('skipping "unittest %s" (dry run)' % cmd) + self.announce('skipping "%s" (dry run)' % cmd) else: - self.announce('running "unittest %s"' % cmd) + self.announce('running "%s"' % cmd) self.with_project_on_sys_path(self.run_tests) def run_tests(self): -- cgit v1.2.1 From 8223f2804628034993247add70943888d96d6348 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:38:36 -0400 Subject: Only include test_suite in args if one is specified. Ref #446. --- setuptools/command/test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 75d55bad..11e4a019 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -80,8 +80,13 @@ class test(Command): @property def test_args(self): - verbose = ['--verbose'] if self.verbose else [] - return verbose + [self.test_suite] + return list(self._test_args()) + + def _test_args(self): + if self.verbose: + yield '--verbose' + if self.test_suite: + yield self.test_suite def with_project_on_sys_path(self, func): with_2to3 = PY3 and getattr(self.distribution, 'use_2to3', False) -- cgit v1.2.1 From 5a9aed6e210628d16cd446c163fa50c9841dba34 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:40:47 -0400 Subject: Accept a pattern argument, supplied by later versions of unittest. --- setuptools/command/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 11e4a019..13b8b46b 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -11,7 +11,7 @@ from setuptools.py31compat import unittest_main class ScanningLoader(TestLoader): - def loadTestsFromModule(self, module): + def loadTestsFromModule(self, module, pattern=None): """Return a suite of all tests cases contained in the given module If the module is a package, load tests from all the modules in it. -- cgit v1.2.1 From 34910765fbafb53bec6604b730875d010a863ae2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:41:25 -0400 Subject: Always execute tests, even if no test_suite is supplied. Fixes #446. --- setuptools/command/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 13b8b46b..9c6a8e04 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -138,7 +138,7 @@ class test(Command): if self.distribution.tests_require: self.distribution.fetch_build_eggs(self.distribution.tests_require) - if self.test_suite: + if True: cmd = ' '.join(self._argv) if self.dry_run: self.announce('skipping "%s" (dry run)' % cmd) -- cgit v1.2.1 From 63140936955baeaf8390ddad115af1947787f37f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:41:50 -0400 Subject: Remove unreachable branch. --- setuptools/command/test.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 9c6a8e04..160e21c9 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -138,13 +138,12 @@ class test(Command): if self.distribution.tests_require: self.distribution.fetch_build_eggs(self.distribution.tests_require) - if True: - cmd = ' '.join(self._argv) - if self.dry_run: - self.announce('skipping "%s" (dry run)' % cmd) - else: - self.announce('running "%s"' % cmd) - self.with_project_on_sys_path(self.run_tests) + cmd = ' '.join(self._argv) + if self.dry_run: + self.announce('skipping "%s" (dry run)' % cmd) + else: + self.announce('running "%s"' % cmd) + self.with_project_on_sys_path(self.run_tests) def run_tests(self): # Purge modules under test from sys.modules. The test loader will -- cgit v1.2.1 From d24ca2822867ef944f959ba420a1c4cf47bae859 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 20:43:46 -0400 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 32dd4486..d2007753 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +---- +18.4 +---- + +* Issue #446: Test command now always invokes unittest, even + if no test suite is supplied. + ------ 18.3.2 ------ -- cgit v1.2.1 From cab9d9c40afac011cc7e12989dc387094a4f1285 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 21:04:06 -0400 Subject: Bumped to 18.4 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 2247dd79..53988038 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.3.3" +DEFAULT_VERSION = "18.4" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 79dd2dab..0cf7321a 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.3.3' +__version__ = '18.4' -- cgit v1.2.1 From 23391cf15730456b0e9aad8140cf26f699ecab76 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 21:04:08 -0400 Subject: Added tag 18.4 for changeset 6203335278be --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c72034f4..d7ea9e2e 100644 --- a/.hgtags +++ b/.hgtags @@ -221,3 +221,4 @@ c0395f556c35d8311fdfe2bda6846b91149819cd 18.1 b59320212c8371d0be9e5e6c5f7eec392124c009 18.3 7a705b610abb1177ca169311c4ee261f3e4f0957 18.3.1 1e120f04bcaa2421c4df0eb6678c3019ba4a82f6 18.3.2 +6203335278be7543d31790d9fba55739469a4c6c 18.4 -- cgit v1.2.1 From 513c0d0f73951677f006cb43fcbc2127154ccbe7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 10 Oct 2015 21:05:24 -0400 Subject: Bumped to 18.5 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 53988038..50e0dfc6 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.4" +DEFAULT_VERSION = "18.5" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 0cf7321a..1be1f7ec 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.4' +__version__ = '18.5' -- cgit v1.2.1 From d1b750124e38d63b26a96e8c0921c02de3b0869d Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Mon, 19 Oct 2015 10:56:35 +0100 Subject: Corrected instructions for running tests. The package name from pypi is `pytest`, and running raw `py.test` results in errors. --- docs/developer-guide.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index 27c304e5..87ddf28f 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -94,7 +94,7 @@ The primary tests are run using py.test. To run the tests:: $ python setup.py ptr -Or install py.test into your environment and run ``py.test``. +Or install ``pytest`` into your environment and run ``py.test setuptools``. Under continuous integration, additional tests may be run. See the ``.travis.yml`` file for full details on the tests run under Travis-CI. -- cgit v1.2.1 From bfc525457225a7c0a45553d0fcf29592230e9855 Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Mon, 19 Oct 2015 12:06:08 +0100 Subject: Added test utility for building files quickly. And made use of it in test_egg_info. --- setuptools/tests/files.py | 32 ++++++++++++++++++++++++++++++++ setuptools/tests/test_egg_info.py | 23 ++++++++++++----------- 2 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 setuptools/tests/files.py diff --git a/setuptools/tests/files.py b/setuptools/tests/files.py new file mode 100644 index 00000000..4364241b --- /dev/null +++ b/setuptools/tests/files.py @@ -0,0 +1,32 @@ +import os + + +def build_files(file_defs, prefix=""): + """ + Build a set of files/directories, as described by the file_defs dictionary. + + Each key/value pair in the dictionary is interpreted as a filename/contents + pair. If the contents value is a dictionary, a directory is created, and the + dictionary interpreted as the files within it, recursively. + + For example: + + {"README.txt": "A README file", + "foo": { + "__init__.py": "", + "bar": { + "__init__.py": "", + }, + "baz.py": "# Some code", + } + } + """ + for name, contents in file_defs.items(): + full_name = os.path.join(prefix, name) + if isinstance(contents, dict): + if not os.path.exists(full_name): + os.makedirs(full_name) + build_files(contents, prefix=full_name) + else: + with open(full_name, 'w') as f: + f.write(contents) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index a1caf9fd..8d831107 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -4,6 +4,7 @@ import stat import pytest from . import environment +from .files import build_files from .textwrap import DALS from . import contexts @@ -22,14 +23,13 @@ class TestEggInfo: """) def _create_project(self): - with open('setup.py', 'w') as f: - f.write(self.setup_script) - - with open('hello.py', 'w') as f: - f.write(DALS(""" + build_files({ + 'setup.py': self.setup_script, + 'hello.py': DALS(""" def run(): print('hello') - """)) + """) + }) @pytest.yield_fixture def env(self): @@ -44,13 +44,14 @@ class TestEggInfo: for dirname in subs ) list(map(os.mkdir, env.paths.values())) - config = os.path.join(env.paths['home'], '.pydistutils.cfg') - with open(config, 'w') as f: - f.write(DALS(""" + build_files({ + env.paths['home']: { + '.pydistutils.cfg': DALS(""" [egg_info] egg-base = %(egg-base)s - """ % env.paths - )) + """ % env.paths) + } + }) yield env def test_egg_base_installed_egg_info(self, tmpdir_cwd, env): -- cgit v1.2.1 From 0b9fa15f89c18733d3b17d147a64a72134e0d8a3 Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Mon, 19 Oct 2015 11:49:29 +0100 Subject: Pulled out some test code for re-use. --- setuptools/tests/test_egg_info.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 8d831107..4977ea01 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -57,6 +57,20 @@ class TestEggInfo: def test_egg_base_installed_egg_info(self, tmpdir_cwd, env): self._create_project() + self._run_install_command(tmpdir_cwd, env) + actual = self._find_egg_info_files(env.paths['lib']) + + expected = [ + 'PKG-INFO', + 'SOURCES.txt', + 'dependency_links.txt', + 'entry_points.txt', + 'not-zip-safe', + 'top_level.txt', + ] + assert sorted(actual) == expected + + def _run_install_command(self, tmpdir_cwd, env): environ = os.environ.copy().update( HOME=env.paths['home'], ) @@ -76,18 +90,6 @@ class TestEggInfo: if code: raise AssertionError(data) - actual = self._find_egg_info_files(env.paths['lib']) - - expected = [ - 'PKG-INFO', - 'SOURCES.txt', - 'dependency_links.txt', - 'entry_points.txt', - 'not-zip-safe', - 'top_level.txt', - ] - assert sorted(actual) == expected - def _find_egg_info_files(self, root): results = ( filenames -- cgit v1.2.1 From a9c3739984908d8ed9e902e3a6efe21f031c2908 Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Mon, 19 Oct 2015 12:04:26 +0100 Subject: Added test to ensure that egg_info applies MANIFEST.in The 'self.read_template()' line of manifest_maker was previously uncovered by any test, and the test suite passed if you commented it out. --- setuptools/tests/test_egg_info.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 4977ea01..8281fdc1 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -58,7 +58,7 @@ class TestEggInfo: self._create_project() self._run_install_command(tmpdir_cwd, env) - actual = self._find_egg_info_files(env.paths['lib']) + _, actual = self._find_egg_info_files(env.paths['lib']) expected = [ 'PKG-INFO', @@ -70,6 +70,21 @@ class TestEggInfo: ] assert sorted(actual) == expected + def test_manifest_template_is_read(self, tmpdir_cwd, env): + self._create_project() + build_files({ + 'MANIFEST.in': DALS(""" + recursive-include docs *.rst + """), + 'docs': { + 'usage.rst': "Run 'hi'", + } + }) + self._run_install_command(tmpdir_cwd, env) + egg_info_dir, _ = self._find_egg_info_files(env.paths['lib']) + sources_txt = os.path.join(egg_info_dir, 'SOURCES.txt') + assert 'docs/usage.rst' in open(sources_txt).read().split('\n') + def _run_install_command(self, tmpdir_cwd, env): environ = os.environ.copy().update( HOME=env.paths['home'], @@ -92,7 +107,7 @@ class TestEggInfo: def _find_egg_info_files(self, root): results = ( - filenames + (dirpath, filenames) for dirpath, dirnames, filenames in os.walk(root) if os.path.basename(dirpath) == 'EGG-INFO' ) -- cgit v1.2.1 From ae6c73f07680da77345f5ccfac4facde30ad4d7e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 22 Oct 2015 16:57:13 -0400 Subject: Dropping support for Python 3.2 and earlier Python 3 versions. Currently only log a warning, but future versions will fail. --- .travis.yml | 1 - CHANGES.txt | 8 ++++++++ pkg_resources/__init__.py | 7 +++++++ setup.py | 2 -- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 45cace4b..0097ab89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: python python: - 2.6 - 2.7 - - 3.2 - 3.3 - 3.4 - pypy diff --git a/CHANGES.txt b/CHANGES.txt index d2007753..6c7239d1 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +---- +18.5 +---- + +* In preparation for dropping support for Python 3.2, a warning is + now logged when pkg_resources is imported on Python 3.2 or earlier + Python 3 versions. + ---- 18.4 ---- diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index ce8f2e98..ae363755 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -95,6 +95,13 @@ except ImportError: import packaging.specifiers +if (3, 0) < sys.version_info < (3, 3): + msg = ( + "Support for Python 3.0-3.2 has been dropped. Future versions " + "will fail here." + ) + warnings.warn(msg) + # declare some globals that will be defined later to # satisfy the linters. require = None diff --git a/setup.py b/setup.py index 2b367a6d..6226111d 100755 --- a/setup.py +++ b/setup.py @@ -140,8 +140,6 @@ setup_params = dict( Programming Language :: Python :: 2.6 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 - Programming Language :: Python :: 3.1 - Programming Language :: Python :: 3.2 Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 -- cgit v1.2.1 From 03cc3be9da0f1d31a3e4f2272d3ebb28ed761b35 Mon Sep 17 00:00:00 2001 From: Dweep Shah Date: Mon, 26 Oct 2015 16:45:04 -0400 Subject: Unload all pkg_resources modules and not just the main module. Fixes #453. --- ez_setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ez_setup.py b/ez_setup.py index 50e0dfc6..bbfe0544 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -125,7 +125,12 @@ def _do_download(version, download_base, to_dir, download_delay): # Remove previously-imported pkg_resources if present (see # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). if 'pkg_resources' in sys.modules: - del sys.modules['pkg_resources'] + del_modules = [ + name for name in sys.modules + if name.startswith('pkg_resources') + ] + for mod_name in del_modules: + del sys.modules[mod_name] import setuptools setuptools.bootstrap_install_from = egg -- cgit v1.2.1 From dca452f0ed773557f5a5013cd77f76edfcbbb74e Mon Sep 17 00:00:00 2001 From: Dweep Shah Date: Tue, 27 Oct 2015 16:35:06 -0400 Subject: Uses an existing method to delete pkg_resources --- ez_setup.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index bbfe0544..a1977155 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -125,12 +125,7 @@ def _do_download(version, download_base, to_dir, download_delay): # Remove previously-imported pkg_resources if present (see # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). if 'pkg_resources' in sys.modules: - del_modules = [ - name for name in sys.modules - if name.startswith('pkg_resources') - ] - for mod_name in del_modules: - del sys.modules[mod_name] + _unload_pkg_resources() import setuptools setuptools.bootstrap_install_from = egg -- cgit v1.2.1 From 57ebfa41e0f96b97e599ecd931b7ae8a143e096e Mon Sep 17 00:00:00 2001 From: Vadim Markovtsev Date: Sun, 1 Nov 2015 12:35:38 +0300 Subject: Fix "dictionary changed size during iteration" env is being modified at the same time as being iterated which leads to RuntimeError: dictionary changed size during iteration. --- pkg_resources/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index ae363755..df662dfe 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -1536,7 +1536,7 @@ class MarkerEvaluation(object): # markerlib implements Metadata 1.2 (PEP 345) environment markers. # Translate the variables to Metadata 2.0 (PEP 426). env = _markerlib.default_environment() - for key in env.keys(): + for key in tuple(env.keys()): new_key = key.replace('.', '_') env[new_key] = env.pop(key) try: -- cgit v1.2.1 From 2e236152228a7d2aec383fcecd70731f96ad4de3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 1 Nov 2015 12:07:00 -0500 Subject: Extract a a method to encapsulate behavior and documentation. Rewrite for loop as legacy-style dictionary comprehension. --- pkg_resources/__init__.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index df662dfe..fb8704fd 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -1525,6 +1525,17 @@ class MarkerEvaluation(object): """ return cls.interpret(parser.expr(text).totuple(1)[1]) + @staticmethod + def _translate_metadata2(env): + """ + Markerlib implements Metadata 1.2 (PEP 345) environment markers. + Translate the variables to Metadata 2.0 (PEP 426). + """ + return dict( + (key.replace('.', '_'), value) + for key, value in env + ) + @classmethod def _markerlib_evaluate(cls, text): """ @@ -1533,12 +1544,8 @@ class MarkerEvaluation(object): Raise SyntaxError if marker is invalid. """ import _markerlib - # markerlib implements Metadata 1.2 (PEP 345) environment markers. - # Translate the variables to Metadata 2.0 (PEP 426). - env = _markerlib.default_environment() - for key in tuple(env.keys()): - new_key = key.replace('.', '_') - env[new_key] = env.pop(key) + + env = cls._translate_metadata2(_markerlib.default_environment()) try: result = _markerlib.interpret(text, env) except NameError as e: -- cgit v1.2.1 From d76ce5c06cb8c290e8f2cc803c85ae97543a3de2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 1 Nov 2015 19:19:01 -0500 Subject: Update changelog --- CHANGES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 6c7239d1..bd05b8bd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,6 +9,10 @@ CHANGES * In preparation for dropping support for Python 3.2, a warning is now logged when pkg_resources is imported on Python 3.2 or earlier Python 3 versions. +* `Add support for python_platform_implementation environment marker + `_. +* `Fix dictionary mutation during iteration + `_. ---- 18.4 -- cgit v1.2.1 From 260c08f4bacf1d2e0833f30522f5b55c7440ec7a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 1 Nov 2015 19:19:41 -0500 Subject: Added tag 18.5 for changeset 31dc6d2ac0f5 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index d7ea9e2e..5729d664 100644 --- a/.hgtags +++ b/.hgtags @@ -222,3 +222,4 @@ b59320212c8371d0be9e5e6c5f7eec392124c009 18.3 7a705b610abb1177ca169311c4ee261f3e4f0957 18.3.1 1e120f04bcaa2421c4df0eb6678c3019ba4a82f6 18.3.2 6203335278be7543d31790d9fba55739469a4c6c 18.4 +31dc6d2ac0f5ab766652602fe6ca716fff7180e7 18.5 -- cgit v1.2.1 From 2ac80cd8a4ab5d9398c51fbfcc71489141f4f1c1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 1 Nov 2015 19:21:10 -0500 Subject: Bumped to 18.6 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 50e0dfc6..c41c10e9 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.5" +DEFAULT_VERSION = "18.6" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 1be1f7ec..74e48b04 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.5' +__version__ = '18.6' -- cgit v1.2.1 From 5b72c2587563f6190db732cb5b49e1868fa546e2 Mon Sep 17 00:00:00 2001 From: Robert Collins Date: Thu, 5 Nov 2015 11:37:38 +1300 Subject: Fix EBNF for package specifications. --- docs/pkg_resources.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pkg_resources.txt b/docs/pkg_resources.txt index 6c6405a8..3d40a1a2 100644 --- a/docs/pkg_resources.txt +++ b/docs/pkg_resources.txt @@ -592,7 +592,7 @@ Requirements Parsing The syntax of a requirement specifier can be defined in EBNF as follows:: - requirement ::= project_name versionspec? extras? + requirement ::= project_name extras? versionspec? versionspec ::= comparison version (',' comparison version)* comparison ::= '<' | '<=' | '!=' | '==' | '>=' | '>' | '~=' | '===' extras ::= '[' extralist? ']' -- cgit v1.2.1 From a88effc90cdc99974ae65c008238566cdab4b98e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 21 Nov 2015 10:42:48 -0500 Subject: Update docs to reflect preferred usage with latest pytest-runner. --- docs/developer-guide.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index 27c304e5..b6f5bb9f 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -92,7 +92,7 @@ Testing The primary tests are run using py.test. To run the tests:: - $ python setup.py ptr + $ python setup.py test Or install py.test into your environment and run ``py.test``. -- cgit v1.2.1 From b6a3ccf987ce2f8d13e1520563223bd76460744a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 22 Nov 2015 19:16:09 -0500 Subject: Extract function for detecting unpacked egg. Ref #462. --- pkg_resources/__init__.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index d09e0b6f..0c024f1b 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -1716,7 +1716,7 @@ class EggProvider(NullProvider): path = self.module_path old = None while path!=old: - if path.lower().endswith('.egg'): + if _is_unpacked_egg(path): self.egg_name = os.path.basename(path) self.egg_info = os.path.join(path, 'EGG-INFO') self.egg_root = path @@ -2099,7 +2099,7 @@ def find_eggs_in_zip(importer, path_item, only=False): # don't yield nested distros return for subitem in metadata.resource_listdir('/'): - if subitem.endswith('.egg'): + if _is_unpacked_egg(subitem): subpath = os.path.join(path_item, subitem) for dist in find_eggs_in_zip(zipimport.zipimporter(subpath), subpath): yield dist @@ -2115,8 +2115,7 @@ def find_on_path(importer, path_item, only=False): path_item = _normalize_cached(path_item) if os.path.isdir(path_item) and os.access(path_item, os.R_OK): - if path_item.lower().endswith('.egg'): - # unpacked egg + if _is_unpacked_egg(path_item): yield Distribution.from_filename( path_item, metadata=PathMetadata( path_item, os.path.join(path_item,'EGG-INFO') @@ -2136,7 +2135,7 @@ def find_on_path(importer, path_item, only=False): yield Distribution.from_location( path_item, entry, metadata, precedence=DEVELOP_DIST ) - elif not only and lower.endswith('.egg'): + elif not only and _is_unpacked_egg(entry): dists = find_distributions(os.path.join(path_item, entry)) for dist in dists: yield dist @@ -2283,6 +2282,14 @@ def _normalize_cached(filename, _cache={}): _cache[filename] = result = normalize_path(filename) return result +def _is_unpacked_egg(path): + """ + Determine if given path appears to be an unpacked egg. + """ + return ( + path.lower().endswith('.egg') + ) + def _set_parent_ns(packageName): parts = packageName.split('.') name = parts.pop() -- cgit v1.2.1 From 40436edb86b034979b716695ec68fe55bb656d79 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 22 Nov 2015 19:18:37 -0500 Subject: Only detect a path as an unpacked egg if it also has an EGG-INFO directory. Fixes #462. --- CHANGES.txt | 7 +++++++ pkg_resources/__init__.py | 1 + 2 files changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index bd05b8bd..60d43fb2 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,13 @@ CHANGES ======= +---- +18.6 +---- + +* Issue #462: Provide a more refined detection of unpacked egg + directories, avoiding detecting zc.recipe.egg wheel as an egg. + ---- 18.5 ---- diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 0c024f1b..8841ee63 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2288,6 +2288,7 @@ def _is_unpacked_egg(path): """ return ( path.lower().endswith('.egg') + and os.path.isdir(os.path.join(path, 'EGG-INFO')) ) def _set_parent_ns(packageName): -- cgit v1.2.1 From f05162f5583979a3cc56492b91211cbe54353efa Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 10:54:46 -0500 Subject: Short circuit on skipped behavior, leaving main behavior in the body of the method. --- setuptools/command/easy_install.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 45d180bb..4fae2560 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -760,9 +760,10 @@ class easy_install(Command): return dst def install_wrapper_scripts(self, dist): - if not self.exclude_scripts: - for args in ScriptWriter.best().get_args(dist): - self.write_script(*args) + if self.exclude_scripts: + return + for args in ScriptWriter.best().get_args(dist): + self.write_script(*args) def install_script(self, dist, script_name, script_text, dev_path=None): """Generate a legacy script wrapper and install it""" -- cgit v1.2.1 From 998ceceaeb3dfce1b2b05a82aaf356db54f46de6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 11:27:22 -0500 Subject: Back out 435b1b762fba. The change breaks detection of zip eggs. Reopens #462. --- CHANGES.txt | 7 ------- pkg_resources/__init__.py | 1 - 2 files changed, 8 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 60d43fb2..bd05b8bd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,13 +2,6 @@ CHANGES ======= ----- -18.6 ----- - -* Issue #462: Provide a more refined detection of unpacked egg - directories, avoiding detecting zc.recipe.egg wheel as an egg. - ---- 18.5 ---- diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 8841ee63..0c024f1b 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2288,7 +2288,6 @@ def _is_unpacked_egg(path): """ return ( path.lower().endswith('.egg') - and os.path.isdir(os.path.join(path, 'EGG-INFO')) ) def _set_parent_ns(packageName): -- cgit v1.2.1 From f4576e373b51fab07eec7f6f2cde3ffa2e04f6c0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 11:32:45 -0500 Subject: Add VersionlessRequirement adapter to suppress the version number in a Distribution. Ref #439. --- setuptools/command/develop.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 368b64fe..0959d937 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -167,3 +167,26 @@ class develop(easy_install): script_text = f.read() f.close() self.install_script(dist, script_name, script_text, script_path) + + +class VersionlessRequirement(object): + """ + Adapt a pkg_resources.Distribution to simply return the project + name as the 'requirement' so that scripts will work across + multiple versions. + + >>> dist = Distribution(project_name='foo', version='1.0') + >>> str(dist.as_requirement()) + 'foo==1.0' + >>> adapted_dist = VersionlessRequirement(dist) + >>> str(adapted_dist.as_requirement()) + 'foo' + """ + def __init__(self, dist): + self.__dist = dist + + def __getattr__(self, name): + return getattr(self.__dist, name) + + def as_requirement(self): + return self.project_name -- cgit v1.2.1 From c23be8f034d8600191decd7e843ae93619d15298 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 11:35:27 -0500 Subject: Adapt the dist to suppress the version in the requirement when installing scripts under the develop command. Fixes #439. --- setuptools/command/develop.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 0959d937..360872fc 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -168,6 +168,10 @@ class develop(easy_install): f.close() self.install_script(dist, script_name, script_text, script_path) + def install_wrapper_scripts(self, dist): + dist = VersionlessRequirement(dist) + return super(develop, self).install_wrapper_scripts(dist) + class VersionlessRequirement(object): """ -- cgit v1.2.1 From de6c530852988f412f7e546a5a60f02b6a2e06e3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 11:36:46 -0500 Subject: Update changelog; ref #439. --- CHANGES.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index bd05b8bd..c4b456f6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +---- +18.6 +---- + +* Issue #439: When installing entry_point scripts under development, + omit the version number of the package, allowing any version of the + package to be used. + ---- 18.5 ---- -- cgit v1.2.1 From 6e6872addad422b164c7a9a0e8711a7264978c58 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 11:43:58 -0500 Subject: Added tag 18.6 for changeset dfe190b09908 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 5729d664..d95f31dd 100644 --- a/.hgtags +++ b/.hgtags @@ -223,3 +223,4 @@ b59320212c8371d0be9e5e6c5f7eec392124c009 18.3 1e120f04bcaa2421c4df0eb6678c3019ba4a82f6 18.3.2 6203335278be7543d31790d9fba55739469a4c6c 18.4 31dc6d2ac0f5ab766652602fe6ca716fff7180e7 18.5 +dfe190b09908f6b953209d13573063809de451b8 18.6 -- cgit v1.2.1 From 172bd064abe5a973f38ab9641a80b39782ad2cde Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 11:46:14 -0500 Subject: Bumped to 18.7 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index c41c10e9..20d80e8e 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.6" +DEFAULT_VERSION = "18.7" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 74e48b04..f6dc6bf4 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.6' +__version__ = '18.7' -- cgit v1.2.1 From f34cf8e9242d2b4c25b5a511f9f74fbffcb17c4f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 11:58:35 -0500 Subject: Suppress testing of upload-releases-as-zip script --- pytest.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index 91d64bb8..351942f4 100755 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,3 @@ [pytest] -addopts=--doctest-modules --ignore release.py --ignore setuptools/lib2to3_ex.py --ignore tests/manual_test.py --ignore tests/shlib_test --doctest-glob=pkg_resources/api_tests.txt +addopts=--doctest-modules --ignore release.py --ignore setuptools/lib2to3_ex.py --ignore tests/manual_test.py --ignore tests/shlib_test --doctest-glob=pkg_resources/api_tests.txt --ignore scripts/upload-old-releases-as-zip.py norecursedirs=dist build *.egg -- cgit v1.2.1 From e311cafb5305a445def27fbc79fdc5f098c76728 Mon Sep 17 00:00:00 2001 From: Ryan Kelly Date: Tue, 24 Nov 2015 13:46:26 -0500 Subject: issue #464: don't crash using super() on a old-style class --- setuptools/command/develop.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 360872fc..5ae25d71 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -170,7 +170,7 @@ class develop(easy_install): def install_wrapper_scripts(self, dist): dist = VersionlessRequirement(dist) - return super(develop, self).install_wrapper_scripts(dist) + return easy_install.install_wrapper_scripts(self, dist) class VersionlessRequirement(object): -- cgit v1.2.1 From ea6c487fbfe70032a1dddb0b4501e66420eefeb4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 18:51:29 -0500 Subject: Update changelog --- CHANGES.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index c4b456f6..b14e9103 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= + +------ +18.6.1 +------ + +* Issue #464: Correct regression in invocation of superclass on old-style + class on Python 2. + ---- 18.6 ---- -- cgit v1.2.1 From a84f4878c07509a79af863cabf29ce4de6f212c2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 18:52:20 -0500 Subject: Bumped to 18.6.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 20d80e8e..06918e1b 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.7" +DEFAULT_VERSION = "18.6.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index f6dc6bf4..9f17b0ab 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.7' +__version__ = '18.6.1' -- cgit v1.2.1 From ceaafa112be304add1353435599df514dbcbe9ec Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 18:52:22 -0500 Subject: Added tag 18.6.1 for changeset 804f87045a90 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index d95f31dd..6ed522b4 100644 --- a/.hgtags +++ b/.hgtags @@ -224,3 +224,4 @@ b59320212c8371d0be9e5e6c5f7eec392124c009 18.3 6203335278be7543d31790d9fba55739469a4c6c 18.4 31dc6d2ac0f5ab766652602fe6ca716fff7180e7 18.5 dfe190b09908f6b953209d13573063809de451b8 18.6 +804f87045a901f1dc121cf9149143d654228dc13 18.6.1 -- cgit v1.2.1 From cf39578632c13d49866fe924bf4c5f5ba48db554 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 18:54:16 -0500 Subject: Bumped to 18.6.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 06918e1b..4740248f 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.6.1" +DEFAULT_VERSION = "18.6.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 9f17b0ab..86ad21c6 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.6.1' +__version__ = '18.6.2' -- cgit v1.2.1 From 3bcf6213d25381d9df9baa2b7a16c9449fbf78e7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 18:55:48 -0500 Subject: Use context manager for opening file --- setuptools/tests/test_develop.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index ed1b194a..b920655d 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -32,15 +32,13 @@ class TestDevelopTest: os.mkdir(os.path.join(self.dir, 'foo')) # setup.py setup = os.path.join(self.dir, 'setup.py') - f = open(setup, 'w') - f.write(SETUP_PY) - f.close() + with open(setup, 'w') as f: + f.write(SETUP_PY) self.old_cwd = os.getcwd() # foo/__init__.py init = os.path.join(self.dir, 'foo', '__init__.py') - f = open(init, 'w') - f.write(INIT_PY) - f.close() + with open(init, 'w') as f: + f.write(INIT_PY) os.chdir(self.dir) self.old_base = site.USER_BASE -- cgit v1.2.1 From bc7f3b0a36a1c676809f89eae7299afbb7f70f32 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 19:32:13 -0500 Subject: Extract setup/teardown methods as proper fixtures. --- setuptools/tests/test_develop.py | 57 +++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index b920655d..96b9f4ef 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -6,8 +6,12 @@ import site import sys import tempfile +import pytest + from setuptools.command.develop import develop from setuptools.dist import Distribution +from . import contexts + SETUP_PY = """\ from setuptools import setup @@ -21,43 +25,42 @@ setup(name='foo', INIT_PY = """print "foo" """ +@pytest.yield_fixture +def temp_user(monkeypatch): + with contexts.tempdir() as user_base: + with contexts.tempdir() as user_site: + monkeypatch.setattr('site.USER_BASE', user_base) + monkeypatch.setattr('site.USER_SITE', user_site) + yield + + +@pytest.yield_fixture +def test_env(tmpdir, temp_user): + target = tmpdir + foo = target.mkdir('foo') + setup = target / 'setup.py' + if setup.isfile(): + raise ValueError(dir(target)) + with setup.open('w') as f: + f.write(SETUP_PY) + init = foo / '__init__.py' + with init.open('w') as f: + f.write(INIT_PY) + with target.as_cwd(): + yield target + + class TestDevelopTest: def setup_method(self, method): if hasattr(sys, 'real_prefix'): return - # Directory structure - self.dir = tempfile.mkdtemp() - os.mkdir(os.path.join(self.dir, 'foo')) - # setup.py - setup = os.path.join(self.dir, 'setup.py') - with open(setup, 'w') as f: - f.write(SETUP_PY) - self.old_cwd = os.getcwd() - # foo/__init__.py - init = os.path.join(self.dir, 'foo', '__init__.py') - with open(init, 'w') as f: - f.write(INIT_PY) - - os.chdir(self.dir) - self.old_base = site.USER_BASE - site.USER_BASE = tempfile.mkdtemp() - self.old_site = site.USER_SITE - site.USER_SITE = tempfile.mkdtemp() - def teardown_method(self, method): if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix): return - os.chdir(self.old_cwd) - shutil.rmtree(self.dir) - shutil.rmtree(site.USER_BASE) - shutil.rmtree(site.USER_SITE) - site.USER_BASE = self.old_base - site.USER_SITE = self.old_site - - def test_develop(self): + def test_develop(self, test_env): if hasattr(sys, 'real_prefix'): return dist = Distribution( -- cgit v1.2.1 From 448cfc53cd16fb11562def2ee8b9bf66ed178b21 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 19:37:11 -0500 Subject: Replace silent test acceptance with a proper skip check --- setuptools/tests/test_develop.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 96b9f4ef..2baf83bb 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -51,18 +51,9 @@ def test_env(tmpdir, temp_user): class TestDevelopTest: - - def setup_method(self, method): - if hasattr(sys, 'real_prefix'): - return - - def teardown_method(self, method): - if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix): - return - + @pytest.mark.skipif(hasattr(sys, 'real_prefix'), + reason="Cannot run when invoked in a virtualenv") def test_develop(self, test_env): - if hasattr(sys, 'real_prefix'): - return dist = Distribution( dict(name='foo', packages=['foo'], -- cgit v1.2.1 From e1e3570fb01aa4f1fe6d0e56cfb73d38b781a307 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 19:38:13 -0500 Subject: Extract variable --- setuptools/tests/test_develop.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 2baf83bb..49e007e6 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -54,12 +54,13 @@ class TestDevelopTest: @pytest.mark.skipif(hasattr(sys, 'real_prefix'), reason="Cannot run when invoked in a virtualenv") def test_develop(self, test_env): - dist = Distribution( - dict(name='foo', - packages=['foo'], - use_2to3=True, - version='0.0', - )) + settings = dict( + name='foo', + packages=['foo'], + use_2to3=True, + version='0.0', + ) + dist = Distribution(settings) dist.script_name = 'setup.py' cmd = develop(dist) cmd.user = 1 -- cgit v1.2.1 From 731c83fd5ebe79a7643465e68310c11387b427e8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 19:41:32 -0500 Subject: Remove unused imports --- setuptools/tests/test_develop.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 49e007e6..962c4f3c 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -1,10 +1,8 @@ """develop tests """ import os -import shutil import site import sys -import tempfile import pytest -- cgit v1.2.1 From 693f20d40fca6b41ac629665901c350cd3dcd4e8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 19:45:12 -0500 Subject: Use quiet context to suppress stdout. --- setuptools/tests/test_develop.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 962c4f3c..f0adcb18 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -65,12 +65,8 @@ class TestDevelopTest: cmd.ensure_finalized() cmd.install_dir = site.USER_SITE cmd.user = 1 - old_stdout = sys.stdout - #sys.stdout = StringIO() - try: + with contexts.quiet(): cmd.run() - finally: - sys.stdout = old_stdout # let's see if we got our egg link at the right place content = os.listdir(site.USER_SITE) -- cgit v1.2.1 From 0861296a63b3fafd059759840fb62ba12d4e6adc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 19:47:58 -0500 Subject: Use io.open and its context for simpler reading of a file --- setuptools/tests/test_develop.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index f0adcb18..ec655462 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -3,6 +3,7 @@ import os import site import sys +import io import pytest @@ -74,16 +75,12 @@ class TestDevelopTest: assert content == ['easy-install.pth', 'foo.egg-link'] # Check that we are using the right code. - egg_link_file = open(os.path.join(site.USER_SITE, 'foo.egg-link'), 'rt') - try: + fn = os.path.join(site.USER_SITE, 'foo.egg-link') + with io.open(fn) as egg_link_file: path = egg_link_file.read().split()[0].strip() - finally: - egg_link_file.close() - init_file = open(os.path.join(path, 'foo', '__init__.py'), 'rt') - try: + fn = os.path.join(path, 'foo', '__init__.py') + with io.open(fn) as init_file: init = init_file.read().strip() - finally: - init_file.close() if sys.version < "3": assert init == 'print "foo"' else: -- cgit v1.2.1 From 951a3b9df51c1c46a39753dc6f2854ea18f45729 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 20:01:32 -0500 Subject: Use if clause. --- setuptools/tests/test_develop.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index ec655462..35f3ea25 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -10,6 +10,7 @@ import pytest from setuptools.command.develop import develop from setuptools.dist import Distribution from . import contexts +from setuptools.compat import PY3 SETUP_PY = """\ @@ -81,7 +82,6 @@ class TestDevelopTest: fn = os.path.join(path, 'foo', '__init__.py') with io.open(fn) as init_file: init = init_file.read().strip() - if sys.version < "3": - assert init == 'print "foo"' - else: - assert init == 'print("foo")' + + expected = 'print("foo")' if PY3 else 'print "foo"' + assert init == expected -- cgit v1.2.1 From 436be23a0ac5d7f21f261bdcd6fd9119a4f55346 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 20:38:52 -0500 Subject: Rename tests for clarity --- setuptools/tests/test_develop.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 35f3ea25..725c4ce2 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -50,10 +50,10 @@ def test_env(tmpdir, temp_user): yield target -class TestDevelopTest: +class TestDevelop: @pytest.mark.skipif(hasattr(sys, 'real_prefix'), reason="Cannot run when invoked in a virtualenv") - def test_develop(self, test_env): + def test_2to3_user_mode(self, test_env): settings = dict( name='foo', packages=['foo'], -- cgit v1.2.1 From 7bd76e0869310de9da5a32ca2c860f6a1fa461b5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 24 Nov 2015 21:21:09 -0500 Subject: Draft a test for testing the new expectation for develop command (and general functionality when console scripts are present). --- setuptools/tests/test_develop.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 725c4ce2..71f0d69a 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -85,3 +85,28 @@ class TestDevelop: expected = 'print("foo")' if PY3 else 'print "foo"' assert init == expected + + def test_console_scripts(self, tmpdir): + """ + Test that console scripts are installed and that they reference + only the project by name and not the current version. + """ + pytest.skip("TODO: needs a fixture to cause 'develop' " + "to be invoked without mutating environment.") + settings = dict( + name='foo', + packages=['foo'], + version='0.0', + entry_points={ + 'console_scripts': [ + 'foocmd = foo:foo', + ], + }, + ) + dist = Distribution(settings) + dist.script_name = 'setup.py' + cmd = develop(dist) + cmd.ensure_finalized() + cmd.install_dir = tmpdir + cmd.run() + #assert '0.0' not in foocmd_text -- cgit v1.2.1 From adc0d911143caf6a174fed7b71b75249404d5eff Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 25 Nov 2015 09:43:50 -0500 Subject: No need for a separate DEVGUIDE --- DEVGUIDE.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 DEVGUIDE.txt diff --git a/DEVGUIDE.txt b/DEVGUIDE.txt deleted file mode 100644 index 066a3a6b..00000000 --- a/DEVGUIDE.txt +++ /dev/null @@ -1 +0,0 @@ -The canonical development guide can be found in docs/developer-guide.txt. -- cgit v1.2.1 From 75a571e4d9d5f5c3fde661c54a368b533be1978b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 25 Nov 2015 10:04:33 -0500 Subject: Skip the test when running under venv also --- setuptools/tests/test_develop.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 71f0d69a..ab5da00e 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -51,8 +51,10 @@ def test_env(tmpdir, temp_user): class TestDevelop: - @pytest.mark.skipif(hasattr(sys, 'real_prefix'), - reason="Cannot run when invoked in a virtualenv") + in_virtualenv = hasattr(sys, 'real_prefix') + in_venv = hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix + @pytest.mark.skipif(in_virtualenv or in_venv, + reason="Cannot run when invoked in a virtualenv or venv") def test_2to3_user_mode(self, test_env): settings = dict( name='foo', -- cgit v1.2.1 From 63c3e2e1ba805f64ad251a90c1182bdd06e28a12 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 25 Nov 2015 10:44:07 -0500 Subject: Update tox tests so they run the full suite of tests using the canonical technique. Include .tox in norecursedirs to avoid testing all the dependencies and environment. Update docs to reflect findings (https://bitbucket.org/spookylukey/setuptools/commits/88339d2e4af661a60a42bc14c4ff3e68cd19fa21#comment-2558164). --- docs/developer-guide.txt | 3 ++- tox.ini | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index b6f5bb9f..ae33649b 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -94,7 +94,8 @@ The primary tests are run using py.test. To run the tests:: $ python setup.py test -Or install py.test into your environment and run ``py.test``. +Or install py.test into your environment and run ``PYTHONPATH=. py.test`` +or ``python -m pytest``. Under continuous integration, additional tests may be run. See the ``.travis.yml`` file for full details on the tests run under Travis-CI. diff --git a/tox.ini b/tox.ini index 7aeffdd8..9061869f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,5 @@ [tox] envlist = py26,py27,py31,py32,py33,py34 + [testenv] -deps= - pytest - mock -commands=py.test setuptools {posargs} +commands=python setup.py test -- cgit v1.2.1 From 9186dd6e15a7f7102ec4d3bf0f9c660ea6c7f082 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 27 Nov 2015 12:43:20 -0500 Subject: Add a bit more detail about the setup script and what to expect. Fixes #466. --- docs/setuptools.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/setuptools.txt b/docs/setuptools.txt index e2753cba..d6a62de8 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -112,10 +112,16 @@ the distutils. Here's a minimal setup script using setuptools:: ) As you can see, it doesn't take much to use setuptools in a project. -Just by doing the above, this project will be able to produce eggs, upload to +Run that script in your project folder, alongside the Python packages +you have developed. + +Invoke that script to produce eggs, upload to PyPI, and automatically include all packages in the directory where the setup.py lives. See the `Command Reference`_ section below to see what -commands you can give to this setup script. +commands you can give to this setup script. For example, +to produce a source distribution, simply invoke:: + + python setup.py sdist Of course, before you release your project to PyPI, you'll want to add a bit more information to your setup script to help people find or learn about your -- cgit v1.2.1 From 08edac82f02e771ff82f01938208def8ef9991b0 Mon Sep 17 00:00:00 2001 From: John Vandenberg Date: Fri, 13 Nov 2015 07:02:56 +1100 Subject: Fix docstring started with """" instead of """ --- setuptools/py31compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/py31compat.py b/setuptools/py31compat.py index c487ac04..8fe6dd9d 100644 --- a/setuptools/py31compat.py +++ b/setuptools/py31compat.py @@ -20,7 +20,7 @@ except ImportError: import shutil import tempfile class TemporaryDirectory(object): - """" + """ Very simple temporary directory context manager. Will try to delete afterward, but will also ignore OS and similar errors on deletion. -- cgit v1.2.1 From 03e7e8c23889bcac55d2cb563ad8deb172e77210 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Sun, 15 Nov 2015 22:30:46 -0500 Subject: Add tests ref #419. --- setuptools/tests/test_egg_info.py | 96 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index a1caf9fd..b4195e06 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -6,9 +6,14 @@ import pytest from . import environment from .textwrap import DALS from . import contexts +from pkg_resources import WorkingSet, Requirement -class TestEggInfo: +class Environment(str): + pass + + +class TestEggInfo(object): setup_script = DALS(""" from setuptools import setup @@ -33,8 +38,6 @@ class TestEggInfo: @pytest.yield_fixture def env(self): - class Environment(str): pass - with contexts.tempdir(prefix='setuptools-test.') as env_dir: env = Environment(env_dir) os.chmod(env_dir, stat.S_IRWXU) @@ -49,8 +52,7 @@ class TestEggInfo: f.write(DALS(""" [egg_info] egg-base = %(egg-base)s - """ % env.paths - )) + """ % env.paths)) yield env def test_egg_base_installed_egg_info(self, tmpdir_cwd, env): @@ -96,3 +98,87 @@ class TestEggInfo: # expect exactly one result result, = results return result + + +class TestEggInfoDistutils(object): + + version = '1.11.0.dev0+2329eae' + setup_script = DALS(""" + from distutils.core import setup + + setup( + name='foo', + py_modules=['hello'], + version='%s', + ) + """) + + def _create_project(self): + with open('setup.py', 'w') as f: + f.write(self.setup_script % self.version) + + with open('hello.py', 'w') as f: + f.write(DALS(""" + def run(): + print('hello') + """)) + + @pytest.yield_fixture + def env(self): + with contexts.tempdir(prefix='setuptools-test.') as env_dir: + env = Environment(env_dir) + os.chmod(env_dir, stat.S_IRWXU) + subs = 'home', 'lib', 'scripts', 'data', 'egg-base' + env.paths = dict( + (dirname, os.path.join(env_dir, dirname)) + for dirname in subs + ) + list(map(os.mkdir, env.paths.values())) + config = os.path.join(env.paths['home'], '.pydistutils.cfg') + with open(config, 'w') as f: + f.write(DALS(""" + [egg_info] + egg-base = %(egg-base)s + """ % env.paths)) + yield env + + def test_egg_base_installed_egg_info(self, tmpdir_cwd, env): + self._create_project() + + environ = os.environ.copy().update( + HOME=env.paths['home'], + ) + cmd = [ + 'install', + '--home', env.paths['home'], + '--install-lib', env.paths['lib'], + '--install-scripts', env.paths['scripts'], + '--install-data', env.paths['data'], + ] + code, data = environment.run_setup_py( + cmd=cmd, + pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]), + data_stream=1, + env=environ, + ) + if code: + raise AssertionError(data) + + actual = self._find_egg_info_file(env.paths['lib']) + # On Py3k it can be e.g. foo-1.11.0.dev0_2329eae-py3.4.egg-info + # but 2.7 doesn't add the Python version, so to be expedient we + # just check our start and end, omitting the potential version num + assert actual.startswith('foo-' + self.version.replace('+', '_')) + assert actual.endswith('.egg-info') + # this requirement parsing will raise a VersionConflict unless the + # .egg-info file is parsed (see #419 on BitBucket) + req = Requirement.parse('foo>=1.9') + dist = WorkingSet([env.paths['lib']]).find(req) + assert dist.version == self.version + + def _find_egg_info_file(self, root): + # expect exactly one result + result = (filename for dirpath, dirnames, filenames in os.walk(root) + for filename in filenames if filename.endswith('.egg-info')) + result, = result + return result -- cgit v1.2.1 From 5681e303fca322007efd10a6004221795295414e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 16:53:27 -0500 Subject: Adding script from idg serpro. Ref #432. --- scripts/upload-old-releases-as-zip.py | 234 ++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 scripts/upload-old-releases-as-zip.py diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py new file mode 100644 index 00000000..53492819 --- /dev/null +++ b/scripts/upload-old-releases-as-zip.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import errno +import glob +import hashlib +import json +import os +import shutil +import tarfile +import tempfile +import urllib +import urllib2 + +from distutils.version import LooseVersion + +OK = '\033[92m' +FAIL = '\033[91m' +END = '\033[0m' +DISTRIBUTION = "setuptools" + + +class SetuptoolsOldReleasesWithoutZip(object): + """docstring for SetuptoolsOldReleases""" + + def __init__(self): + super(SetuptoolsOldReleasesWithoutZip, self).__init__() + self.dirpath = tempfile.mkdtemp(prefix=DISTRIBUTION) + print "Downloading %s releases..." % DISTRIBUTION + print "All releases will be downloaded to %s" % self.dirpath + self.data_json_setuptools = self.get_json_data(DISTRIBUTION) + self.valid_releases_numbers = sorted([ + release + for release in self.data_json_setuptools['releases'] + # This condition is motivated by 13.0 release, which + # comes as "13.0": [], in the json + if self.data_json_setuptools['releases'][release] + ], key=LooseVersion) + self.total_downloaded_ok = 0 + + def get_json_data(self, package_name): + """ + "releases": { + "0.7.2": [ + { + "has_sig": false, + "upload_time": "2013-06-09T16:10:00", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-0.7.2.tar.gz", # NOQA + "md5_digest": "de44cd90f8a1c713d6c2bff67bbca65d", + "downloads": 159014, + "filename": "setuptools-0.7.2.tar.gz", + "packagetype": "sdist", + "size": 633077 + } + ], + "0.7.3": [ + { + "has_sig": false, + "upload_time": "2013-06-18T21:08:56", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-0.7.3.tar.gz", # NOQA + "md5_digest": "c854adacbf9067d330a847f06f7a8eba", + "downloads": 30594, + "filename": "setuptools-0.7.3.tar.gz", + "packagetype": "sdist", + "size": 751152 + } + ], + "12.3": [ + { + "has_sig": false, + "upload_time": "2015-02-26T19:15:51", + "comment_text": "", + "python_version": "3.4", + "url": "https://pypi.python.org/packages/3.4/s/setuptools/setuptools-12.3-py2.py3-none-any.whl", # NOQA + "md5_digest": "31f51a38497a70efadf5ce8d4c2211ab", + "downloads": 288451, + "filename": "setuptools-12.3-py2.py3-none-any.whl", + "packagetype": "bdist_wheel", + "size": 501904 + }, + { + "has_sig": false, + "upload_time": "2015-02-26T19:15:43", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-12.3.tar.gz", # NOQA + "md5_digest": "67614b6d560fa4f240e99cd553ec7f32", + "downloads": 110109, + "filename": "setuptools-12.3.tar.gz", + "packagetype": "sdist", + "size": 635025 + }, + { + "has_sig": false, + "upload_time": "2015-02-26T19:15:47", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-12.3.zip", # NOQA + "md5_digest": "abc799e7db6e7281535bf342bfc41a12", + "downloads": 67539, + "filename": "setuptools-12.3.zip", + "packagetype": "sdist", + "size": 678783 + } + ], + """ + url = "https://pypi.python.org/pypi/%s/json" % (package_name,) + data = json.load(urllib2.urlopen(urllib2.Request(url))) + + # Mainly for debug. + json_filename = "%s/%s.json" % (self.dirpath, DISTRIBUTION) + with open(json_filename, 'w') as outfile: + json.dump( + data, + outfile, + sort_keys=True, + indent=4, + separators=(',', ': '), + ) + + return data + + def get_setuptools_releases_without_zip_counterpart(self): + # Get set(all_valid_releases) - set(releases_with_zip), so now we have + # the releases without zip. + return set(self.valid_releases_numbers) - set([ + release + for release in self.valid_releases_numbers + for same_version_release_dict in self.data_json_setuptools['releases'][release] # NOQA + if 'zip' in same_version_release_dict['filename'] + ]) + + def download_setuptools_releases_without_zip_counterpart(self): + try: + releases_without_zip = self.get_setuptools_releases_without_zip_counterpart() # NOQA + failed_md5_releases = [] + # This is a "strange" loop, going through all releases and + # testing only the release I need to download, but I thought it + # would be mouch more readable than trying to iterate through + # releases I need and get into traverse hell values inside dicts + # inside dicts of the json to get the distribution's url to + # download. + for release in self.valid_releases_numbers: + if release in releases_without_zip: + for same_version_release_dict in self.data_json_setuptools['releases'][release]: # NOQA + if 'tar.gz' in same_version_release_dict['filename']: + print "Downloading %s..." % release + local_file = '%s/%s' % ( + self.dirpath, + same_version_release_dict["filename"] + ) + urllib.urlretrieve( + same_version_release_dict["url"], + local_file + ) + targz = open(local_file, 'rb').read() + hexdigest = hashlib.md5(targz).hexdigest() + if (hexdigest != same_version_release_dict['md5_digest']): # NOQA + print FAIL + "FAIL: md5 for %s didn't match!" % release + END # NOQA + failed_md5_releases.append(release) + else: + self.total_downloaded_ok += 1 + print 'Total releases without zip: %s' % len(releases_without_zip) + print 'Total downloaded: %s' % self.total_downloaded_ok + if failed_md5_releases: + raise(Exception( + FAIL + ( + "FAIL: these releases %s failed the md5 check!" % + ','.join(failed_md5_releases) + ) + END + )) + elif self.total_downloaded_ok != len(releases_without_zip): + raise(Exception( + FAIL + ( + "FAIL: Unknown error occured. Please check the logs." + ) + END + )) + else: + print OK + "All releases downloaded and md5 checked." + END + + except OSError as e: + if e.errno != errno.EEXIST: + raise e + + def convert_targz_to_zip(self): + print "Converting the tar.gz to zip..." + files = glob.glob('%s/*.tar.gz' % self.dirpath) + total_converted = 0 + for targz in sorted(files, key=LooseVersion): + # Extract and remove tar. + tar = tarfile.open(targz) + tar.extractall(path=self.dirpath) + tar.close() + os.remove(targz) + + # Zip the extracted tar. + setuptools_folder_path = targz.replace('.tar.gz', '') + setuptools_folder_name = setuptools_folder_path.split("/")[-1] + print setuptools_folder_name + shutil.make_archive( + setuptools_folder_path, + 'zip', + self.dirpath, + setuptools_folder_name + ) + # Exclude extracted tar folder. + shutil.rmtree(setuptools_folder_path.replace('.zip', '')) + total_converted += 1 + print 'Total converted: %s' % total_converted + if self.total_downloaded_ok != total_converted: + raise(Exception( + FAIL + ( + "FAIL: Total number of downloaded releases is different" + " from converted ones. Please check the logs." + ) + END + )) + print "Done with the tar.gz->zip. Check folder %s." % main.dirpath + + def upload_zips_to_pypi(self): + print 'Uploading to pypi...' + zips = sorted(glob.glob('%s/*.zip' % self.dirpath), key=LooseVersion) + for zips in glob.glob('%s/*.zip' % self.dirpath): + # Put the twine upload code here + pass + + +main = SetuptoolsOldReleasesWithoutZip() +main.download_setuptools_releases_without_zip_counterpart() +main.convert_targz_to_zip() +main.upload_zips_to_pypi() -- cgit v1.2.1 From 34668623d92b950634a2fcf750d902fb34f321ae Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 16:53:56 -0500 Subject: Only execute when invoked as script --- scripts/upload-old-releases-as-zip.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py index 53492819..e08e4bb4 100644 --- a/scripts/upload-old-releases-as-zip.py +++ b/scripts/upload-old-releases-as-zip.py @@ -228,7 +228,8 @@ class SetuptoolsOldReleasesWithoutZip(object): pass -main = SetuptoolsOldReleasesWithoutZip() -main.download_setuptools_releases_without_zip_counterpart() -main.convert_targz_to_zip() -main.upload_zips_to_pypi() +if __name__ == '__main__': + main = SetuptoolsOldReleasesWithoutZip() + main.download_setuptools_releases_without_zip_counterpart() + main.convert_targz_to_zip() + main.upload_zips_to_pypi() -- cgit v1.2.1 From 2ac91b232f9f7061c53b51520353c31b12d576be Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 17:00:39 -0500 Subject: Extract parameter to exceptions and remove superfluous parentheses --- scripts/upload-old-releases-as-zip.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py index e08e4bb4..f0ca41c3 100644 --- a/scripts/upload-old-releases-as-zip.py +++ b/scripts/upload-old-releases-as-zip.py @@ -167,18 +167,16 @@ class SetuptoolsOldReleasesWithoutZip(object): print 'Total releases without zip: %s' % len(releases_without_zip) print 'Total downloaded: %s' % self.total_downloaded_ok if failed_md5_releases: - raise(Exception( - FAIL + ( - "FAIL: these releases %s failed the md5 check!" % - ','.join(failed_md5_releases) - ) + END - )) + msg = FAIL + ( + "FAIL: these releases %s failed the md5 check!" % + ','.join(failed_md5_releases) + ) + END + raise Exception(msg) elif self.total_downloaded_ok != len(releases_without_zip): - raise(Exception( - FAIL + ( - "FAIL: Unknown error occured. Please check the logs." - ) + END - )) + msg = FAIL + ( + "FAIL: Unknown error occured. Please check the logs." + ) + END + raise Exception(msg) else: print OK + "All releases downloaded and md5 checked." + END @@ -212,12 +210,11 @@ class SetuptoolsOldReleasesWithoutZip(object): total_converted += 1 print 'Total converted: %s' % total_converted if self.total_downloaded_ok != total_converted: - raise(Exception( - FAIL + ( - "FAIL: Total number of downloaded releases is different" - " from converted ones. Please check the logs." - ) + END - )) + msg = FAIL + ( + "FAIL: Total number of downloaded releases is different" + " from converted ones. Please check the logs." + ) + END + raise Exception(msg) print "Done with the tar.gz->zip. Check folder %s." % main.dirpath def upload_zips_to_pypi(self): -- cgit v1.2.1 From e30ea433fbfc1de15e23bcb4f2310c525fa5ea0c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 17:01:26 -0500 Subject: Run 2to3 on script --- scripts/upload-old-releases-as-zip.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py index f0ca41c3..33a3e29c 100644 --- a/scripts/upload-old-releases-as-zip.py +++ b/scripts/upload-old-releases-as-zip.py @@ -9,8 +9,8 @@ import os import shutil import tarfile import tempfile -import urllib -import urllib2 +import urllib.request, urllib.parse, urllib.error +import urllib.request, urllib.error, urllib.parse from distutils.version import LooseVersion @@ -26,8 +26,8 @@ class SetuptoolsOldReleasesWithoutZip(object): def __init__(self): super(SetuptoolsOldReleasesWithoutZip, self).__init__() self.dirpath = tempfile.mkdtemp(prefix=DISTRIBUTION) - print "Downloading %s releases..." % DISTRIBUTION - print "All releases will be downloaded to %s" % self.dirpath + print("Downloading %s releases..." % DISTRIBUTION) + print("All releases will be downloaded to %s" % self.dirpath) self.data_json_setuptools = self.get_json_data(DISTRIBUTION) self.valid_releases_numbers = sorted([ release @@ -109,7 +109,7 @@ class SetuptoolsOldReleasesWithoutZip(object): ], """ url = "https://pypi.python.org/pypi/%s/json" % (package_name,) - data = json.load(urllib2.urlopen(urllib2.Request(url))) + data = json.load(urllib.request.urlopen(urllib.request.Request(url))) # Mainly for debug. json_filename = "%s/%s.json" % (self.dirpath, DISTRIBUTION) @@ -148,24 +148,24 @@ class SetuptoolsOldReleasesWithoutZip(object): if release in releases_without_zip: for same_version_release_dict in self.data_json_setuptools['releases'][release]: # NOQA if 'tar.gz' in same_version_release_dict['filename']: - print "Downloading %s..." % release + print("Downloading %s..." % release) local_file = '%s/%s' % ( self.dirpath, same_version_release_dict["filename"] ) - urllib.urlretrieve( + urllib.request.urlretrieve( same_version_release_dict["url"], local_file ) targz = open(local_file, 'rb').read() hexdigest = hashlib.md5(targz).hexdigest() if (hexdigest != same_version_release_dict['md5_digest']): # NOQA - print FAIL + "FAIL: md5 for %s didn't match!" % release + END # NOQA + print(FAIL + "FAIL: md5 for %s didn't match!" % release + END) # NOQA failed_md5_releases.append(release) else: self.total_downloaded_ok += 1 - print 'Total releases without zip: %s' % len(releases_without_zip) - print 'Total downloaded: %s' % self.total_downloaded_ok + print('Total releases without zip: %s' % len(releases_without_zip)) + print('Total downloaded: %s' % self.total_downloaded_ok) if failed_md5_releases: msg = FAIL + ( "FAIL: these releases %s failed the md5 check!" % @@ -178,14 +178,14 @@ class SetuptoolsOldReleasesWithoutZip(object): ) + END raise Exception(msg) else: - print OK + "All releases downloaded and md5 checked." + END + print(OK + "All releases downloaded and md5 checked." + END) except OSError as e: if e.errno != errno.EEXIST: raise e def convert_targz_to_zip(self): - print "Converting the tar.gz to zip..." + print("Converting the tar.gz to zip...") files = glob.glob('%s/*.tar.gz' % self.dirpath) total_converted = 0 for targz in sorted(files, key=LooseVersion): @@ -198,7 +198,7 @@ class SetuptoolsOldReleasesWithoutZip(object): # Zip the extracted tar. setuptools_folder_path = targz.replace('.tar.gz', '') setuptools_folder_name = setuptools_folder_path.split("/")[-1] - print setuptools_folder_name + print(setuptools_folder_name) shutil.make_archive( setuptools_folder_path, 'zip', @@ -208,17 +208,17 @@ class SetuptoolsOldReleasesWithoutZip(object): # Exclude extracted tar folder. shutil.rmtree(setuptools_folder_path.replace('.zip', '')) total_converted += 1 - print 'Total converted: %s' % total_converted + print('Total converted: %s' % total_converted) if self.total_downloaded_ok != total_converted: msg = FAIL + ( "FAIL: Total number of downloaded releases is different" " from converted ones. Please check the logs." ) + END raise Exception(msg) - print "Done with the tar.gz->zip. Check folder %s." % main.dirpath + print("Done with the tar.gz->zip. Check folder %s." % main.dirpath) def upload_zips_to_pypi(self): - print 'Uploading to pypi...' + print('Uploading to pypi...') zips = sorted(glob.glob('%s/*.zip' % self.dirpath), key=LooseVersion) for zips in glob.glob('%s/*.zip' % self.dirpath): # Put the twine upload code here -- cgit v1.2.1 From fac5dc448b0a4a451da001ab629c134623399cc2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 17:07:42 -0500 Subject: Add twine implementation --- scripts/upload-old-releases-as-zip.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py index 33a3e29c..c1ce41f5 100644 --- a/scripts/upload-old-releases-as-zip.py +++ b/scripts/upload-old-releases-as-zip.py @@ -1,6 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +# declare and require dependencies +__requires__ = [ + 'twine', +]; __import__('pkg_resources') + import errno import glob import hashlib @@ -11,9 +16,11 @@ import tarfile import tempfile import urllib.request, urllib.parse, urllib.error import urllib.request, urllib.error, urllib.parse - from distutils.version import LooseVersion +from twine.commands import upload + + OK = '\033[92m' FAIL = '\033[91m' END = '\033[0m' @@ -221,8 +228,8 @@ class SetuptoolsOldReleasesWithoutZip(object): print('Uploading to pypi...') zips = sorted(glob.glob('%s/*.zip' % self.dirpath), key=LooseVersion) for zips in glob.glob('%s/*.zip' % self.dirpath): - # Put the twine upload code here - pass + print("simulated upload of", zips); continue + upload.upload(dists=list(zips)) if __name__ == '__main__': -- cgit v1.2.1 From 8329fb1ab5832f6ab07ed03929814bc4a4aeecd8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 17:08:25 -0500 Subject: Remove repeat glob code --- scripts/upload-old-releases-as-zip.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py index c1ce41f5..0c722d48 100644 --- a/scripts/upload-old-releases-as-zip.py +++ b/scripts/upload-old-releases-as-zip.py @@ -227,9 +227,8 @@ class SetuptoolsOldReleasesWithoutZip(object): def upload_zips_to_pypi(self): print('Uploading to pypi...') zips = sorted(glob.glob('%s/*.zip' % self.dirpath), key=LooseVersion) - for zips in glob.glob('%s/*.zip' % self.dirpath): - print("simulated upload of", zips); continue - upload.upload(dists=list(zips)) + print("simulated upload of", zips); return + upload.upload(dists=zips) if __name__ == '__main__': -- cgit v1.2.1 From 1837b319518745e80e32a3ec23ccd28b7fec3634 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 17:14:23 -0500 Subject: Reorganize imports --- scripts/upload-old-releases-as-zip.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py index 0c722d48..c7c89fa7 100644 --- a/scripts/upload-old-releases-as-zip.py +++ b/scripts/upload-old-releases-as-zip.py @@ -14,8 +14,9 @@ import os import shutil import tarfile import tempfile -import urllib.request, urllib.parse, urllib.error -import urllib.request, urllib.error, urllib.parse +import urllib.request +import urllib.parse +import urllib.error from distutils.version import LooseVersion from twine.commands import upload -- cgit v1.2.1 From 7ffe08ef8185d87c0dfff1d5567f9d84f8e47ba7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 17:19:48 -0500 Subject: Remove unnecessary __init__ --- scripts/upload-old-releases-as-zip.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py index c7c89fa7..1a638720 100644 --- a/scripts/upload-old-releases-as-zip.py +++ b/scripts/upload-old-releases-as-zip.py @@ -14,6 +14,7 @@ import os import shutil import tarfile import tempfile +import codecs import urllib.request import urllib.parse import urllib.error @@ -32,7 +33,6 @@ class SetuptoolsOldReleasesWithoutZip(object): """docstring for SetuptoolsOldReleases""" def __init__(self): - super(SetuptoolsOldReleasesWithoutZip, self).__init__() self.dirpath = tempfile.mkdtemp(prefix=DISTRIBUTION) print("Downloading %s releases..." % DISTRIBUTION) print("All releases will be downloaded to %s" % self.dirpath) @@ -117,7 +117,10 @@ class SetuptoolsOldReleasesWithoutZip(object): ], """ url = "https://pypi.python.org/pypi/%s/json" % (package_name,) - data = json.load(urllib.request.urlopen(urllib.request.Request(url))) + resp = urllib.request.urlopen(urllib.request.Request(url)) + charset = resp.info().get_content_charset() + reader = codecs.getreader(charset)(resp) + data = json.load(reader) # Mainly for debug. json_filename = "%s/%s.json" % (self.dirpath, DISTRIBUTION) -- cgit v1.2.1 From fcdbdc6fa628daffb6e80d5f333311705f86207a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 17:20:07 -0500 Subject: Remove unnecessary superclass --- scripts/upload-old-releases-as-zip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py index 1a638720..c4b1bfb5 100644 --- a/scripts/upload-old-releases-as-zip.py +++ b/scripts/upload-old-releases-as-zip.py @@ -29,7 +29,7 @@ END = '\033[0m' DISTRIBUTION = "setuptools" -class SetuptoolsOldReleasesWithoutZip(object): +class SetuptoolsOldReleasesWithoutZip: """docstring for SetuptoolsOldReleases""" def __init__(self): -- cgit v1.2.1 From cff3a4820a926b379b5556ab28c9e5bd67152926 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 17 Nov 2015 17:21:39 -0500 Subject: Use a local path rather than a tempdir that never gets cleaned up. --- scripts/upload-old-releases-as-zip.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/upload-old-releases-as-zip.py b/scripts/upload-old-releases-as-zip.py index c4b1bfb5..38cfcd55 100644 --- a/scripts/upload-old-releases-as-zip.py +++ b/scripts/upload-old-releases-as-zip.py @@ -13,7 +13,6 @@ import json import os import shutil import tarfile -import tempfile import codecs import urllib.request import urllib.parse @@ -33,7 +32,8 @@ class SetuptoolsOldReleasesWithoutZip: """docstring for SetuptoolsOldReleases""" def __init__(self): - self.dirpath = tempfile.mkdtemp(prefix=DISTRIBUTION) + self.dirpath = './dist' + os.makedirs(self.dirpath, exist_ok=True) print("Downloading %s releases..." % DISTRIBUTION) print("All releases will be downloaded to %s" % self.dirpath) self.data_json_setuptools = self.get_json_data(DISTRIBUTION) -- cgit v1.2.1 From 32237eae19b3722b2a1c87bc0a74613c5f12d6fd Mon Sep 17 00:00:00 2001 From: sunpoet Date: Fri, 20 Nov 2015 05:54:41 +0800 Subject: Fix package list inconsistency caused by namespace package on Python 3.5 namespace package will be skipped during installation. Since Python 3.5, .pyo files are removed and new .opt-1.pyc (and .opt-2.pyc) files are introduced [1]. However setuptools does not understand that new naming therefore the corresponding foo.opt-1.pyc is still added into package list (via --record). The inconsistency leads to a packaging error. [1] https://www.python.org/dev/peps/pep-0488/ --- setuptools/command/install_lib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 9b772227..78fe6891 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -79,6 +79,8 @@ class install_lib(orig.install_lib): base = os.path.join('__pycache__', '__init__.' + imp.get_tag()) yield base + '.pyc' yield base + '.pyo' + yield base + '.opt-1.pyc' + yield base + '.opt-2.pyc' def copy_tree( self, infile, outfile, -- cgit v1.2.1 From 68e4344ceaff4dd88ffbfbf5370639cc854a8af8 Mon Sep 17 00:00:00 2001 From: grizzlynyo Date: Sat, 21 Nov 2015 14:13:19 +0200 Subject: update certifi to 2015.11.20 --HG-- branch : sync_certifi --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 6226111d..9d7f228d 100755 --- a/setup.py +++ b/setup.py @@ -150,10 +150,10 @@ setup_params = dict( """).strip().splitlines(), extras_require={ "ssl:sys_platform=='win32'": "wincertstore==0.2", - "certs": "certifi==2015.04.28", + "certs": "certifi==2015.11.20", }, dependency_links=[ - 'https://pypi.python.org/packages/source/c/certifi/certifi-2015.04.28.tar.gz#md5=12c7c3a063b2ff97a0f8291d8de41e8c', + 'https://pypi.python.org/packages/source/c/certifi/certifi-2015.11.20.tar.gz#md5=25134646672c695c1ff1593c2dd75d08', 'https://pypi.python.org/packages/source/w/wincertstore/wincertstore-0.2.zip#md5=ae728f2f007185648d0c7a8679b361e2', ], scripts=[], -- cgit v1.2.1 From 864de11cf162c693fe248b609d73545cacb622df Mon Sep 17 00:00:00 2001 From: grizzlynyo Date: Sat, 21 Nov 2015 15:15:23 +0200 Subject: fix an issue for bdist_wininst with gui_scripts: The script header was always generated with non-gui executable. This was caused by by adjust_header assuming the executable is always an absolute path. Fixed by using find_executables() from distutils. --HG-- branch : bdist_wininst_gui_scripts --- setuptools/command/easy_install.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 45d180bb..7ceac03f 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -2137,10 +2137,13 @@ class WindowsScriptWriter(ScriptWriter): pattern, repl = repl, pattern pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE) new_header = pattern_ob.sub(string=orig_header, repl=repl) - clean_header = new_header[2:-1].strip('"') - if sys.platform == 'win32' and not os.path.exists(clean_header): - # the adjusted version doesn't exist, so return the original - return orig_header + if sys.platform == 'win32': + from distutils.spawn import find_executable + + clean_header = new_header[2:-1].strip('"') + if not find_executable(clean_header): + # the adjusted version doesn't exist, so return the original + return orig_header return new_header -- cgit v1.2.1 From aa8a6c90ac9b165ee1c6e6e3d72fff34adba2850 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 27 Nov 2015 21:20:36 -0500 Subject: Update changelog --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index b14e9103..a6b9f720 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,12 @@ CHANGES ======= +---- +18.7 +---- + +* Update dependency on certify. + ------ 18.6.1 ------ -- cgit v1.2.1 From fb2860e63f463355aa3c9e824adff48dfeaad837 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 27 Nov 2015 21:28:59 -0500 Subject: Update changelog --- CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index a6b9f720..73855d1c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,8 @@ CHANGES ---- * Update dependency on certify. +* Pull Request #160: Improve detection of gui script in + ``easy_install._adjust_header``. ------ 18.6.1 -- cgit v1.2.1 From a361ef49cda256e1f53894470cb921d19e04e853 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 27 Nov 2015 21:35:51 -0500 Subject: Extract _use_header method --- setuptools/command/easy_install.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index f3b5fa62..9e9c5e54 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -20,6 +20,7 @@ from distutils.errors import DistutilsArgError, DistutilsOptionError, \ from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS from distutils import log, dir_util from distutils.command.build_scripts import first_line_re +from distutils.spawn import find_executable import sys import os import zipimport @@ -2126,8 +2127,8 @@ class WindowsScriptWriter(ScriptWriter): blockers = [name + x for x in old] yield name + ext, header + script_text, 't', blockers - @staticmethod - def _adjust_header(type_, orig_header): + @classmethod + def _adjust_header(cls, type_, orig_header): """ Make sure 'pythonw' is used for gui and and 'python' is used for console (regardless of what sys.executable is). @@ -2138,14 +2139,19 @@ class WindowsScriptWriter(ScriptWriter): pattern, repl = repl, pattern pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE) new_header = pattern_ob.sub(string=orig_header, repl=repl) - if sys.platform == 'win32': - from distutils.spawn import find_executable - - clean_header = new_header[2:-1].strip('"') - if not find_executable(clean_header): - # the adjusted version doesn't exist, so return the original - return orig_header - return new_header + return new_header if cls._use_header(new_header) else orig_header + + @staticmethod + def _use_header(new_header): + """ + Should _adjust_header use the replaced header? + + On non-windows systems, always use. On + Windows systems, only use the replaced header if it resolves + to an executable on the system. + """ + clean_header = new_header[2:-1].strip('"') + return sys.platform != 'win32' or find_executable(clean_header) class WindowsExecutableLauncherWriter(WindowsScriptWriter): -- cgit v1.2.1 From a63119c9ebd8e7c578203628023877f7aa3f7e97 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 27 Nov 2015 22:41:52 -0500 Subject: Make test.test_args a non-data property per Pull Request #155. --- CHANGES.txt | 2 ++ setuptools/command/test.py | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 73855d1c..f399636f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -10,6 +10,8 @@ CHANGES * Update dependency on certify. * Pull Request #160: Improve detection of gui script in ``easy_install._adjust_header``. +* Made ``test.test_args`` a non-data property; alternate fix + for the issue reported in Pull Request #155. ------ 18.6.1 diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 160e21c9..c26f5fc9 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -41,6 +41,17 @@ class ScanningLoader(TestLoader): return tests[0] # don't create a nested suite for only one return +# adapted from jaraco.classes.properties:NonDataProperty +class NonDataProperty(object): + def __init__(self, fget): + self.fget = fget + + def __get__(self, obj, objtype=None): + if obj is None: + return self + return self.fget(obj) + + class test(Command): """Command to run unit tests after in-place build""" @@ -78,7 +89,7 @@ class test(Command): if self.test_runner is None: self.test_runner = getattr(self.distribution, 'test_runner', None) - @property + @NonDataProperty def test_args(self): return list(self._test_args()) -- cgit v1.2.1 From 1a5cecf5cf61861816a2e02e513256b614b492d8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 27 Nov 2015 22:55:03 -0500 Subject: Update changelog --- CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index f399636f..ebe76433 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -12,6 +12,8 @@ CHANGES ``easy_install._adjust_header``. * Made ``test.test_args`` a non-data property; alternate fix for the issue reported in Pull Request #155. +* Issue #453: In ``ez_setup`` bootstrap module, unload all + ``pkg_resources`` modules following download. ------ 18.6.1 -- cgit v1.2.1 From e99e20ceb50b6292be0d383ec67f2ca6692a6d70 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 27 Nov 2015 23:04:23 -0500 Subject: Update changelog --- CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index ebe76433..fa89b09b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,6 +14,9 @@ CHANGES for the issue reported in Pull Request #155. * Issue #453: In ``ez_setup`` bootstrap module, unload all ``pkg_resources`` modules following download. +* Pull Request #158: Honor `PEP-488 + `_ when excluding + files for namespace packages. ------ 18.6.1 -- cgit v1.2.1 From 141d093b0e7f50459c8053ee4619c9991473be6e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 11:51:17 -0500 Subject: Move test into pkg_resources tests --- pkg_resources/tests/test_pkg_resources.py | 96 +++++++++++++++++++++++++++++++ setuptools/tests/test_egg_info.py | 85 --------------------------- 2 files changed, 96 insertions(+), 85 deletions(-) diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index 564d7cec..257cbb5b 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -5,9 +5,17 @@ import zipfile import datetime import time import subprocess +import stat + +import pytest import pkg_resources +from setuptools.tests.textwrap import DALS +from setuptools.tests import contexts +from setuptools.tests import environment + + try: unicode except NameError: @@ -109,3 +117,91 @@ class TestIndependence: ) cmd = [sys.executable, '-c', '; '.join(lines)] subprocess.check_call(cmd) + + + +class TestEggInfoDistutils(object): + + version = '1.11.0.dev0+2329eae' + setup_script = DALS(""" + from distutils.core import setup + + setup( + name='foo', + py_modules=['hello'], + version='%s', + ) + """) + + def _create_project(self): + with open('setup.py', 'w') as f: + f.write(self.setup_script % self.version) + + with open('hello.py', 'w') as f: + f.write(DALS(""" + def run(): + print('hello') + """)) + + @pytest.yield_fixture + def env(self): + class Environment(str): + pass + with contexts.tempdir(prefix='setuptools-test.') as env_dir: + env = Environment(env_dir) + os.chmod(env_dir, stat.S_IRWXU) + subs = 'home', 'lib', 'scripts', 'data', 'egg-base' + env.paths = dict( + (dirname, os.path.join(env_dir, dirname)) + for dirname in subs + ) + list(map(os.mkdir, env.paths.values())) + config = os.path.join(env.paths['home'], '.pydistutils.cfg') + with open(config, 'w') as f: + f.write(DALS(""" + [egg_info] + egg-base = %(egg-base)s + """ % env.paths)) + yield env + + def test_egg_base_installed_egg_info(self, tmpdir_cwd, env): + self._create_project() + + environ = os.environ.copy().update( + HOME=env.paths['home'], + ) + cmd = [ + 'install', + '--home', env.paths['home'], + '--install-lib', env.paths['lib'], + '--install-scripts', env.paths['scripts'], + '--install-data', env.paths['data'], + ] + code, data = environment.run_setup_py( + cmd=cmd, + pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]), + data_stream=1, + env=environ, + ) + if code: + raise AssertionError(data) + + actual = self._find_egg_info_file(env.paths['lib']) + # On Py3k it can be e.g. foo-1.11.0.dev0_2329eae-py3.4.egg-info + # but 2.7 doesn't add the Python version, so to be expedient we + # just check our start and end, omitting the potential version num + assert actual.startswith('foo-' + self.version.replace('+', '_')) + assert actual.endswith('.egg-info') + # this requirement parsing will raise a VersionConflict unless the + # .egg-info file is parsed (see #419 on BitBucket) + req = pkg_resources.Requirement.parse('foo>=1.9') + dist = pkg_resources.WorkingSet([env.paths['lib']]).find(req) + assert dist.version == self.version + + def _find_egg_info_file(self, root): + # expect exactly one result + result = (filename for dirpath, dirnames, filenames in os.walk(root) + for filename in filenames if filename.endswith('.egg-info')) + result, = result + return result + diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index b4195e06..645c379c 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -6,7 +6,6 @@ import pytest from . import environment from .textwrap import DALS from . import contexts -from pkg_resources import WorkingSet, Requirement class Environment(str): @@ -98,87 +97,3 @@ class TestEggInfo(object): # expect exactly one result result, = results return result - - -class TestEggInfoDistutils(object): - - version = '1.11.0.dev0+2329eae' - setup_script = DALS(""" - from distutils.core import setup - - setup( - name='foo', - py_modules=['hello'], - version='%s', - ) - """) - - def _create_project(self): - with open('setup.py', 'w') as f: - f.write(self.setup_script % self.version) - - with open('hello.py', 'w') as f: - f.write(DALS(""" - def run(): - print('hello') - """)) - - @pytest.yield_fixture - def env(self): - with contexts.tempdir(prefix='setuptools-test.') as env_dir: - env = Environment(env_dir) - os.chmod(env_dir, stat.S_IRWXU) - subs = 'home', 'lib', 'scripts', 'data', 'egg-base' - env.paths = dict( - (dirname, os.path.join(env_dir, dirname)) - for dirname in subs - ) - list(map(os.mkdir, env.paths.values())) - config = os.path.join(env.paths['home'], '.pydistutils.cfg') - with open(config, 'w') as f: - f.write(DALS(""" - [egg_info] - egg-base = %(egg-base)s - """ % env.paths)) - yield env - - def test_egg_base_installed_egg_info(self, tmpdir_cwd, env): - self._create_project() - - environ = os.environ.copy().update( - HOME=env.paths['home'], - ) - cmd = [ - 'install', - '--home', env.paths['home'], - '--install-lib', env.paths['lib'], - '--install-scripts', env.paths['scripts'], - '--install-data', env.paths['data'], - ] - code, data = environment.run_setup_py( - cmd=cmd, - pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]), - data_stream=1, - env=environ, - ) - if code: - raise AssertionError(data) - - actual = self._find_egg_info_file(env.paths['lib']) - # On Py3k it can be e.g. foo-1.11.0.dev0_2329eae-py3.4.egg-info - # but 2.7 doesn't add the Python version, so to be expedient we - # just check our start and end, omitting the potential version num - assert actual.startswith('foo-' + self.version.replace('+', '_')) - assert actual.endswith('.egg-info') - # this requirement parsing will raise a VersionConflict unless the - # .egg-info file is parsed (see #419 on BitBucket) - req = Requirement.parse('foo>=1.9') - dist = WorkingSet([env.paths['lib']]).find(req) - assert dist.version == self.version - - def _find_egg_info_file(self, root): - # expect exactly one result - result = (filename for dirpath, dirnames, filenames in os.walk(root) - for filename in filenames if filename.endswith('.egg-info')) - result, = result - return result -- cgit v1.2.1 From 25fc8c1d05c84ea9d6155be4326e837f90dd173d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 11:54:23 -0500 Subject: Rename test to match intention. --- pkg_resources/tests/test_pkg_resources.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index 257cbb5b..698aefbd 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -164,7 +164,7 @@ class TestEggInfoDistutils(object): """ % env.paths)) yield env - def test_egg_base_installed_egg_info(self, tmpdir_cwd, env): + def test_version_resolved_from_egg_info(self, tmpdir_cwd, env): self._create_project() environ = os.environ.copy().update( -- cgit v1.2.1 From 41868fe7c4f75708b3cb663bf1b76405223869b0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 12:54:28 -0500 Subject: Rewrite test to simply create the egg_info. --- pkg_resources/tests/test_pkg_resources.py | 115 +++++++++--------------------- 1 file changed, 35 insertions(+), 80 deletions(-) diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index 698aefbd..8b9a317a 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -8,13 +8,10 @@ import subprocess import stat import pytest +import py import pkg_resources -from setuptools.tests.textwrap import DALS -from setuptools.tests import contexts -from setuptools.tests import environment - try: unicode @@ -120,88 +117,46 @@ class TestIndependence: -class TestEggInfoDistutils(object): +class TestDeepVersionLookup(object): - version = '1.11.0.dev0+2329eae' - setup_script = DALS(""" - from distutils.core import setup + @pytest.fixture + def env(self, tmpdir): + """ + Create a package environment, similar to a virtualenv, + in which packages are installed. + """ + class Environment(str): + pass - setup( - name='foo', - py_modules=['hello'], - version='%s', + env = Environment(tmpdir) + tmpdir.chmod(stat.S_IRWXU) + subs = 'home', 'lib', 'scripts', 'data', 'egg-base' + env.paths = dict( + (dirname, str(tmpdir / dirname)) + for dirname in subs ) - """) - - def _create_project(self): - with open('setup.py', 'w') as f: - f.write(self.setup_script % self.version) + list(map(os.mkdir, env.paths.values())) + return env - with open('hello.py', 'w') as f: - f.write(DALS(""" - def run(): - print('hello') - """)) + def create_foo_pkg(self, env, version): + """ + Create a foo package installed to env.paths['lib'] + as version. + """ + safe_version = pkg_resources.safe_version(version) + lib = py.path.local(env.paths['lib']) + egg_info = lib / 'foo-' + safe_version + '.egg-info' + egg_info.mkdir() + pkg_info = egg_info / 'PKG_INFO' + with pkg_info.open('w') as strm: + strm.write('version: ' + version) + + def test_version_resolved_from_egg_info(self, env): + version = '1.11.0.dev0+2329eae' + self.create_foo_pkg(env, version) - @pytest.yield_fixture - def env(self): - class Environment(str): - pass - with contexts.tempdir(prefix='setuptools-test.') as env_dir: - env = Environment(env_dir) - os.chmod(env_dir, stat.S_IRWXU) - subs = 'home', 'lib', 'scripts', 'data', 'egg-base' - env.paths = dict( - (dirname, os.path.join(env_dir, dirname)) - for dirname in subs - ) - list(map(os.mkdir, env.paths.values())) - config = os.path.join(env.paths['home'], '.pydistutils.cfg') - with open(config, 'w') as f: - f.write(DALS(""" - [egg_info] - egg-base = %(egg-base)s - """ % env.paths)) - yield env - - def test_version_resolved_from_egg_info(self, tmpdir_cwd, env): - self._create_project() - - environ = os.environ.copy().update( - HOME=env.paths['home'], - ) - cmd = [ - 'install', - '--home', env.paths['home'], - '--install-lib', env.paths['lib'], - '--install-scripts', env.paths['scripts'], - '--install-data', env.paths['data'], - ] - code, data = environment.run_setup_py( - cmd=cmd, - pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]), - data_stream=1, - env=environ, - ) - if code: - raise AssertionError(data) - - actual = self._find_egg_info_file(env.paths['lib']) - # On Py3k it can be e.g. foo-1.11.0.dev0_2329eae-py3.4.egg-info - # but 2.7 doesn't add the Python version, so to be expedient we - # just check our start and end, omitting the potential version num - assert actual.startswith('foo-' + self.version.replace('+', '_')) - assert actual.endswith('.egg-info') # this requirement parsing will raise a VersionConflict unless the # .egg-info file is parsed (see #419 on BitBucket) req = pkg_resources.Requirement.parse('foo>=1.9') dist = pkg_resources.WorkingSet([env.paths['lib']]).find(req) - assert dist.version == self.version - - def _find_egg_info_file(self, root): - # expect exactly one result - result = (filename for dirpath, dirnames, filenames in os.walk(root) - for filename in filenames if filename.endswith('.egg-info')) - result, = result - return result - + assert dist.version == version -- cgit v1.2.1 From 9744cf2edf82eeda796ca22bf21ac0056c8aa925 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 13:00:32 -0500 Subject: Rewrite test to use distutils' install_egg_info to generate the metadata. --- pkg_resources/tests/test_pkg_resources.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index 8b9a317a..0a03dd93 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -6,9 +6,10 @@ import datetime import time import subprocess import stat +import distutils.dist +import distutils.command.install_egg_info import pytest -import py import pkg_resources @@ -117,7 +118,7 @@ class TestIndependence: -class TestDeepVersionLookup(object): +class TestDeepVersionLookupDistutils(object): @pytest.fixture def env(self, tmpdir): @@ -140,16 +141,16 @@ class TestDeepVersionLookup(object): def create_foo_pkg(self, env, version): """ - Create a foo package installed to env.paths['lib'] + Create a foo package installed (distutils-style) to env.paths['lib'] as version. """ - safe_version = pkg_resources.safe_version(version) - lib = py.path.local(env.paths['lib']) - egg_info = lib / 'foo-' + safe_version + '.egg-info' - egg_info.mkdir() - pkg_info = egg_info / 'PKG_INFO' - with pkg_info.open('w') as strm: - strm.write('version: ' + version) + attrs = dict(name='foo', version=version) + dist = distutils.dist.Distribution(attrs) + iei_cmd = distutils.command.install_egg_info.install_egg_info(dist) + iei_cmd.initialize_options() + iei_cmd.install_dir = env.paths['lib'] + iei_cmd.finalize_options() + iei_cmd.run() def test_version_resolved_from_egg_info(self, env): version = '1.11.0.dev0+2329eae' -- cgit v1.2.1 From 423ef416ff975934fc3a2166b7fec76b3861da65 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 13:14:56 -0500 Subject: Rewrite _version_from_file using iterables and filters --- pkg_resources/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 938f4818..59787a95 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2466,11 +2466,11 @@ def _remove_md5_fragment(location): return location -def _version_from_file(fid): - for line in fid: - if line.lower().startswith('version:'): - version = safe_version(line.split(':', 1)[1].strip()) - return version +def _version_from_file(lines): + is_version_line = lambda line: line.lower().startswith('version:') + version_lines = filter(is_version_line, lines) + line = next(iter(version_lines)) + return safe_version(line.split(':', 1)[1].strip()) class Distribution(object): -- cgit v1.2.1 From 498e9d316fad24d848e80a7394c45f2740dd24bb Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 13:16:14 -0500 Subject: Use partition to avoid integer literals --- pkg_resources/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 59787a95..c4071f11 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2470,7 +2470,8 @@ def _version_from_file(lines): is_version_line = lambda line: line.lower().startswith('version:') version_lines = filter(is_version_line, lines) line = next(iter(version_lines)) - return safe_version(line.split(':', 1)[1].strip()) + _, _, value = line.partition(':') + return safe_version(value.strip()) class Distribution(object): -- cgit v1.2.1 From 653987e5827beb668a2b32d9512fc7b238576155 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 13:21:01 -0500 Subject: Return None when no version is encountered. --- pkg_resources/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index c4071f11..9a3ca36c 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2469,9 +2469,9 @@ def _remove_md5_fragment(location): def _version_from_file(lines): is_version_line = lambda line: line.lower().startswith('version:') version_lines = filter(is_version_line, lines) - line = next(iter(version_lines)) + line = next(iter(version_lines), '') _, _, value = line.partition(':') - return safe_version(value.strip()) + return safe_version(value.strip()) or None class Distribution(object): -- cgit v1.2.1 From 87ceb61bbb4a668539111efd84c5e0de7649e097 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 13:21:54 -0500 Subject: Add docstring --- pkg_resources/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 9a3ca36c..e4decac3 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2467,6 +2467,10 @@ def _remove_md5_fragment(location): def _version_from_file(lines): + """ + Given an iterable of lines from a Metadata file, return + the value of the Version field, if present, or None otherwise. + """ is_version_line = lambda line: line.lower().startswith('version:') version_lines = filter(is_version_line, lines) line = next(iter(version_lines), '') -- cgit v1.2.1 From 78b89bdb89e27a165619496fc0b84979664784e3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 13:46:53 -0500 Subject: Extract method for _version_from_egg_info. --- pkg_resources/__init__.py | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index e4decac3..3090dd81 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2497,6 +2497,7 @@ class Distribution(object): @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: # .dist-info gets much metadata differently @@ -2507,26 +2508,34 @@ class Distribution(object): ) cls = _distributionImpl[ext.lower()] - # Some packages e.g. numpy and scipy use distutils instead of - # setuptools, and their version numbers can get mangled when - # converted to filenames (e.g., 1.11.0.dev0+2329eae to - # 1.11.0.dev0_2329eae). These will not be parsed properly - # downstream by Distribution and safe_version, so we need to - # take an extra step and try to get the version number from - # the file itself instead of the filename. - if ext == '.egg-info': - full_name = os.path.join(location, basename + ext) - try: - with open(full_name, 'r') as fid: - version_ = _version_from_file(fid) - version = version_ if version_ is not None else version - except IOError: - pass + version = cls._version_from_egg_info(dist_path) or version return cls( location, metadata, project_name=project_name, version=version, py_version=py_version, platform=platform, **kw ) + @staticmethod + def _version_from_egg_info(dist_path): + """ + Packages installed by distutils (e.g. numpy or scipy), + which uses an old safe_version, and so + their version numbers can get mangled when + converted to filenames (e.g., 1.11.0.dev0+2329eae to + 1.11.0.dev0_2329eae). These distributions will not be + parsed properly + downstream by Distribution and safe_version, so + take an extra step and try to get the version number from + the metadata file itself instead of the filename. + """ + _, ext = os.path.splitext(dist_path) + if ext != '.egg-info' or not os.path.isfile(dist_path): + return + try: + with open(dist_path) as strm: + return _version_from_file(strm) + except IOError: + pass + @property def hashcmp(self): return ( -- cgit v1.2.1 From ca89b06983e1a099bab3a7fe540ef72d210484b3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 14:00:30 -0500 Subject: Encapsulate egg-info special behavior in EggInfoDistribution class. --- pkg_resources/__init__.py | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 3090dd81..631c8547 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2516,25 +2516,7 @@ class Distribution(object): @staticmethod def _version_from_egg_info(dist_path): - """ - Packages installed by distutils (e.g. numpy or scipy), - which uses an old safe_version, and so - their version numbers can get mangled when - converted to filenames (e.g., 1.11.0.dev0+2329eae to - 1.11.0.dev0_2329eae). These distributions will not be - parsed properly - downstream by Distribution and safe_version, so - take an extra step and try to get the version number from - the metadata file itself instead of the filename. - """ - _, ext = os.path.splitext(dist_path) - if ext != '.egg-info' or not os.path.isfile(dist_path): - return - try: - with open(dist_path) as strm: - return _version_from_file(strm) - except IOError: - pass + pass @property def hashcmp(self): @@ -2830,6 +2812,30 @@ class Distribution(object): return [dep for dep in self._dep_map if dep] +class EggInfoDistribution(Distribution): + + @staticmethod + def _version_from_egg_info(dist_path): + """ + Packages installed by distutils (e.g. numpy or scipy), + which uses an old safe_version, and so + their version numbers can get mangled when + converted to filenames (e.g., 1.11.0.dev0+2329eae to + 1.11.0.dev0_2329eae). These distributions will not be + parsed properly + downstream by Distribution and safe_version, so + 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 + + class DistInfoDistribution(Distribution): """Wrap an actual or potential sys.path entry w/metadata, .dist-info style""" PKG_INFO = 'METADATA' @@ -2895,7 +2901,7 @@ class DistInfoDistribution(Distribution): _distributionImpl = { '.egg': Distribution, - '.egg-info': Distribution, + '.egg-info': EggInfoDistribution, '.dist-info': DistInfoDistribution, } -- cgit v1.2.1 From df5516526d165a13c50ef51a392b73955025e7fe Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 14:08:21 -0500 Subject: Rename method as _version_from_metadata. --- pkg_resources/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 631c8547..7c3e18b4 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2500,22 +2500,22 @@ class Distribution(object): dist_path = os.path.join(location, basename) basename, ext = os.path.splitext(basename) if ext.lower() in _distributionImpl: - # .dist-info gets much metadata differently + cls = _distributionImpl[ext.lower()] + match = EGG_NAME(basename) if match: project_name, version, py_version, platform = match.group( 'name', 'ver', 'pyver', 'plat' ) - cls = _distributionImpl[ext.lower()] - version = cls._version_from_egg_info(dist_path) or version + 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 ) @staticmethod - def _version_from_egg_info(dist_path): + def _version_from_metadata(dist_path): pass @property @@ -2815,7 +2815,7 @@ class Distribution(object): class EggInfoDistribution(Distribution): @staticmethod - def _version_from_egg_info(dist_path): + def _version_from_metadata(dist_path): """ Packages installed by distutils (e.g. numpy or scipy), which uses an old safe_version, and so -- cgit v1.2.1 From 65036cf1fd4454d09513482140f1a6524ca66100 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 14:18:09 -0500 Subject: Update changelog. Fixes #419. --- CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index fa89b09b..32e516d5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -17,6 +17,9 @@ CHANGES * Pull Request #158: Honor `PEP-488 `_ when excluding files for namespace packages. +* Issue #419 and Pull Request #144: Add experimental support for + reading the version info from distutils-installed metadata rather + than using the version in the filename. ------ 18.6.1 -- cgit v1.2.1 From e79907fc0a582234cbddcdc964ebf8206120469d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 17:57:44 -0500 Subject: Bumped to 18.7 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 2f5e4856..762e26ba 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.6.2" +DEFAULT_VERSION = "18.7" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 86ad21c6..f6dc6bf4 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.6.2' +__version__ = '18.7' -- cgit v1.2.1 From b7bdb8f00a99a430b4a2ca642978caee682d5911 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 17:57:45 -0500 Subject: Added tag 18.7 for changeset 67d07805606a --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 6ed522b4..075aca30 100644 --- a/.hgtags +++ b/.hgtags @@ -225,3 +225,4 @@ b59320212c8371d0be9e5e6c5f7eec392124c009 18.3 31dc6d2ac0f5ab766652602fe6ca716fff7180e7 18.5 dfe190b09908f6b953209d13573063809de451b8 18.6 804f87045a901f1dc121cf9149143d654228dc13 18.6.1 +67d07805606aead09349d5b91d7d26c68ddad2fc 18.7 -- cgit v1.2.1 From c11203148a150299fac498918b76c0dd83c3fd81 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 28 Nov 2015 17:59:46 -0500 Subject: Bumped to 18.8 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 762e26ba..e0cefe2d 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.7" +DEFAULT_VERSION = "18.8" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index f6dc6bf4..aeb7307b 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.7' +__version__ = '18.8' -- cgit v1.2.1 From 07199bdc471d257822a56fb7c75bc1d4c7ccc36f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 30 Nov 2015 11:27:59 -0500 Subject: Always use Python 3 filter in pkg_resources --- pkg_resources/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 46f09a2d..0bd27d46 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -37,6 +37,7 @@ import plistlib import email.parser import tempfile import textwrap +import itertools from pkgutil import get_importer try: @@ -53,6 +54,7 @@ if PY3: if PY2: from urlparse import urlparse, urlunparse + filter = itertools.ifilter if PY3: string_types = str, -- cgit v1.2.1 From 7a37ebfae2843651e41d481794d19adff2eb110d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 30 Nov 2015 11:28:57 -0500 Subject: Always use Python 3 map in pkg_resources --- pkg_resources/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 0bd27d46..eaebb2fa 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -55,6 +55,7 @@ if PY3: if PY2: from urlparse import urlparse, urlunparse filter = itertools.ifilter + map = itertools.imap if PY3: string_types = str, -- cgit v1.2.1 From dfbc96168d8b921bd6b02fe7aeceeeb930f68cfe Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 09:24:52 -0500 Subject: Add test for regression on Python 3 when LANG=C and there is non-ascii in the metadata file before the version. Ref #469. --- pkg_resources/tests/test_pkg_resources.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index 0a03dd93..31eee635 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -1,3 +1,6 @@ +# coding: utf-8 +from __future__ import unicode_literals + import sys import tempfile import os @@ -144,7 +147,8 @@ class TestDeepVersionLookupDistutils(object): 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() -- cgit v1.2.1 From 18a329d0498b4f3bbe0b5dda8063d1a910cb6945 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 09:26:14 -0500 Subject: Also run the tests with LANG=C --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0097ab89..c5ea0815 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,4 +11,5 @@ script: - python bootstrap.py - python setup.py test --addopts='-rs' + - LANG=C python setup.py test - python ez_setup.py --version 12.2 -- cgit v1.2.1 From 3c257e67279bdb82c2525515bb305816f70c1615 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 09:27:45 -0500 Subject: Always run tests with LANG=C to capture issues in that restrictive environment. --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c5ea0815..4bc6ebd6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,5 @@ script: # update egg_info based on setup.py in checkout - python bootstrap.py - - python setup.py test --addopts='-rs' - - LANG=C python setup.py test + - LANG=C python setup.py test --addopts='-rs' - python ez_setup.py --version 12.2 -- cgit v1.2.1 From e82b7d5a1f8d48f4b957888b6a2e345f06716aee Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 09:29:24 -0500 Subject: Travis has 3.5 now also --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4bc6ebd6..9afbf067 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ python: - 2.7 - 3.3 - 3.4 + - 3.5 - pypy # command to run tests script: -- cgit v1.2.1 From e5b87949322042b310e509c7d332a9beb708935d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 09:34:14 -0500 Subject: Force consistent ordering with PYTHONHASHSEED=0 --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9afbf067..ac12cd7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,12 @@ python: - 3.4 - 3.5 - pypy -# command to run tests +env: + - LANG=C + - PYTHONHASHSEED=0 script: # update egg_info based on setup.py in checkout - python bootstrap.py - - LANG=C python setup.py test --addopts='-rs' + - python setup.py test --addopts='-rs' - python ez_setup.py --version 12.2 -- cgit v1.2.1 From edc8a0e1459cc9c8c08872f5c6262a7ab44dbb15 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 10:11:32 -0500 Subject: I meant for the variables to be defined together --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ac12cd7e..3f7b14b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,7 @@ python: - 3.5 - pypy env: - - LANG=C - - PYTHONHASHSEED=0 + - LANG=C PYTHONHASHSEED=0 script: # update egg_info based on setup.py in checkout - python bootstrap.py -- cgit v1.2.1 From 4660f43ea68a13ddba2de0cdf7da410ea2b3a576 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 10:25:02 -0500 Subject: Try LC_ALL --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3f7b14b4..88b9ed86 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ python: - 3.5 - pypy env: - - LANG=C PYTHONHASHSEED=0 + - LC_ALL=C PYTHONHASHSEED=0 script: # update egg_info based on setup.py in checkout - python bootstrap.py -- cgit v1.2.1 From e36ec568112d58b584383469392ce2e0b43f88e6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 11:09:34 -0500 Subject: Bump version installed by bootstrap tester --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 88b9ed86..cab70640 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,4 +13,4 @@ script: - python bootstrap.py - python setup.py test --addopts='-rs' - - python ez_setup.py --version 12.2 + - python ez_setup.py --version 18.6.1 -- cgit v1.2.1 From 718c66c493beb2e24f7f84a423cec378b7d701a4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 11:11:13 -0500 Subject: Re-use metadata loading functionality from Provider. Fixes #469. --- CHANGES.txt | 7 +++++++ pkg_resources/__init__.py | 23 +++++++---------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 32e516d5..7f7ab9bd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,13 @@ CHANGES ======= +------ +18.7.1 +------ + +* Issue #469: Refactored logic for Issue #419 fix to re-use metadata + loading from Provider. + ---- 18.7 ---- diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index eaebb2fa..fe5c644d 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2507,7 +2507,6 @@ class Distribution(object): @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()] @@ -2517,16 +2516,13 @@ class Distribution(object): 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): @@ -2824,8 +2820,7 @@ class Distribution(object): 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 @@ -2837,13 +2832,9 @@ class EggInfoDistribution(Distribution): 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)) + self._version = md_version or self._version + return self class DistInfoDistribution(Distribution): -- cgit v1.2.1 From d693850138a93b2e46262d33e8c1bc0b9b1a7312 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 11:25:18 -0500 Subject: Leave _version unset if no metadata version was found. --- pkg_resources/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index fe5c644d..c53215c6 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2833,7 +2833,8 @@ class EggInfoDistribution(Distribution): the metadata file itself instead of the filename. """ md_version = _version_from_file(self._get_metadata(self.PKG_INFO)) - self._version = md_version or self._version + if md_version: + self._version = md_version return self -- cgit v1.2.1 From 6081eb70a20b2176386973720bbf6fd5d9846644 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 11:53:50 -0500 Subject: Read metadata as utf-8; Fixes failure when LC_ALL=C --- pkg_resources/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index c53215c6..3cd67fa0 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2021,7 +2021,7 @@ class FileMetadata(EmptyProvider): def get_metadata(self, name): if name=='PKG-INFO': - with open(self.path,'rU') as f: + with io.open(self.path, 'rU', encoding='utf-8') as f: metadata = f.read() return metadata raise KeyError("No metadata except PKG-INFO is available") -- cgit v1.2.1 From 5d6c6a9008fa15d8bd116ba61d968a744d85bda4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 12:24:54 -0500 Subject: Run tests with and without LC_ALL=C --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cab70640..e32524cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,8 @@ python: - 3.5 - pypy env: - - LC_ALL=C PYTHONHASHSEED=0 + - LC_ALL=C + - "" script: # update egg_info based on setup.py in checkout - python bootstrap.py -- cgit v1.2.1 From 81c103f75d22580b14f162103232632444c9ec6f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 12:27:21 -0500 Subject: Expect failure on LC_ALL=C also --- setuptools/tests/test_easy_install.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 66601bfe..fa510098 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -430,8 +430,10 @@ class TestScriptHeader: expected = '#!"%s"\n' % self.exe_with_spaces assert actual == expected + c_type = os.environ.get("LC_CTYPE", os.environ.get("LC_ALL")) + is_ascii = c_type in ("C", "POSIX") @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= -- cgit v1.2.1 From efededd6aa8be5ab054037ee32680a772d06a3c5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 12:41:58 -0500 Subject: Expect failures on these tests due to ASCII --- setuptools/tests/__init__.py | 4 ++++ setuptools/tests/test_easy_install.py | 4 +--- setuptools/tests/test_sdist.py | 8 +++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py index b8a29cba..a93be134 100644 --- a/setuptools/tests/__init__.py +++ b/setuptools/tests/__init__.py @@ -16,6 +16,10 @@ import setuptools.depends as dep 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, "Test fails in this locale") + def makeSetup(**args): """Return distribution from 'setup(**args)', without executing commands""" diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index fa510098..00e16b63 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -35,7 +35,7 @@ import setuptools.tests.server import pkg_resources from .py26compat import tarfile_open -from . import contexts +from . import contexts, is_ascii from .textwrap import DALS @@ -430,8 +430,6 @@ class TestScriptHeader: expected = '#!"%s"\n' % self.exe_with_spaces assert actual == expected - c_type = os.environ.get("LC_CTYPE", os.environ.get("LC_ALL")) - is_ascii = c_type in ("C", "POSIX") @pytest.mark.xfail( compat.PY3 and is_ascii, reason="Test fails in this locale on Python 3" diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 9013b505..4313c456 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -16,6 +16,8 @@ from setuptools.compat import StringIO, unicode, PY3, PY2 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 + SETUP_ATTRS = { 'name': 'sdist_test', @@ -147,6 +149,7 @@ class TestSdistTest: 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) @@ -256,6 +259,7 @@ class TestSdistTest: # 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) @@ -320,9 +324,7 @@ class TestSdistTest: 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) -- cgit v1.2.1 From df2fad0435a7875bbbb2f91240754d85a8aebc1f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 12:45:10 -0500 Subject: Correct usage --- setuptools/tests/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py index a93be134..fed07628 100644 --- a/setuptools/tests/__init__.py +++ b/setuptools/tests/__init__.py @@ -18,7 +18,7 @@ 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, "Test fails in this locale") +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""" -- cgit v1.2.1 From 7cb174c62560328ed051bb9596c4926c8577d3d0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 13:06:48 -0500 Subject: Force later pytest --- .travis.yml | 3 +++ setup.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e32524cc..537e1755 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,9 @@ env: - LC_ALL=C - "" script: + # avoid VersionConflict when newer version is required + - python -m pip install -U pytest + # update egg_info based on setup.py in checkout - python bootstrap.py diff --git a/setup.py b/setup.py index 9d7f228d..dfb578a1 100755 --- a/setup.py +++ b/setup.py @@ -159,7 +159,7 @@ setup_params = dict( scripts=[], tests_require=[ 'setuptools[ssl]', - 'pytest', + 'pytest>=2.8', ] + (['mock'] if sys.version_info[:2] < (3, 3) else []), setup_requires=[ ] + sphinx + pytest_runner, -- cgit v1.2.1 From a477a657941bed882db1eec1deb8339f0af2a14a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 13:09:03 -0500 Subject: Invoke old pip directly --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 537e1755..e8cd2f9a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ env: - "" script: # avoid VersionConflict when newer version is required - - python -m pip install -U pytest + - pip install -U pytest # update egg_info based on setup.py in checkout - python bootstrap.py -- cgit v1.2.1 From fac9d7a483ea00e7627a2890e4f5f5f95a7c975c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 13:10:53 -0500 Subject: Reorder tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e8cd2f9a..f8722567 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,8 @@ python: - 3.5 - pypy env: - - LC_ALL=C - "" + - LC_ALL=C script: # avoid VersionConflict when newer version is required - pip install -U pytest -- cgit v1.2.1 From e7fdbbf85712acea80a591d2ec079b5349a53129 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 13:14:18 -0500 Subject: Try inlining the xfail marker. --- setuptools/tests/test_sdist.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 4313c456..cc7661e6 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -16,7 +16,7 @@ from setuptools.compat import StringIO, unicode, PY3, PY2 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 +from setuptools.tests import fail_on_ascii, is_ascii SETUP_ATTRS = { @@ -149,7 +149,7 @@ class TestSdistTest: assert 'setup.py' not in manifest, manifest assert 'setup.cfg' not in manifest, manifest - @fail_on_ascii + @pytest.mark.xfail(is_ascii, reason="Test fails in this locale") def test_manifest_is_written_with_utf8_encoding(self): # Test for #303. dist = Distribution(SETUP_ATTRS) -- cgit v1.2.1 From 2e46cd7f81c5cf46ae45f8d7687ed4a4f9132a76 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 13:20:47 -0500 Subject: WTF --- setuptools/tests/test_sdist.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index cc7661e6..4d100fad 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -152,6 +152,7 @@ class TestSdistTest: @pytest.mark.xfail(is_ascii, reason="Test fails in this locale") def test_manifest_is_written_with_utf8_encoding(self): # Test for #303. + assert not is_ascii dist = Distribution(SETUP_ATTRS) dist.script_name = 'setup.py' mm = manifest_maker(dist) -- cgit v1.2.1 From b4724ffead99897ce9c1411ff59206977df64f5f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 13:31:01 -0500 Subject: Try setting LC_CTYPE also --- .travis.yml | 2 +- setuptools/tests/test_sdist.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index f8722567..0a798138 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ python: - pypy env: - "" - - LC_ALL=C + - LC_ALL=C LC_CTYPE=C script: # avoid VersionConflict when newer version is required - pip install -U pytest diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 4d100fad..df46518b 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """sdist tests""" -import locale import os import shutil import sys @@ -9,14 +8,12 @@ import tempfile import unicodedata import contextlib -import pytest - import pkg_resources from setuptools.compat import StringIO, unicode, PY3, PY2 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, is_ascii +from setuptools.tests import fail_on_ascii SETUP_ATTRS = { @@ -149,10 +146,9 @@ class TestSdistTest: assert 'setup.py' not in manifest, manifest assert 'setup.cfg' not in manifest, manifest - @pytest.mark.xfail(is_ascii, reason="Test fails in this locale") + @fail_on_ascii def test_manifest_is_written_with_utf8_encoding(self): # Test for #303. - assert not is_ascii dist = Distribution(SETUP_ATTRS) dist.script_name = 'setup.py' mm = manifest_maker(dist) -- cgit v1.2.1 From adcf02655449638849df8a77064b030a22dd648f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 13:59:18 -0500 Subject: Output the env in the test run --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0a798138..0bfb11bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,9 @@ script: # avoid VersionConflict when newer version is required - pip install -U pytest + # Output the env, because the travis docs just can't be trusted + - env + # update egg_info based on setup.py in checkout - python bootstrap.py -- cgit v1.2.1 From 8e0ac92076007aa6e49f22029003b9618605c996 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 14:07:15 -0500 Subject: Expect failure running Python 3 only tests on Python 2 --- setuptools/tests/__init__.py | 1 + setuptools/tests/test_sdist.py | 210 +++++++++++++++++++++-------------------- 2 files changed, 107 insertions(+), 104 deletions(-) diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py index fed07628..f985a6e4 100644 --- a/setuptools/tests/__init__.py +++ b/setuptools/tests/__init__.py @@ -20,6 +20,7 @@ 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 --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index df46518b..2b4d5207 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -8,6 +8,8 @@ import tempfile import unicodedata import contextlib +import pytest + import pkg_resources from setuptools.compat import StringIO, unicode, PY3, PY2 from setuptools.command.sdist import sdist @@ -16,6 +18,9 @@ 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', 'version': '0.0', @@ -181,80 +186,79 @@ class TestSdistTest: assert posix(filename) in u_contents - # Python 3 only - if PY3: + @py3_only + 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() - - # 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 + # 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 + + @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') + + # 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() + + # 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): @@ -288,38 +292,36 @@ class TestSdistTest: 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() - 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 + # The Latin-1 filename should have been skipped + filename = filename.decode('latin-1') + assert filename not in cmd.filelist.files @fail_on_ascii def test_sdist_with_utf8_encoded_filename(self): -- cgit v1.2.1 From dc67e7816dcc9f2f5d2056fe4b4613c74fe1e0d3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 14:08:43 -0500 Subject: Expect fail when LC_ALL=C --- setuptools/tests/test_sdist.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 2b4d5207..ec3c8aa9 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -187,6 +187,7 @@ class TestSdistTest: assert posix(filename) in u_contents @py3_only + @fail_on_ascii def test_write_manifest_allows_utf8_filenames(self): # Test for #303. dist = Distribution(SETUP_ATTRS) -- cgit v1.2.1 From 42cba609fdb7b639b9fa6d48742afceb8b6e93ff Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 14:14:11 -0500 Subject: Bumped to 18.7.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index e0cefe2d..36a09758 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.8" +DEFAULT_VERSION = "18.7.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index aeb7307b..ac653aa1 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.8' +__version__ = '18.7.1' -- cgit v1.2.1 From 7e2d02ab43988a87ec5c2d443f900f382d731b6d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 14:14:13 -0500 Subject: Added tag 18.7.1 for changeset 3041e1fc409b --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 075aca30..508adf5b 100644 --- a/.hgtags +++ b/.hgtags @@ -226,3 +226,4 @@ b59320212c8371d0be9e5e6c5f7eec392124c009 18.3 dfe190b09908f6b953209d13573063809de451b8 18.6 804f87045a901f1dc121cf9149143d654228dc13 18.6.1 67d07805606aead09349d5b91d7d26c68ddad2fc 18.7 +3041e1fc409be90e885968b90faba405420fc161 18.7.1 -- cgit v1.2.1 From dadd14d82c5f1db83704eb1c6da0b62998cb25a7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 14:15:38 -0500 Subject: Bumped to 18.7.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 36a09758..975b45c5 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.7.1" +DEFAULT_VERSION = "18.7.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index ac653aa1..5e40c658 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.7.1' +__version__ = '18.7.2' -- cgit v1.2.1 From 98ea00965bed70ccf57eb58394d15739fb7372ab Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 21:59:33 -0500 Subject: Use context manager for opening file --- setuptools/command/easy_install.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 9e9c5e54..547a8842 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -805,9 +805,8 @@ class easy_install(Command): 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): -- cgit v1.2.1 From 2086ae7b381287872add8fe9a91b74498d501679 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 1 Dec 2015 22:00:45 -0500 Subject: Extract variable --- setuptools/command/easy_install.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 547a8842..79f068b1 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -772,8 +772,8 @@ class easy_install(Command): 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 -- cgit v1.2.1 From 9a86e5c638a16afc092c9895ae24c4669248448e Mon Sep 17 00:00:00 2001 From: Stanislaw Pitucha Date: Mon, 7 Dec 2015 16:13:26 +1100 Subject: Fix multiline strings with missing spaces --- setuptools/dist.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index d7ad4655..03369da8 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -160,7 +160,7 @@ def check_packages(dist, attr, value): for pkgname in value: if not re.match(r'\w+(\.\w+)*', pkgname): distutils.log.warn( - "WARNING: %r not a valid package name; please use only" + "WARNING: %r not a valid package name; please use only " ".-separated package names in setup.py", pkgname ) @@ -818,7 +818,7 @@ class Feature: if not self.available: raise DistutilsPlatformError( - self.description+" is required," + self.description+" is required, " "but is not available on this platform" ) -- cgit v1.2.1 -- cgit v1.2.1 From fc916c8ea1f7ac0ee5cc56dfaa0ab4ef6aee1cfb Mon Sep 17 00:00:00 2001 From: Sachi King Date: Mon, 7 Dec 2015 19:52:21 +1300 Subject: Add get_command_list to dist and process distutils.commands entry points --HG-- branch : get_command_list --- setuptools/dist.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/setuptools/dist.py b/setuptools/dist.py index d7ad4655..c5f04b33 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -440,6 +440,14 @@ class Distribution(_Distribution): self.cmdclass[ep.name] = cmdclass return _Distribution.print_commands(self) + def get_command_list(self): + for ep in pkg_resources.iter_entry_points('distutils.commands'): + if ep.name not in self.cmdclass: + # don't require extras as the commands won't be invoked + cmdclass = ep.resolve() + self.cmdclass[ep.name] = cmdclass + return _Distribution.get_command_list(self) + def _set_feature(self,name,status): """Set feature's inclusion status""" setattr(self,self._feature_attrname(name),status) -- cgit v1.2.1 From bb967deca4ff251c5aa8f0404b1223e94d9a301b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 8 Dec 2015 19:04:13 -0500 Subject: Don't rely on repr for an HTML attribute value (could end up with 'u' prefix). Fixes #471. --- setuptools/package_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index cabf1039..dd2df229 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -1037,7 +1037,7 @@ def local_open(url): break elif os.path.isdir(os.path.join(filename,f)): f+='/' - files.append("%s" % (f,f)) + files.append('{name}'.format(name=f)) else: body = ("%s" % url) + \ "%s" % '\n'.join(files) -- cgit v1.2.1 From 59e47d76244bf25a9c385800328394e97be74b48 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 8 Dec 2015 19:06:03 -0500 Subject: Update syntax for modern style --- setuptools/package_index.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index dd2df229..330b8391 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -1031,12 +1031,12 @@ def local_open(url): 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: + if f == 'index.html': + with open(os.path.join(filename, f), 'r') as fp: body = fp.read() break - elif os.path.isdir(os.path.join(filename,f)): - f+='/' + elif os.path.isdir(os.path.join(filename, f)): + f += '/' files.append('{name}'.format(name=f)) else: body = ("%s" % url) + \ -- cgit v1.2.1 From 5a662289e866fb9bac77736ffede2fca05c79367 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 8 Dec 2015 19:06:41 -0500 Subject: Extract variable --- setuptools/package_index.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 330b8391..1c156f07 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -1031,11 +1031,12 @@ def local_open(url): elif path.endswith('/') and os.path.isdir(filename): files = [] for f in os.listdir(filename): + filepath = os.path.join(filename, f) if f == 'index.html': - with open(os.path.join(filename, f), 'r') as fp: + with open(filepath, 'r') as fp: body = fp.read() break - elif os.path.isdir(os.path.join(filename, f)): + elif os.path.isdir(filepath): f += '/' files.append('{name}'.format(name=f)) else: -- cgit v1.2.1 From 95ac77a928a08c836c6f4ccc066a797357207abc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 8 Dec 2015 19:14:04 -0500 Subject: Use new string formatting here as well --- setuptools/package_index.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 1c156f07..525cb645 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -1040,8 +1040,9 @@ def local_open(url): f += '/' files.append('{name}'.format(name=f)) else: - body = ("%s" % url) + \ - "%s" % '\n'.join(files) + tmpl = ("{url}" + "{files}") + body = tmpl.format(url=url, files='\n'.join(files)) status, message = 200, "OK" else: status, message, body = 404, "Path not found", "Not found" -- cgit v1.2.1 From 434d573a2d4d1c7b00d36f8c4f8b5c4b64b46e63 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 8 Dec 2015 19:36:18 -0500 Subject: Update changelog --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 7f7ab9bd..bacace8d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,13 @@ CHANGES ======= +------ +18.7.2 +------ + +* Issue #471: Don't rely on repr for an HTML attribute value in + package_index. + ------ 18.7.1 ------ -- cgit v1.2.1 From 91afe3b30dd32d439ab8914ba3a80bbe2d9f293c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 8 Dec 2015 21:24:40 -0500 Subject: Avoid errors when metadata directory is broken. Ref #419. --- CHANGES.txt | 2 ++ pkg_resources/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index bacace8d..a48cd3e1 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,6 +9,8 @@ CHANGES * 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. ------ 18.7.1 diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 3cd67fa0..2cb851b1 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2017,7 +2017,7 @@ class FileMetadata(EmptyProvider): 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': -- cgit v1.2.1 From a377c191b9394376988029934ec26f1edaab1812 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 02:45:38 -0500 Subject: Remove deprecated use of 'U' in io.open mode parameter. Fixes #472. --- CHANGES.txt | 2 ++ pkg_resources/__init__.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index a48cd3e1..0fcf4c61 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -11,6 +11,8 @@ CHANGES 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 diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 2cb851b1..f65fef3e 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -2021,7 +2021,7 @@ class FileMetadata(EmptyProvider): def get_metadata(self, name): if name=='PKG-INFO': - with io.open(self.path, 'rU', encoding='utf-8') 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") -- cgit v1.2.1 From e76a139ca4fad75c4ce8b3bc95e0009ea0823eb5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 02:48:31 -0500 Subject: Use io.open in build_py --- setuptools/command/build_py.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index a873d54b..779adf2a 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -5,6 +5,8 @@ import os import sys import fnmatch import textwrap +import io + try: from setuptools.lib2to3_ex import Mixin2to3 @@ -157,7 +159,7 @@ class build_py(orig.build_py, Mixin2to3): else: return init_py - f = open(init_py, 'rbU') + f = io.open(init_py, 'rb') if 'declare_namespace'.encode() not in f.read(): from distutils.errors import DistutilsError -- cgit v1.2.1 From 2ef88b8e709f0c090a3f7f8c7f612aacbbcd648f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 02:49:48 -0500 Subject: Use context manager for closing file --- setuptools/command/build_py.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 779adf2a..c971626c 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -159,7 +159,8 @@ class build_py(orig.build_py, Mixin2to3): else: return init_py - f = io.open(init_py, 'rb') + with io.open(init_py, 'rb') as f: + contents = f.read() if 'declare_namespace'.encode() not in f.read(): from distutils.errors import DistutilsError @@ -169,7 +170,6 @@ class build_py(orig.build_py, Mixin2to3): 'fix it.\n(See the setuptools manual under ' '"Namespace Packages" for details.)\n"' % (package,) ) - f.close() return init_py def initialize_options(self): -- cgit v1.2.1 From d7b8b096a206b178d588049a396d5687dbe7235a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 02:50:30 -0500 Subject: Prefer bytes literal --- setuptools/command/build_py.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index c971626c..f0d76705 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -161,7 +161,7 @@ class build_py(orig.build_py, Mixin2to3): with io.open(init_py, 'rb') as f: contents = f.read() - if 'declare_namespace'.encode() not in f.read(): + if b'declare_namespace' not in f.read(): from distutils.errors import DistutilsError raise DistutilsError( -- cgit v1.2.1 From 2b2c7c76e8eda4c608183c8e75d9eb0123724135 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 02:51:23 -0500 Subject: Move import to top --- setuptools/command/build_py.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index f0d76705..43159c7c 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -6,6 +6,7 @@ import sys import fnmatch import textwrap import io +import distutils.errors try: @@ -162,9 +163,7 @@ class build_py(orig.build_py, Mixin2to3): with io.open(init_py, 'rb') as f: contents = f.read() if b'declare_namespace' not in f.read(): - from distutils.errors import DistutilsError - - raise DistutilsError( + 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 ' -- cgit v1.2.1 From fc28df6ec826b3bd1ffa89d55d3674aa89d2f5fc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 02:52:39 -0500 Subject: Remove hanging indent --- setuptools/command/build_py.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 43159c7c..e729f712 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -183,8 +183,10 @@ class build_py(orig.build_py, Mixin2to3): 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, [])) + globs = ( + self.exclude_package_data.get('', []) + + self.exclude_package_data.get(package, []) + ) bad = [] for pattern in globs: bad.extend( -- cgit v1.2.1 From a0ad4c94c41a9af9f2479567139ba6489305b9cc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 02:59:46 -0500 Subject: Rewrite init/loop/extend as dual-for generator expression. --- setuptools/command/build_py.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index e729f712..5bbf0870 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -187,14 +187,14 @@ class build_py(orig.build_py, Mixin2to3): 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)) - ) + bad = dict.fromkeys( + item + for pattern in globs + for item in fnmatch.filter( + files, + os.path.join(src_dir, convert_path(pattern)), ) - bad = dict.fromkeys(bad) + ) seen = {} return [ f for f in files if f not in bad -- cgit v1.2.1 From 4e960934f61c50b98953d6cd12b72b30e85bccf3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:00:28 -0500 Subject: Prefer set to dict.fromkeys --- setuptools/command/build_py.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 5bbf0870..3ae331fd 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -187,7 +187,7 @@ class build_py(orig.build_py, Mixin2to3): self.exclude_package_data.get('', []) + self.exclude_package_data.get(package, []) ) - bad = dict.fromkeys( + bad = set( item for pattern in globs for item in fnmatch.filter( -- cgit v1.2.1 From 3744e23d533ab5b0ebcb34f6d8792777c3433014 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:14:08 -0500 Subject: Reindent to remove trailing comment --- setuptools/command/build_py.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 3ae331fd..55aed230 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -197,8 +197,12 @@ class build_py(orig.build_py, Mixin2to3): ) seen = {} 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 fn not in seen + and seen.setdefault(fn, 1) ] -- cgit v1.2.1 From a8d85057026bc070b2f73b57133f1910218ad815 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:20:12 -0500 Subject: Use a defaultdict and count to track seen items --- setuptools/command/build_py.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 55aed230..317dbba4 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -7,6 +7,8 @@ import fnmatch import textwrap import io import distutils.errors +import collections +import itertools try: @@ -195,14 +197,13 @@ class build_py(orig.build_py, Mixin2to3): os.path.join(src_dir, convert_path(pattern)), ) ) - seen = {} + seen = collections.defaultdict(itertools.count) return [ fn for fn in files if fn not in bad # ditch dupes - and fn not in seen - and seen.setdefault(fn, 1) + and not next(seen[fn]) ] -- cgit v1.2.1 From 1c7e97f95ea74c241b91dfb975c709940ba00f47 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:26:58 -0500 Subject: Remove unused import --- setuptools/command/build_py.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 317dbba4..b2dafec9 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -2,7 +2,6 @@ from glob import glob from distutils.util import convert_path import distutils.command.build_py as orig import os -import sys import fnmatch import textwrap import io -- cgit v1.2.1 From 41112f5afd0d2b0c14899ab1cf2c27183e64d6ac Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:34:35 -0500 Subject: Use io.open for future compatibility and consistency --- setuptools/command/build_py.py | 2 +- setuptools/command/develop.py | 6 +++--- setuptools/command/egg_info.py | 4 ++-- setuptools/command/sdist.py | 6 ++---- setuptools/tests/test_sdist.py | 18 +++++++++--------- 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index b2dafec9..8a50f032 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -163,7 +163,7 @@ class build_py(orig.build_py, Mixin2to3): with io.open(init_py, 'rb') as f: contents = f.read() - if b'declare_namespace' not in 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 " diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 5ae25d71..3a16cdc7 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -3,6 +3,7 @@ from distutils import log 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 @@ -163,9 +164,8 @@ class develop(easy_install): 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 --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 50f3d5c0..9a9193c1 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -10,6 +10,7 @@ import distutils.filelist import os import re import sys +import io try: from setuptools_svn import svn_utils @@ -471,10 +472,9 @@ def get_pkg_info_revision(): # a subversion revision # if os.path.exists('PKG-INFO'): - f = open('PKG-INFO', 'rU') + 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)) - f.close() return 0 diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index 851a1775..71196512 100755 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -3,6 +3,7 @@ from distutils import log 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 @@ class sdist(orig.sdist): 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 --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index ec3c8aa9..8ec9a4cb 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -7,6 +7,7 @@ import sys import tempfile import unicodedata import contextlib +import io import pytest @@ -81,6 +82,11 @@ def decompose(path): return path +def read_all_bytes(filename): + with io.open(filename, 'rb') as fp: + return fp.read() + + class TestSdistTest: def setup_method(self, method): @@ -172,9 +178,7 @@ class TestSdistTest: 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') @@ -210,9 +214,7 @@ class TestSdistTest: # Re-write manifest 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 contents.decode('UTF-8') @@ -248,9 +250,7 @@ class TestSdistTest: # Re-write manifest 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 contents.decode('UTF-8') -- cgit v1.2.1 From 50d864aa0693530a70efd6ffc8007d8328bfea6d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:35:46 -0500 Subject: Reindent --- setuptools/command/egg_info.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 9a9193c1..fb94a044 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -472,9 +472,9 @@ def get_pkg_info_revision(): # a subversion revision # if os.path.exists('PKG-INFO'): - 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)) + 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 -- cgit v1.2.1 From 1265c31f954afe7a1e47edc6dddfe7a5d4c9aa2a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:40:13 -0500 Subject: Replace comment with docstring --- setuptools/command/egg_info.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index fb94a044..57e89c07 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -468,9 +468,10 @@ def write_entries(cmd, basename, filename): 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. + """ if os.path.exists('PKG-INFO'): with io.open('PKG-INFO') as f: for line in f: -- cgit v1.2.1 From ebaf4f2547e71247248abc77f9899e2106482646 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:51:59 -0500 Subject: Deprecate get_pkg_info_revision --- CHANGES.txt | 7 ++++--- setuptools/command/egg_info.py | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 0fcf4c61..cb9bb02d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,10 +3,11 @@ CHANGES ======= ------- -18.7.2 ------- +---- +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 diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 57e89c07..3afd0a45 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -11,6 +11,7 @@ import os import re import sys import io +import warnings try: from setuptools_svn import svn_utils @@ -472,6 +473,7 @@ def get_pkg_info_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'): with io.open('PKG-INFO') as f: for line in f: -- cgit v1.2.1 From 6840f40ad0cc4df8c98cd8b78f4c86d6200c1b57 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:53:38 -0500 Subject: Remove check that would never succeed, because svn_utils always returns an integer and get_svn_revision always returns a non-empty string. --- setuptools/command/egg_info.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 3afd0a45..28aa7994 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -186,9 +186,7 @@ class egg_info(Command): 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 -- cgit v1.2.1 From 2a379eac97f2defcb828589ad5b46ace8a54d0f5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:54:32 -0500 Subject: Reorganize imports --- setuptools/command/egg_info.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 28aa7994..8b393a71 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -13,11 +13,6 @@ import sys import io import warnings -try: - from setuptools_svn import svn_utils -except ImportError: - pass - from setuptools import Command from setuptools.command.sdist import sdist from setuptools.compat import basestring, PY3, StringIO @@ -29,6 +24,12 @@ import setuptools.unicode_utils as unicode_utils 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" -- cgit v1.2.1 From 81ca4fea9e4672f39864439f2049108ad731c8fa Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 9 Dec 2015 03:57:25 -0500 Subject: Move imports to top --- setuptools/command/egg_info.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 8b393a71..1301bd84 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -12,11 +12,15 @@ import re import sys import io import warnings +import time + +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) @@ -61,8 +65,6 @@ class egg_info(Command): 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, @@ -189,8 +191,6 @@ class egg_info(Command): if self.tag_svn_revision: version += '-r%s' % self.get_svn_revision() if self.tag_date: - import time - version += time.strftime("-%Y%m%d") return version @@ -391,7 +391,6 @@ def write_pkg_info(cmd, basename, filename): 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) -- cgit v1.2.1 From 76ffa368456be9ecbcb81a8ba3196f1246e444c0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:04:44 -0500 Subject: Use context manager for opening file --- setuptools/command/develop.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 3a16cdc7..85118767 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -125,9 +125,8 @@ class develop(easy_install): # 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) -- cgit v1.2.1 From 07037d10760792ffe616349ab7642b2fce0a0527 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:07:13 -0500 Subject: Extract variable, avoiding hanging indent. --- setuptools/command/develop.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 85118767..07b66ccb 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -54,8 +54,8 @@ class develop(easy_install): # 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) -- cgit v1.2.1 From 5ba1d009e2c44b63fc2d2e1de09fd1d768c10fca Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:13:30 -0500 Subject: Use context for opening file. --- setuptools/package_index.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 525cb645..f81b8d78 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -359,8 +359,9 @@ class PackageIndex(Environment): self.scan_egg_link(item, entry) def scan_egg_link(self, path, entry): - lines = [_f for _f in map(str.strip, - open(os.path.join(path, entry))) if _f] + 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: for dist in find_distributions(os.path.join(path, lines[0])): dist.location = os.path.join(path, *lines) -- cgit v1.2.1 From cd28f4e0eddf3f571cb0efe05a23fa4a7a254de7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:16:25 -0500 Subject: Replace nested code with short-circuit return. --- setuptools/package_index.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index f81b8d78..5adb8c2b 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -362,11 +362,15 @@ class PackageIndex(Environment): 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: - 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) + + if len(lines) != 2: + # format is not recognized; punt + return + + 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) def process_index(self,url,page): """Process the contents of a PyPI page""" -- cgit v1.2.1 From 2f7d95690e53fe92a82b055b82c4dc02b6a3339c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:18:38 -0500 Subject: Extract variables for improved documentation. --- setuptools/package_index.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 5adb8c2b..36231f11 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -367,7 +367,9 @@ class PackageIndex(Environment): # format is not recognized; punt return - for dist in find_distributions(os.path.join(path, lines[0])): + 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) -- cgit v1.2.1 From dacc24690e7c8503744ce433aae6dd74a50e2337 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:26:16 -0500 Subject: Extract if in for loop --- setuptools/package_index.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 36231f11..00ce3ea5 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -352,8 +352,8 @@ class PackageIndex(Environment): self.warn(msg, url) def scan_egg_links(self, search_path): - for item in search_path: - if os.path.isdir(item): + dirs = filter(os.path.isdir, search_path) + for item in dirs: for entry in os.listdir(item): if entry.endswith('.egg-link'): self.scan_egg_link(item, entry) -- cgit v1.2.1 From 6b8c9181fbb0ef5b223ba45ed361991c601d1d13 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:28:36 -0500 Subject: Get filter from the future --- setuptools/compat.py | 4 ++++ setuptools/package_index.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/setuptools/compat.py b/setuptools/compat.py index 73e6e4aa..68ec97d4 100644 --- a/setuptools/compat.py +++ b/setuptools/compat.py @@ -29,6 +29,8 @@ if PY2: 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 @@ if PY3: urlunsplit, splittag, ) filterfalse = itertools.filterfalse + filter = filter + map = map def reraise(tp, value, tb=None): if value.__traceback__ is not tb: diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 00ce3ea5..095688f9 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -20,7 +20,7 @@ from setuptools.compat import (urllib2, httplib, StringIO, HTTPError, urlparse, urlunparse, unquote, splituser, url2pathname, name2codepoint, unichr, urljoin, urlsplit, urlunsplit, - ConfigParser) + ConfigParser, filter) from setuptools.compat import filterfalse from fnmatch import translate from setuptools.py26compat import strip_fragment -- cgit v1.2.1 From 6667ea387d5694cf936644898acd20000ca7b1ec Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:34:36 -0500 Subject: Replace nested for loop with dual-for generator expression. --- setuptools/package_index.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 095688f9..3456f715 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -6,6 +6,7 @@ import shutil import socket import base64 import hashlib +import itertools from functools import wraps from pkg_resources import ( @@ -353,10 +354,13 @@ class PackageIndex(Environment): def scan_egg_links(self, search_path): dirs = filter(os.path.isdir, search_path) - for item in dirs: - for entry in os.listdir(item): - if entry.endswith('.egg-link'): - self.scan_egg_link(item, entry) + 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): with open(os.path.join(path, entry)) as raw_lines: -- cgit v1.2.1 From e99626c4eadf2e45ca5d729aaa3a5b4bb667536b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:36:25 -0500 Subject: Reclaim space from hanging indents --- setuptools/package_index.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 3456f715..b0837628 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -17,11 +17,11 @@ from pkg_resources import ( 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, filter) +from setuptools.compat import ( + urllib2, httplib, StringIO, HTTPError, urlparse, urlunparse, unquote, + splituser, url2pathname, name2codepoint, unichr, urljoin, urlsplit, + urlunsplit, ConfigParser, filter, +) from setuptools.compat import filterfalse from fnmatch import translate from setuptools.py26compat import strip_fragment -- cgit v1.2.1 From 6a10b4afbad5dca346b7fc7a5d8bb6d08d3286b2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 10:37:09 -0500 Subject: Also use map from the future --- setuptools/package_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index b0837628..7c071457 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -20,7 +20,7 @@ from distutils.errors import DistutilsError from setuptools.compat import ( urllib2, httplib, StringIO, HTTPError, urlparse, urlunparse, unquote, splituser, url2pathname, name2codepoint, unichr, urljoin, urlsplit, - urlunsplit, ConfigParser, filter, + urlunsplit, ConfigParser, filter, map, ) from setuptools.compat import filterfalse from fnmatch import translate -- cgit v1.2.1 From f351891c97500738be1f23b5e83b955e2d5bdd23 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 12:26:46 -0500 Subject: Bumped to 18.8 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 975b45c5..e0cefe2d 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.7.2" +DEFAULT_VERSION = "18.8" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 5e40c658..aeb7307b 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.7.2' +__version__ = '18.8' -- cgit v1.2.1 From 6f9eccba4ca2404ad476ef121226489296171a03 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 12:26:47 -0500 Subject: Added tag 18.8 for changeset c811801ffa1d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 508adf5b..b34cd7fa 100644 --- a/.hgtags +++ b/.hgtags @@ -227,3 +227,4 @@ dfe190b09908f6b953209d13573063809de451b8 18.6 804f87045a901f1dc121cf9149143d654228dc13 18.6.1 67d07805606aead09349d5b91d7d26c68ddad2fc 18.7 3041e1fc409be90e885968b90faba405420fc161 18.7.1 +c811801ffa1de758cf01fbf6a86e4c04ff0c0935 18.8 -- cgit v1.2.1 From 7fd5df90d1f251a22bdb74bed21cebf298b6a8e8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 11 Dec 2015 12:28:10 -0500 Subject: Bumped to 18.9 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index e0cefe2d..6b869656 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.8" +DEFAULT_VERSION = "18.9" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index aeb7307b..9c79593e 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.8' +__version__ = '18.9' -- cgit v1.2.1 From a627cf9a72f8fca78b0520b72a5b44a0bbea9b8c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 10:05:24 -0500 Subject: Add test capturing infinite recursion. Ref #440. --- setuptools/tests/test_sandbox.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index 6e1e9e1c..624954df 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -100,3 +100,13 @@ class TestExceptionSaver: 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. + """ + sandbox = setuptools.sandbox + with sandbox.save_modules(): + sandbox.hide_setuptools() + raise sandbox.SandboxViolation('test') -- cgit v1.2.1 From bf8331685d1d5bb88cc6cf09236601f0dbe62330 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 10:45:04 -0500 Subject: Refine test to not make additional references to exceptions in setuptools.sandbox, but instead create a bespoke unpickleable exception. Ref #440. --- setuptools/tests/test_sandbox.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index 624954df..a54c2fa0 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -106,7 +106,15 @@ class TestExceptionSaver: As revealed in #440, an infinite recursion can occur if an unpickleable exception while setuptools is hidden. Ensure this doesn't happen. """ - sandbox = setuptools.sandbox - with sandbox.save_modules(): - sandbox.hide_setuptools() - raise sandbox.SandboxViolation('test') + class ExceptionUnderTest(Exception): + """ + An unpickleable exception (not in globals). + """ + + with pytest.raises(setuptools.sandbox.UnpickleableException) as exc: + with setuptools.sandbox.save_modules(): + setuptools.sandbox.hide_setuptools() + raise ExceptionUnderTest() + + msg, = exc.value.args + assert msg == 'ExceptionUnderTest()' -- cgit v1.2.1 From 264b5dc6b9cf48b22bd2263d426026d7b8f45608 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 10:48:20 -0500 Subject: Prevent infinite recursion when UnpickleableException occurs in a sandbox context. Fixes #440. --- CHANGES.txt | 9 +++++++++ setuptools/sandbox.py | 6 ++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index cb9bb02d..ff31275a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,15 @@ CHANGES ======= +------ +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 ---- diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 213cebff..b8b1bac1 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -98,8 +98,8 @@ class UnpickleableException(Exception): """ 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 @@ class UnpickleableException(Exception): 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))) -- cgit v1.2.1 From ce481836f31142b939f4b93a6eba90630ba354fd Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 11:00:02 -0500 Subject: caught is a better name here --- setuptools/tests/test_sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index a54c2fa0..40bd2ebe 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -111,10 +111,10 @@ class TestExceptionSaver: An unpickleable exception (not in globals). """ - with pytest.raises(setuptools.sandbox.UnpickleableException) as exc: + with pytest.raises(setuptools.sandbox.UnpickleableException) as caught: with setuptools.sandbox.save_modules(): setuptools.sandbox.hide_setuptools() raise ExceptionUnderTest() - msg, = exc.value.args + msg, = caught.value.args assert msg == 'ExceptionUnderTest()' -- cgit v1.2.1 From 3915be7722713c51aab291ed9720c7b83585d2b5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 11:10:33 -0500 Subject: Add another test capturing violated expectation that SandboxViolation would be raised in a sandbox/hidden_setuptools context. Ref #440. --- setuptools/tests/test_sandbox.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index 40bd2ebe..fefd46f7 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -118,3 +118,24 @@ class TestExceptionSaver: 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 == {} -- cgit v1.2.1 From 1d74aaab3372b6727158802c610043ca036ce5d3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 11:29:01 -0500 Subject: Always import for SandboxViolation so it's pickleable. Ref #440. --- setuptools/sandbox.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index b8b1bac1..85de85ff 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -384,6 +384,7 @@ class DirectorySandbox(AbstractSandbox): AbstractSandbox.__init__(self) def _violation(self, operation, *args, **kw): + from setuptools.sandbox import SandboxViolation raise SandboxViolation(operation, args, kw) if _file: -- cgit v1.2.1 From fa91749d1272c8a00c0c779a4ae9969ff277ee45 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 11:57:40 -0500 Subject: Bumped to 18.8.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index 6b869656..bbc4c926 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.9" +DEFAULT_VERSION = "18.8.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 9c79593e..bd0d8b71 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.9' +__version__ = '18.8.1' -- cgit v1.2.1 From 54852faf6a8c5f1383ac59243dc1e9bcafbbcfc2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 11:57:42 -0500 Subject: Added tag 18.8.1 for changeset fbf06fa35f93 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index b34cd7fa..ee080d5d 100644 --- a/.hgtags +++ b/.hgtags @@ -228,3 +228,4 @@ dfe190b09908f6b953209d13573063809de451b8 18.6 67d07805606aead09349d5b91d7d26c68ddad2fc 18.7 3041e1fc409be90e885968b90faba405420fc161 18.7.1 c811801ffa1de758cf01fbf6a86e4c04ff0c0935 18.8 +fbf06fa35f93a43f044b1645a7e4ff470edb462c 18.8.1 -- cgit v1.2.1 From 17d7ac38c0570bee51f3f202138d522a4cdf5669 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 11:58:57 -0500 Subject: Bumped to 18.8.2 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index bbc4c926..bd2acccd 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.8.1" +DEFAULT_VERSION = "18.8.2" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index bd0d8b71..067c5e37 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.8.1' +__version__ = '18.8.2' -- cgit v1.2.1 From 5eafe7644d18eddd77a5573ecc30b4c98efbb2c6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 14 Dec 2015 04:12:53 -0500 Subject: Prefer setdefault to hasattr/setattr --- setuptools/dist.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index d7ad4655..b0c52838 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -267,8 +267,7 @@ class Distribution(_Distribution): if attrs and 'setup_requires' in attrs: self.fetch_build_eggs(attrs['setup_requires']) for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): - if not hasattr(self,ep.name): - setattr(self,ep.name,None) + vars(self).setdefault(ep.name, None) _Distribution.__init__(self,attrs) if isinstance(self.metadata.version, numbers.Number): # Some people apparently take "version number" too literally :) -- cgit v1.2.1 From 2f0e172bdab76b0c972b5d1480bcccc88f63c7ec Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 14 Dec 2015 04:48:26 -0500 Subject: Add test capturing InterpolationSyntaxError on Python 3 and KeyError on Python 2 --- setuptools/tests/test_packageindex.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index dcd90d6f..897590e8 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -1,7 +1,11 @@ +from __future__ import absolute_import + import sys +import os import distutils.errors from setuptools.compat import httplib, HTTPError, unicode, pathname2url +from .textwrap import DALS import pkg_resources import setuptools.package_index @@ -201,3 +205,20 @@ class TestContentCheckers: 'http://foo/bar#md5=f12895fdffbd45007040d2e44df98478') rep = checker.report(lambda x: x, 'My message about %s') assert rep == 'My message about md5' + + +class TestPyPIConfig: + def test_percent_in_password(self, tmpdir, monkeypatch): + monkeypatch.setitem(os.environ, 'HOME', str(tmpdir)) + pypirc = tmpdir / '.pypirc' + with pypirc.open('w') as strm: + strm.write(DALS(""" + [pypi] + repository=https://pypi.python.org + username=jaraco + password=pity% + """)) + cfg = setuptools.package_index.PyPIConfig() + cred = cfg.creds_by_repository['pypi'] + assert cred.username == 'jaraco' + assert cred.password == 'pity%' -- cgit v1.2.1 From 477fef2d71db14b82d74ea73f4f90e02876d1967 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 14 Dec 2015 04:51:03 -0500 Subject: Add test capturing InterpolationSyntaxError on Python 3. Ref #442 --- setuptools/tests/test_packageindex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index 897590e8..746860d5 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -219,6 +219,6 @@ class TestPyPIConfig: password=pity% """)) cfg = setuptools.package_index.PyPIConfig() - cred = cfg.creds_by_repository['pypi'] + cred = cfg.creds_by_repository['https://pypi.python.org'] assert cred.username == 'jaraco' assert cred.password == 'pity%' -- cgit v1.2.1 From ca4321bb5833e2daa7bee1a32a3dee37cb49f012 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 14 Dec 2015 04:55:43 -0500 Subject: Use the modern name for the configparser module --- setuptools/command/easy_install.py | 8 ++++---- setuptools/command/setopt.py | 4 ++-- setuptools/compat.py | 4 ++-- setuptools/package_index.py | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 79f068b1..9ca3b515 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1402,7 +1402,7 @@ def expand_paths(inputs): def extract_wininst_cfg(dist_filename): """Extract configuration data from a bdist_wininst .exe - Returns a ConfigParser.RawConfigParser, or None + Returns a configparser.RawConfigParser, or None """ f = open(dist_filename, 'rb') try: @@ -1415,7 +1415,7 @@ def extract_wininst_cfg(dist_filename): return None f.seek(prepended - 12) - from setuptools.compat import StringIO, ConfigParser + from setuptools.compat import StringIO, configparser import struct tag, cfglen, bmlen = struct.unpack(" Date: Mon, 14 Dec 2015 05:31:46 -0500 Subject: Use SafeConfigParser in PyPIConfig file. Allows percent signs to be specified using two percent signs. Fixes #442. --- CHANGES.txt | 8 ++++++++ setuptools/package_index.py | 4 ++-- setuptools/tests/test_packageindex.py | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index ff31275a..1396d5fe 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,14 @@ CHANGES ======= +---- +19.0 +---- + +* Issue #442: Use SafeConfigParser for parsing .pypirc file. Now + fields containing the percent symbol (%) must have each percent + replaced with two percent symbols (%%). + ------ 18.8.1 ------ diff --git a/setuptools/package_index.py b/setuptools/package_index.py index a26b58bc..322f9a61 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -945,14 +945,14 @@ class Credential(object): def __str__(self): return '%(username)s:%(password)s' % vars(self) -class PyPIConfig(configparser.ConfigParser): +class PyPIConfig(configparser.SafeConfigParser): def __init__(self): """ Load from ~/.pypirc """ defaults = dict.fromkeys(['username', 'password', 'repository'], '') - configparser.ConfigParser.__init__(self, defaults) + configparser.SafeConfigParser.__init__(self, defaults) rc = os.path.join(os.path.expanduser('~'), '.pypirc') if os.path.exists(rc): diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index 746860d5..a3e45adc 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -216,7 +216,7 @@ class TestPyPIConfig: [pypi] repository=https://pypi.python.org username=jaraco - password=pity% + password=pity%% """)) cfg = setuptools.package_index.PyPIConfig() cred = cfg.creds_by_repository['https://pypi.python.org'] -- cgit v1.2.1 From fbcbb51009bc76df9f2c66547439474799b9ab15 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 14 Dec 2015 05:38:30 -0500 Subject: Use RawConfigParser instead of SafeConfigParser in PyPIConfig class. Interpolated values are no longer supported. Since backward compatibility could not be retained in either case, prefer the simpler, more direct format. Ref #442. --- CHANGES.txt | 5 ++--- setuptools/package_index.py | 4 ++-- setuptools/tests/test_packageindex.py | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 1396d5fe..355c7550 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -7,9 +7,8 @@ CHANGES 19.0 ---- -* Issue #442: Use SafeConfigParser for parsing .pypirc file. Now - fields containing the percent symbol (%) must have each percent - replaced with two percent symbols (%%). +* Issue #442: Use RawConfigParser for parsing .pypirc file. + Interpolated values are no longer honored in .pypirc files. ------ 18.8.1 diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 322f9a61..2c565e88 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -945,14 +945,14 @@ class Credential(object): def __str__(self): return '%(username)s:%(password)s' % vars(self) -class PyPIConfig(configparser.SafeConfigParser): +class PyPIConfig(configparser.RawConfigParser): def __init__(self): """ Load from ~/.pypirc """ defaults = dict.fromkeys(['username', 'password', 'repository'], '') - configparser.SafeConfigParser.__init__(self, defaults) + configparser.RawConfigParser.__init__(self, defaults) rc = os.path.join(os.path.expanduser('~'), '.pypirc') if os.path.exists(rc): diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index a3e45adc..746860d5 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -216,7 +216,7 @@ class TestPyPIConfig: [pypi] repository=https://pypi.python.org username=jaraco - password=pity%% + password=pity% """)) cfg = setuptools.package_index.PyPIConfig() cred = cfg.creds_by_repository['https://pypi.python.org'] -- cgit v1.2.1 From 4765b89927b56b4ae8758b18d8cdd822d9007dae Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 19:47:38 -0500 Subject: Bumped to 19.0 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index bd2acccd..eacaff17 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "18.8.2" +DEFAULT_VERSION = "19.0" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 067c5e37..3b7740f1 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '18.8.2' +__version__ = '19.0' -- cgit v1.2.1 From 2b175325dc6a0516dbfeb902d2fc15e2b5f240ec Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 19:47:40 -0500 Subject: Added tag 19.0 for changeset cc41477ecf92 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index ee080d5d..85ed0095 100644 --- a/.hgtags +++ b/.hgtags @@ -229,3 +229,4 @@ dfe190b09908f6b953209d13573063809de451b8 18.6 3041e1fc409be90e885968b90faba405420fc161 18.7.1 c811801ffa1de758cf01fbf6a86e4c04ff0c0935 18.8 fbf06fa35f93a43f044b1645a7e4ff470edb462c 18.8.1 +cc41477ecf92f221c113736fac2830bf8079d40c 19.0 -- cgit v1.2.1 From 627d4b47c20ca79cd3ce1bb99d1b54ccf457a561 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 19:49:02 -0500 Subject: Bumped to 19.1 in preparation for next release. --- ez_setup.py | 2 +- setuptools/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index eacaff17..da0f034d 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -30,7 +30,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "19.0" +DEFAULT_VERSION = "19.1" DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir diff --git a/setuptools/version.py b/setuptools/version.py index 3b7740f1..a4bfb3ca 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '19.0' +__version__ = '19.1' -- cgit v1.2.1 From 8427babe8e6418012cec2c408fee0eb95b4564a9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 20:57:20 -0500 Subject: ez_setup now loads latest version using metadata --- ez_setup.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index da0f034d..bd73ca9d 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -16,7 +16,8 @@ import subprocess import platform import textwrap import contextlib -import warnings +import json +import codecs from distutils import log @@ -30,7 +31,8 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "19.1" +LATEST = object() +DEFAULT_VERSION = LATEST DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir @@ -140,6 +142,7 @@ def use_setuptools( Return None. Raise SystemExit if the requested version or later cannot be installed. """ + version = _resolve_version(version) to_dir = os.path.abspath(to_dir) # prior to importing, capture the module state for @@ -321,6 +324,7 @@ def download_setuptools( ``downloader_factory`` should be a function taking no arguments and returning a function for downloading a URL to a target. """ + version = _resolve_version(version) # making sure we use the absolute path to_dir = os.path.abspath(to_dir) zip_name = "setuptools-%s.zip" % version @@ -333,6 +337,27 @@ def download_setuptools( return os.path.realpath(saveto) +def _resolve_version(version): + """ + Resolve LATEST version + """ + if version is not LATEST: + return version + + with urlopen('https://pypi.python.org/pypi/setuptools/json') as resp: + charset = resp.info().get_content_charset() + reader = codecs.getreader(charset) + doc = json.load(reader(resp)) + + def by_vals(ver_string): + try: + return tuple(map(int, ver_string.split('.'))) + except Exception: + return (0,) + + return max(doc['releases'], key=by_vals) + + def _build_install_args(options): """ Build the arguments to 'python setup.py install' on the setuptools package. -- cgit v1.2.1 From d150f9d4b67300a7f4c557a5c95252a947558201 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 21:10:43 -0500 Subject: Just use the indicated version directly. --- ez_setup.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ez_setup.py b/ez_setup.py index bd73ca9d..c0991861 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -349,13 +349,7 @@ def _resolve_version(version): reader = codecs.getreader(charset) doc = json.load(reader(resp)) - def by_vals(ver_string): - try: - return tuple(map(int, ver_string.split('.'))) - except Exception: - return (0,) - - return max(doc['releases'], key=by_vals) + return doc['info']['version'] def _build_install_args(options): -- cgit v1.2.1 From 5919897c159a1d5b093107dde380f3c1c81f356a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 21:26:21 -0500 Subject: Use contextlib.closing for the response --- ez_setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ez_setup.py b/ez_setup.py index c0991861..d8c3305e 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -344,7 +344,8 @@ def _resolve_version(version): if version is not LATEST: return version - with urlopen('https://pypi.python.org/pypi/setuptools/json') as resp: + resp = urlopen('https://pypi.python.org/pypi/setuptools/json') + with contextlib.closing(resp): charset = resp.info().get_content_charset() reader = codecs.getreader(charset) doc = json.load(reader(resp)) -- cgit v1.2.1 From 70fb4bec6c4a8fd5cb82cab29efb4a2ce8d227b0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 21:31:04 -0500 Subject: Restore Python 2.7 compatibility --- ez_setup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ez_setup.py b/ez_setup.py index d8c3305e..1320ac92 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -346,7 +346,11 @@ def _resolve_version(version): resp = urlopen('https://pypi.python.org/pypi/setuptools/json') with contextlib.closing(resp): - charset = resp.info().get_content_charset() + try: + charset = resp.info().get_content_charset() + except Exception: + # Python 2 compat; assume UTF-8 + charset = 'UTF-8' reader = codecs.getreader(charset) doc = json.load(reader(resp)) -- cgit v1.2.1 From 7217bff3e01372a98ec19ad29079a8c1680b9500 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 21:31:49 -0500 Subject: release script no longer mutates ez_setup.py --- release.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/release.py b/release.py index a76d2de4..22aeae02 100644 --- a/release.py +++ b/release.py @@ -19,9 +19,7 @@ def before_upload(): def after_push(): BootstrapBookmark.push() -files_with_versions = ( - 'ez_setup.py', 'setuptools/version.py', -) +files_with_versions = 'setuptools/version.py', # bdist_wheel must be included or pip will break dist_commands = 'sdist', 'bdist_wheel' -- cgit v1.2.1 From 2fa748c3eb25908ff3fe6e3e256638562c614aed Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 21:37:14 -0500 Subject: No longer need to specify a version in the test run. --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0bfb11bb..54d9c395 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,4 +20,6 @@ script: - python bootstrap.py - python setup.py test --addopts='-rs' - - python ez_setup.py --version 18.6.1 + + # test the bootstrap script + - python ez_setup.py -- cgit v1.2.1 From 2a24c4c7f67090f4ea73d42a2442b5eaf55d4f39 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 15 Dec 2015 21:52:49 -0500 Subject: Update changelog --- CHANGES.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 355c7550..4bd8c4a6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,14 @@ CHANGES ======= +---- +19.1 +---- + +* The bootstrap script ``ez_setup.py`` now automatically detects + the latest version of setuptools (using PyPI JSON API) rather + than hard-coding a particular value. + ---- 19.0 ---- -- cgit v1.2.1 From 6d8ecefd8e915a8ec4e73649b3e352b7d48931f2 Mon Sep 17 00:00:00 2001 From: lsenta Date: Wed, 16 Dec 2015 12:15:53 +0100 Subject: Fixes #475: correct a typo in metadata environment marker evaluation --- pkg_resources/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index f65fef3e..b55e4127 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -1537,7 +1537,7 @@ class MarkerEvaluation(object): """ return dict( (key.replace('.', '_'), value) - for key, value in env + for key, value in env.items() ) @classmethod -- cgit v1.2.1 From 1542dc13b25c29ae8ccdda47bc2260572c9d1327 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 08:02:19 -0500 Subject: Update changelog --- CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.txt b/CHANGES.txt index 4bd8c4a6..f68cd418 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -10,6 +10,7 @@ CHANGES * The bootstrap script ``ez_setup.py`` now automatically detects the latest version of setuptools (using PyPI JSON API) rather than hard-coding a particular value. +* Issue #475: Fix incorrect usage in _translate_metadata2. ---- 19.0 -- cgit v1.2.1 From 89a239d8a2e2dc0dc42d717ad131957f1063a456 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 08:04:01 -0500 Subject: Now that bootstrap script automatically installs the latest published version, it's no longer necessary to track the _current_ bootstrap version with a bookmark. --- release.py | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/release.py b/release.py index 22aeae02..dd1d6a1c 100644 --- a/release.py +++ b/release.py @@ -4,21 +4,12 @@ install jaraco.packaging and run 'python -m jaraco.packaging.release' """ import os -import subprocess import pkg_resources pkg_resources.require('jaraco.packaging>=2.0') pkg_resources.require('wheel') - -def before_upload(): - BootstrapBookmark.add() - - -def after_push(): - BootstrapBookmark.push() - files_with_versions = 'setuptools/version.py', # bdist_wheel must be included or pip will break @@ -27,22 +18,3 @@ dist_commands = 'sdist', 'bdist_wheel' test_info = "Travis-CI tests: http://travis-ci.org/#!/jaraco/setuptools" os.environ["SETUPTOOLS_INSTALL_WINDOWS_SPECIFIC_FILES"] = "1" - -class BootstrapBookmark: - name = 'bootstrap' - - @classmethod - def add(cls): - cmd = ['hg', 'bookmark', '-i', cls.name, '-f'] - subprocess.Popen(cmd) - - @classmethod - def push(cls): - """ - Push the bootstrap bookmark - """ - push_command = ['hg', 'push', '-B', cls.name] - # don't use check_call here because mercurial will return a non-zero - # code even if it succeeds at pushing the bookmark (because there are - # no changesets to be pushed). !dm mercurial - subprocess.call(push_command) -- cgit v1.2.1 From 4e64dd995a2d3c07efb9472bbd2cd6045d515046 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 08:10:00 -0500 Subject: Update changelog to reference ticket --- CHANGES.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index f68cd418..4e71bd72 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -7,7 +7,8 @@ CHANGES 19.1 ---- -* The bootstrap script ``ez_setup.py`` now automatically detects +* Issue #215: The bootstrap script ``ez_setup.py`` now + automatically detects the latest version of setuptools (using PyPI JSON API) rather than hard-coding a particular value. * Issue #475: Fix incorrect usage in _translate_metadata2. -- cgit v1.2.1 From 2776f28710f3a7e034bb5166e43e150275062c3e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 08:18:05 -0500 Subject: Added tag 19.1 for changeset 834782ce4915 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 85ed0095..f8f7ee7c 100644 --- a/.hgtags +++ b/.hgtags @@ -230,3 +230,4 @@ dfe190b09908f6b953209d13573063809de451b8 18.6 c811801ffa1de758cf01fbf6a86e4c04ff0c0935 18.8 fbf06fa35f93a43f044b1645a7e4ff470edb462c 18.8.1 cc41477ecf92f221c113736fac2830bf8079d40c 19.0 +834782ce49154e9744e499e00eb392c347f9e034 19.1 -- cgit v1.2.1 From cfcfccb6c78490ed368fa08d7ee84418ac4706a6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 08:19:26 -0500 Subject: Bumped to 19.2 in preparation for next release. --- setuptools/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/version.py b/setuptools/version.py index a4bfb3ca..16f3f638 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '19.1' +__version__ = '19.2' -- cgit v1.2.1 From d8a425e00d05c0cd0896b6e684b18304c6bbf717 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 19:05:43 -0500 Subject: In resolve version, always cast to a string (avoiding Unicode on Python 2). Fixes #476. --- CHANGES.txt | 7 +++++++ ez_setup.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 4e71bd72..3764d799 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,13 @@ CHANGES ======= +------ +19.1.1 +------ + +* Issue #476: Cast version to string (using default encoding) + to avoid creating Unicode types on Python 2 clients. + ---- 19.1 ---- diff --git a/ez_setup.py b/ez_setup.py index 1320ac92..39ea44bc 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -354,7 +354,7 @@ def _resolve_version(version): reader = codecs.getreader(charset) doc = json.load(reader(resp)) - return doc['info']['version'] + return str(doc['info']['version']) def _build_install_args(options): -- cgit v1.2.1 From 156bf219d2e9c99b3a241fa59dd4c652cfa90a45 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 19:10:07 -0500 Subject: Explicitly quote strings rather than relying on repr. Fixes #477. --- CHANGES.txt | 3 +++ ez_setup.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 3764d799..48fc18a9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,6 +9,9 @@ CHANGES * Issue #476: Cast version to string (using default encoding) to avoid creating Unicode types on Python 2 clients. +* Issue #477: In Powershell downloader, use explicit rendering + of strings, rather than rely on ``repr``, which can be + incorrect (especially on Python 2). ---- 19.1 diff --git a/ez_setup.py b/ez_setup.py index 39ea44bc..16f707a6 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -225,7 +225,7 @@ def download_file_powershell(url, target): ps_cmd = ( "[System.Net.WebRequest]::DefaultWebProxy.Credentials = " "[System.Net.CredentialCache]::DefaultCredentials; " - "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)" + '(new-object System.Net.WebClient).DownloadFile("%(url)s", "%(target)s")' % vars() ) cmd = [ -- cgit v1.2.1 From 0923ea577d1374b39a4d5e57688c0c9739ed3734 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 19:10:27 -0500 Subject: Prefer locals to vars --- ez_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ez_setup.py b/ez_setup.py index 16f707a6..9715bdc7 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -226,7 +226,7 @@ def download_file_powershell(url, target): "[System.Net.WebRequest]::DefaultWebProxy.Credentials = " "[System.Net.CredentialCache]::DefaultCredentials; " '(new-object System.Net.WebClient).DownloadFile("%(url)s", "%(target)s")' - % vars() + % locals() ) cmd = [ 'powershell', -- cgit v1.2.1 From 79d6a93283b6fab9a1aa8f63a0024eff43f88716 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 19:27:29 -0500 Subject: Bumped to 19.1.1 in preparation for next release. --- setuptools/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/version.py b/setuptools/version.py index 16f3f638..1ed11507 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '19.2' +__version__ = '19.1.1' -- cgit v1.2.1 From 4e75ee7fc0fa6bc9ff00bbc338ca883f0f21f968 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 19:27:30 -0500 Subject: Added tag 19.1.1 for changeset 0a2a3d89416e --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index f8f7ee7c..eb98b62a 100644 --- a/.hgtags +++ b/.hgtags @@ -231,3 +231,4 @@ c811801ffa1de758cf01fbf6a86e4c04ff0c0935 18.8 fbf06fa35f93a43f044b1645a7e4ff470edb462c 18.8.1 cc41477ecf92f221c113736fac2830bf8079d40c 19.0 834782ce49154e9744e499e00eb392c347f9e034 19.1 +0a2a3d89416e1642cf6f41d22dbc07b3d3c15a4d 19.1.1 -- cgit v1.2.1 From 8a91baa090870aa3e70ea26c716ccde955ec1381 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 16 Dec 2015 19:29:18 -0500 Subject: Bumped to 19.1.2 in preparation for next release. --- setuptools/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/version.py b/setuptools/version.py index 1ed11507..961ff96e 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '19.1.1' +__version__ = '19.1.2' -- cgit v1.2.1 From 3f4ef89512da6a3e89f27121446ec59773869017 Mon Sep 17 00:00:00 2001 From: Erik Bray Date: Wed, 23 Dec 2015 14:07:40 -0500 Subject: Fix failing test on Windows due to path separator --- setuptools/tests/test_setuptools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py index 8aca593a..e59800d2 100644 --- a/setuptools/tests/test_setuptools.py +++ b/setuptools/tests/test_setuptools.py @@ -23,7 +23,7 @@ def test_findall(example_source): def test_findall_curdir(example_source): with example_source.as_cwd(): found = list(setuptools.findall()) - expected = ['readme.txt', 'foo/bar.py'] + expected = ['readme.txt', os.path.join('foo', 'bar.py')] assert found == expected -- cgit v1.2.1 From 2f2011b3d9e21861f003181ab0c3abb9701df83b Mon Sep 17 00:00:00 2001 From: Erik Bray Date: Thu, 24 Dec 2015 15:45:14 -0500 Subject: Fix failing test on Windows due to path formatting bugs --- setuptools/tests/test_easy_install.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 00e16b63..f0330f17 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -446,10 +446,15 @@ class TestScriptHeader: exe = tmpdir / 'exe.py' with exe.open('w') as f: f.write(header) - exe = str(exe) + + exe = ei.nt_quote_arg(os.path.normpath(str(exe))) + + # Make sure Windows paths are quoted properly before they're sent + # through shlex.split by get_script_header + executable = '"%s"' % exe if os.path.splitdrive(exe)[0] else exe header = ei.ScriptWriter.get_script_header('#!/usr/local/bin/python', - executable=exe) + executable=executable) assert header == '#!/usr/bin/env %s\n' % exe expect_out = 'stdout' if sys.version_info < (2,7) else 'stderr' @@ -458,7 +463,7 @@ class TestScriptHeader: # When options are included, generate a broken shebang line # with a warning emitted candidate = ei.ScriptWriter.get_script_header('#!/usr/bin/python -x', - executable=exe) + executable=executable) assert candidate == '#!%s -x\n' % exe output = locals()[expect_out] assert 'Unable to adapt shebang line' in output.getvalue() -- cgit v1.2.1 From 9578a0f640dac57f95a391c9f2a1ebdaba1a0846 Mon Sep 17 00:00:00 2001 From: Erik Bray Date: Thu, 24 Dec 2015 16:16:19 -0500 Subject: Prevent exception in atexit handlers when cert store's tempfile is already cleaned up by py.test. --- setuptools/ssl_support.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setuptools/ssl_support.py b/setuptools/ssl_support.py index cc7db067..7394f4f5 100644 --- a/setuptools/ssl_support.py +++ b/setuptools/ssl_support.py @@ -223,6 +223,12 @@ def get_win_certfile(): self.addcerts(certs) atexit.register(self.close) + def close(self): + try: + super(MyCertFile, self).close() + except OSError: + pass + _wincerts = MyCertFile(stores=['CA', 'ROOT']) return _wincerts.name -- cgit v1.2.1 From 3172bf9505e5d6b6f95b8b6a7f3dbde9cfe4ce48 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 25 Dec 2015 09:56:47 -0500 Subject: Update changelog --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 48fc18a9..005f2ce6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,12 @@ CHANGES ======= +---- +19.2 +---- + +* Pull Request #163: Add get_command_list method to Distribution. + ------ 19.1.1 ------ -- cgit v1.2.1 From 57809ecf386e1c87bfbed81baf4a3d7f9af9dbbe Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 25 Dec 2015 10:23:52 -0500 Subject: Separate _find_egg_info_files into two methods, one for each of the needed outputs. --- setuptools/tests/test_egg_info.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 74beb7f5..e92ef920 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -60,7 +60,7 @@ class TestEggInfo(object): self._create_project() self._run_install_command(tmpdir_cwd, env) - _, actual = self._find_egg_info_files(env.paths['lib']) + actual = self._find_egg_info_files(env.paths['lib']) expected = [ 'PKG-INFO', @@ -83,7 +83,7 @@ class TestEggInfo(object): } }) self._run_install_command(tmpdir_cwd, env) - egg_info_dir, _ = self._find_egg_info_files(env.paths['lib']) + egg_info_dir = self._find_egg_info_dir(env.paths['lib']) sources_txt = os.path.join(egg_info_dir, 'SOURCES.txt') assert 'docs/usage.rst' in open(sources_txt).read().split('\n') @@ -107,12 +107,15 @@ class TestEggInfo(object): if code: raise AssertionError(data) - def _find_egg_info_files(self, root): + def _find_egg_info_dir(self, root): results = ( - (dirpath, filenames) + dirpath for dirpath, dirnames, filenames in os.walk(root) if os.path.basename(dirpath) == 'EGG-INFO' ) # expect exactly one result result, = results return result + + def _find_egg_info_files(self, root): + return os.listdir(self._find_egg_info_dir(root)) -- cgit v1.2.1 From f4ad85091ab6a78134de046ef5c7a57cffa273ac Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 25 Dec 2015 10:28:25 -0500 Subject: Wrap the result in a DirList to avoid tuple unpacking and unused variables --- setuptools/tests/test_egg_info.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 74beb7f5..333d11d6 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -60,7 +60,7 @@ class TestEggInfo(object): self._create_project() self._run_install_command(tmpdir_cwd, env) - _, actual = self._find_egg_info_files(env.paths['lib']) + actual = self._find_egg_info_files(env.paths['lib']) expected = [ 'PKG-INFO', @@ -83,7 +83,7 @@ class TestEggInfo(object): } }) self._run_install_command(tmpdir_cwd, env) - egg_info_dir, _ = self._find_egg_info_files(env.paths['lib']) + egg_info_dir = self._find_egg_info_files(env.paths['lib']).base sources_txt = os.path.join(egg_info_dir, 'SOURCES.txt') assert 'docs/usage.rst' in open(sources_txt).read().split('\n') @@ -108,8 +108,13 @@ class TestEggInfo(object): raise AssertionError(data) def _find_egg_info_files(self, root): + class DirList(list): + def __init__(self, files, base): + super(DirList, self).__init__(files) + self.base = base + results = ( - (dirpath, filenames) + DirList(filenames, dirpath) for dirpath, dirnames, filenames in os.walk(root) if os.path.basename(dirpath) == 'EGG-INFO' ) -- cgit v1.2.1 From 81f26b644ab1bbb56eb0b2161a0aec752c51bf54 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 25 Dec 2015 10:49:28 -0500 Subject: Update changelog --- CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 005f2ce6..7ed7434b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,8 @@ CHANGES ---- * Pull Request #163: Add get_command_list method to Distribution. +* Pull Request #162: Add missing whitespace to multiline string + literals. ------ 19.1.1 -- cgit v1.2.1 From c8deca55f387fe2be58842a610aea761d642725c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 25 Dec 2015 10:52:52 -0500 Subject: Bumped to 19.2 in preparation for next release. --- setuptools/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/version.py b/setuptools/version.py index 961ff96e..16f3f638 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '19.1.2' +__version__ = '19.2' -- cgit v1.2.1 From b5b4ff480354eb52f17835cad6c828f12d2d5b6c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 25 Dec 2015 10:52:54 -0500 Subject: Added tag 19.2 for changeset 5d24cf9d1ced --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index eb98b62a..60ce3f94 100644 --- a/.hgtags +++ b/.hgtags @@ -232,3 +232,4 @@ fbf06fa35f93a43f044b1645a7e4ff470edb462c 18.8.1 cc41477ecf92f221c113736fac2830bf8079d40c 19.0 834782ce49154e9744e499e00eb392c347f9e034 19.1 0a2a3d89416e1642cf6f41d22dbc07b3d3c15a4d 19.1.1 +5d24cf9d1ced76c406ab3c4a94c25d1fe79b94bc 19.2 -- cgit v1.2.1 From 6bdbe8957d8c8d293e3fea3fa4baf45eb7c3a3a4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 25 Dec 2015 10:54:28 -0500 Subject: Bumped to 19.3 in preparation for next release. --- setuptools/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/version.py b/setuptools/version.py index 16f3f638..09bbb730 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '19.2' +__version__ = '19.3' -- cgit v1.2.1