From 0239a4da1d74ac9b5ff948ab88fabf8a59fbb6d4 Mon Sep 17 00:00:00 2001 From: Melvyn Sopacua Date: Sat, 5 Jul 2014 17:43:39 +0200 Subject: Fix exclude list on python 3.2+ imp.get_tag() is only available on 3.2+. Since 2 Date: Sat, 5 Jul 2014 18:41:12 +0200 Subject: Commit the fix we did when testing python3 I shall `hg status` before submitting PRs. I shall `hg status` before submitting PRs. I shall `hg status` before submitting PRs. --- setuptools/command/install_lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index cf5375f6..7692e0f3 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -18,7 +18,7 @@ class install_lib(orig.install_lib): .single_version_externally_managed) exclude_names = ['__init__.py', '__init__.pyc', '__init__.pyo'] if hasattr(imp, 'get_tag') : - exclude_names.extend( + exclude_names.extend(( os.path.join( '__pycache__', '__init__.' + imp.get_tag() + '.pyc' @@ -27,7 +27,7 @@ class install_lib(orig.install_lib): '__pycache__', '__init__.' + imp.get_tag() + '.pyo' ), - ) + )) if svem: for pkg in nsp: parts = pkg.split('.') -- cgit v1.2.1 From 51a264643308ae8da841e8e2309076d821f03359 Mon Sep 17 00:00:00 2001 From: Hugues Lerebours Date: Mon, 18 Aug 2014 14:11:34 +0200 Subject: [Fix/Typo] Fix missing parenthesis in egg_info.py Syntax error introduced in be37eff86c761a399c1ec98b0e5eeed9a90c9cd7 --- setuptools/command/egg_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 1ef723da..06764a17 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -389,7 +389,7 @@ def write_toplevel_names(cmd, basename, filename): for k in cmd.distribution.iter_distribution_names() ] ) - cmd.write_file("top-level names", filename, '\n'.join(sorted(pkgs) + '\n') + cmd.write_file("top-level names", filename, '\n'.join(sorted(pkgs)) + '\n') def overwrite_arg(cmd, basename, filename): -- cgit v1.2.1 From 72b042153ae0eb2c2a17c540eb187df98318d8c3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 9 Sep 2014 09:38:58 -0400 Subject: Move sister functions into proximity --- pkg_resources.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pkg_resources.py b/pkg_resources.py index ee2c553b..23ac1a36 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -81,15 +81,6 @@ try: except ImportError: pass -def _bypass_ensure_directory(name, mode=0o777): - # Sandbox-bypassing version of ensure_directory() - if not WRITE_SUPPORT: - raise IOError('"os.mkdir" not supported on this platform.') - dirname, filename = split(name) - if dirname and filename and not isdir(dirname): - _bypass_ensure_directory(dirname) - mkdir(dirname, mode) - _state_vars = {} @@ -2824,6 +2815,17 @@ def ensure_directory(path): if not os.path.isdir(dirname): os.makedirs(dirname) + +def _bypass_ensure_directory(name, mode=0o777): + """Sandbox-bypassing version of ensure_directory()""" + if not WRITE_SUPPORT: + raise IOError('"os.mkdir" not supported on this platform.') + dirname, filename = split(name) + if dirname and filename and not isdir(dirname): + _bypass_ensure_directory(dirname) + mkdir(dirname, mode) + + def split_sections(s): """Split a string or iterable thereof into (section, content) pairs -- cgit v1.2.1 From 2a4496eb6a1d6ddcc33508cf0434006b60773a79 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 9 Sep 2014 09:39:47 -0400 Subject: Rename argument for consistency --- pkg_resources.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg_resources.py b/pkg_resources.py index 23ac1a36..08983919 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -2816,11 +2816,11 @@ def ensure_directory(path): os.makedirs(dirname) -def _bypass_ensure_directory(name, mode=0o777): +def _bypass_ensure_directory(path, mode=0o777): """Sandbox-bypassing version of ensure_directory()""" if not WRITE_SUPPORT: raise IOError('"os.mkdir" not supported on this platform.') - dirname, filename = split(name) + dirname, filename = split(path) if dirname and filename and not isdir(dirname): _bypass_ensure_directory(dirname) mkdir(dirname, mode) -- cgit v1.2.1 From 26fe77d1d26c087281562e0bd761e8f0a8fcc8bd Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 18 Sep 2014 07:13:18 -0400 Subject: Add indicators for PY2 vs. PY3 --- pkg_resources.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg_resources.py b/pkg_resources.py index 08983919..9992b17d 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -35,6 +35,9 @@ import email.parser import tempfile from pkgutil import get_importer +PY3 = sys.version_info > (3,) +PY2 = not PY3 + try: from urlparse import urlparse, urlunparse except ImportError: -- cgit v1.2.1 From 07097b102aaf0e0064579560474c8de150389fff Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 18 Sep 2014 07:16:33 -0400 Subject: Remove conditional import for frozenset (available in Python 2.6+) --- pkg_resources.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg_resources.py b/pkg_resources.py index 9992b17d..a0566688 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -43,10 +43,6 @@ try: except ImportError: from urllib.parse import urlparse, urlunparse -try: - frozenset -except NameError: - from sets import ImmutableSet as frozenset try: basestring next = lambda o: o.next() -- cgit v1.2.1 From d57fce3c23369b8d7fc3caea11ec0c4e45b05b03 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 18 Sep 2014 07:21:24 -0400 Subject: Use PY3/PY2 indicators to reliably select behavior. Fixes #237 --- CHANGES.txt | 8 ++++++++ pkg_resources.py | 17 +++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 83b05bbe..185052fb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,14 @@ CHANGES ======= +--- +5.8 +--- + +* Issue #237: ``pkg_resources`` now uses explicit detection of Python 2 vs. + Python 3, supporting environments where builtins have been patched to make + Python 3 look more like Python 2. + --- 5.7 --- diff --git a/pkg_resources.py b/pkg_resources.py index a0566688..5dcfd66e 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -38,16 +38,13 @@ from pkgutil import get_importer PY3 = sys.version_info > (3,) PY2 = not PY3 -try: - from urlparse import urlparse, urlunparse -except ImportError: +if PY3: from urllib.parse import urlparse, urlunparse -try: - basestring - next = lambda o: o.next() - from cStringIO import StringIO as BytesIO -except NameError: +if PY2: + from urlparse import urlparse, urlunparse + +if PY3: basestring = str from io import BytesIO def execfile(fn, globs=None, locs=None): @@ -57,6 +54,10 @@ except NameError: locs = globs exec(compile(open(fn).read(), fn, 'exec'), globs, locs) +if PY2: + next = lambda o: o.next() + from cStringIO import StringIO as BytesIO + # capture these to bypass sandboxing from os import utime try: -- cgit v1.2.1 From e6e5c60cc48a9a0aa003d834fb21b96c655fd5a5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 18 Sep 2014 07:25:45 -0400 Subject: next function and io module are available on Python 2.6 --- pkg_resources.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg_resources.py b/pkg_resources.py index 5dcfd66e..d8c73320 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -16,6 +16,7 @@ method. import sys import os +import io import time import re import imp @@ -46,7 +47,6 @@ if PY2: if PY3: basestring = str - from io import BytesIO def execfile(fn, globs=None, locs=None): if globs is None: globs = globals() @@ -54,10 +54,6 @@ if PY3: locs = globs exec(compile(open(fn).read(), fn, 'exec'), globs, locs) -if PY2: - next = lambda o: o.next() - from cStringIO import StringIO as BytesIO - # capture these to bypass sandboxing from os import utime try: @@ -1378,7 +1374,7 @@ class NullProvider: return self._fn(self.module_path, resource_name) def get_resource_stream(self, manager, resource_name): - return BytesIO(self.get_resource_string(manager, resource_name)) + return io.BytesIO(self.get_resource_string(manager, resource_name)) def get_resource_string(self, manager, resource_name): return self._get(self._fn(self.module_path, resource_name)) -- cgit v1.2.1 From 9cf8c1b38252f97169864d7742d82d7e1c3e61f6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 18 Sep 2014 07:31:09 -0400 Subject: Use the term 'string_types', following the pattern in six --- pkg_resources.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pkg_resources.py b/pkg_resources.py index d8c73320..825b3004 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -46,13 +46,15 @@ if PY2: from urlparse import urlparse, urlunparse if PY3: - basestring = str + string_types = str, def execfile(fn, globs=None, locs=None): if globs is None: globs = globals() if locs is None: locs = globs exec(compile(open(fn).read(), fn, 'exec'), globs, locs) +else: + string_types = str, eval('unicode') # capture these to bypass sandboxing from os import utime @@ -330,7 +332,7 @@ run_main = run_script def get_distribution(dist): """Return a current distribution object for a Requirement or string""" - if isinstance(dist, basestring): + if isinstance(dist, string_types): dist = Requirement.parse(dist) if isinstance(dist, Requirement): dist = get_provider(dist) @@ -2050,8 +2052,8 @@ def _set_parent_ns(packageName): def yield_lines(strs): - """Yield non-empty/non-comment lines of a ``basestring`` or sequence""" - if isinstance(strs, basestring): + """Yield non-empty/non-comment lines of a string or sequence""" + if isinstance(strs, string_types): for s in strs.splitlines(): s = s.strip() # skip blank lines/comments @@ -2643,8 +2645,7 @@ def issue_warning(*args,**kw): def parse_requirements(strs): """Yield ``Requirement`` objects for each specification in `strs` - `strs` must be an instance of ``basestring``, or a (possibly-nested) - iterable thereof. + `strs` must be a string, or a (possibly-nested) iterable thereof. """ # create a steppable iterator, so we can handle \-continuations lines = iter(yield_lines(strs)) @@ -2745,7 +2746,7 @@ class Requirement: # only get if we need it if self.index: item = item.parsed_version - elif isinstance(item, basestring): + elif isinstance(item, string_types): item = parse_version(item) last = None # -1, 0, 1 -- cgit v1.2.1 From 6cfe52d5176b00474971b0778a7c87555047cf9f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 18 Sep 2014 07:34:23 -0400 Subject: Remove execfile compatibility - unnecessary on Python 2.6+ --- pkg_resources.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pkg_resources.py b/pkg_resources.py index 825b3004..517298c9 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -47,12 +47,6 @@ if PY2: if PY3: string_types = str, - def execfile(fn, globs=None, locs=None): - if globs is None: - globs = globals() - if locs is None: - locs = globs - exec(compile(open(fn).read(), fn, 'exec'), globs, locs) else: string_types = str, eval('unicode') @@ -1424,7 +1418,9 @@ class NullProvider: script_filename = self._fn(self.egg_info, script) namespace['__file__'] = script_filename if os.path.exists(script_filename): - execfile(script_filename, namespace, namespace) + source = open(script_filename).read() + code = compile(source, script_filename, 'exec') + exec(code, namespace, namespace) else: from linecache import cache cache[script_filename] = ( -- cgit v1.2.1 -- cgit v1.2.1 From 8f4b25979f395bc8dee14f0381a3e4caf1a508d2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 18 Sep 2014 07:40:48 -0400 Subject: Bumped to 5.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 74c8224a..0fd1c872 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -36,7 +36,7 @@ try: except ImportError: USER_SITE = None -DEFAULT_VERSION = "5.8" +DEFAULT_VERSION = "5.9" 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 868f2d33..7244139e 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '5.8' +__version__ = '5.9' -- cgit v1.2.1 From f6f7c0366904358cb8a4a6ebfceb4566d88ceac4 Mon Sep 17 00:00:00 2001 From: Randy Syring Date: Sat, 20 Sep 2014 16:29:41 -0400 Subject: sdist command: fix case insensitivity when adding some files to filelist This should fix the problem in Bitbucket issue #100. It gives the same behavior for inclusion of default files (README*, etc.) on Windows as Linux. BACKWARDS INCOMPATABILITY: This may result in a backwards incompatible change for users on a case insensitive file system. If they were relying on some files getting included in their distribution due to setuptools defaults, and their files do not have the same case as the files being looked for in setuptools, those files will no longer be included in the package. For example, if a package had a file: readme.rst Previous to this commit, that file would have been included in the distribution as: README.rst But it will now no longer be included at all. To get the file included in the package, it can be added to the package's MANIFEST.in file: include readme.rst Files affected by this change will have a case variant of the files or patterns listed below: README README.txt README.rst setup.py (or whatever your setuptools script is named) setup.cfg test/test*.py --- setuptools/command/sdist.py | 11 +++++++---- setuptools/tests/test_sdist.py | 28 ++++++++++++++++++++++++++++ setuptools/utils.py | 11 +++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 setuptools/utils.py diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index 2aa1ee20..dc8d6773 100755 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -8,6 +8,8 @@ import sys from setuptools import svn_utils from setuptools.compat import PY3 +from setuptools.utils import cs_path_exists + import pkg_resources READMES = ('README', 'README.rst', 'README.txt') @@ -146,7 +148,7 @@ class sdist(orig.sdist): alts = fn got_it = 0 for fn in alts: - if os.path.exists(fn): + if cs_path_exists(fn): got_it = 1 self.filelist.append(fn) break @@ -155,16 +157,17 @@ class sdist(orig.sdist): self.warn("standard file not found: should have one of " + ', '.join(alts)) else: - if os.path.exists(fn): + if cs_path_exists(fn): self.filelist.append(fn) else: self.warn("standard file '%s' not found" % fn) optional = ['test/test*.py', 'setup.cfg'] for pattern in optional: - files = list(filter(os.path.isfile, glob(pattern))) + files = list(filter(cs_path_exists, glob(pattern))) if files: - self.filelist.extend(files) + actual_fnames = map(os.path.normcase, files) + self.filelist.extend(actual_fnames) # getting python files if self.distribution.has_pure_modules(): diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 5b3862e9..5f8a190f 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -86,6 +86,7 @@ class TestSdistTest(unittest.TestCase): f = open(os.path.join(self.temp_dir, 'setup.py'), 'w') f.write(SETUP_PY) f.close() + # Set up the rest of the test package test_pkg = os.path.join(self.temp_dir, 'sdist_test') os.mkdir(test_pkg) @@ -121,6 +122,33 @@ class TestSdistTest(unittest.TestCase): self.assertTrue(os.path.join('sdist_test', 'b.txt') in manifest) self.assertTrue(os.path.join('sdist_test', 'c.rst') not in manifest) + + def test_defaults_case_sensitivity(self): + """ + Make sure default files (README.*, etc.) are added in a case-sensitive + way to avoid problems with packages built on Windows. + """ + + open(os.path.join(self.temp_dir, 'readme.rst'), 'w').close() + open(os.path.join(self.temp_dir, 'SETUP.cfg'), 'w').close() + + dist = Distribution(SETUP_ATTRS) + # the extension deliberately capitalized for this test + # to make sure the actual filename (not capitalized) gets added + # to the manifest + dist.script_name = 'setup.PY' + cmd = sdist(dist) + cmd.ensure_finalized() + + with quiet(): + cmd.run() + + # lowercase all names so we can test in a case-insensitive way to make sure the files are not included + manifest = map(lambda x: x.lower(), cmd.filelist.files) + self.assertFalse('readme.rst' in manifest, manifest) + self.assertFalse('setup.py' in manifest, manifest) + self.assertFalse('setup.cfg' in manifest, manifest) + def test_manifest_is_written_with_utf8_encoding(self): # Test for #303. dist = Distribution(SETUP_ATTRS) diff --git a/setuptools/utils.py b/setuptools/utils.py new file mode 100644 index 00000000..91e4b87f --- /dev/null +++ b/setuptools/utils.py @@ -0,0 +1,11 @@ +import os +import os.path + + +def cs_path_exists(fspath): + if not os.path.exists(fspath): + return False + # make absolute so we always have a directory + abspath = os.path.abspath(fspath) + directory, filename = os.path.split(abspath) + return filename in os.listdir(directory) \ No newline at end of file -- cgit v1.2.1 From b7657bd33c1ff5e1bcfda7bdac50000b41fd6e36 Mon Sep 17 00:00:00 2001 From: Randy Syring Date: Sat, 20 Sep 2014 16:37:25 -0400 Subject: remove unneeded code from last commit --- setuptools/command/sdist.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index dc8d6773..a77c39f2 100755 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -166,8 +166,7 @@ class sdist(orig.sdist): for pattern in optional: files = list(filter(cs_path_exists, glob(pattern))) if files: - actual_fnames = map(os.path.normcase, files) - self.filelist.extend(actual_fnames) + self.filelist.extend(files) # getting python files if self.distribution.has_pure_modules(): -- cgit v1.2.1 From 19708e2c4e944e0ec5843437744b8f23f235a026 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 24 Sep 2014 00:22:22 -0400 Subject: Update changelog --- CHANGES.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 185052fb..a6e27372 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,28 @@ CHANGES ======= +--- +6.0 +--- + +* Issue #100: When building a distribution, Setuptools will no longer match + default files using platform-dependent case sensitivity, but rather will + only match the files if their case matches exactly. As a result, on Windows + and other case-insensitive file systems, files with names such as + 'readme.txt' or 'README.TXT' will be omitted from the distribution and a + warning will be issued indicating that 'README.txt' was not found. Other + filenames affected are: + + - README.rst + - README + - setup.cfg + - setup.py (or the script name) + - test/test*.py + + Any users producing distributions with filenames that match those above + case-insensitively, but not case-sensitively, should rename those files in + their repository for better portability. + --- 5.8 --- -- cgit v1.2.1 From fc7d696c5a6af1aefa7daf9131893b5b5065cdb0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 09:54:15 -0400 Subject: Normalize syntax --- setuptools/command/install_lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 7692e0f3..c0c271a4 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -17,7 +17,7 @@ class install_lib(orig.install_lib): svem = (nsp and self.get_finalized_command('install') .single_version_externally_managed) exclude_names = ['__init__.py', '__init__.pyc', '__init__.pyo'] - if hasattr(imp, 'get_tag') : + if hasattr(imp, 'get_tag'): exclude_names.extend(( os.path.join( '__pycache__', @@ -33,7 +33,7 @@ class install_lib(orig.install_lib): parts = pkg.split('.') while parts: pkgdir = os.path.join(self.install_dir, *parts) - for f in exclude_names : + for f in exclude_names: exclude[os.path.join(pkgdir, f)] = 1 parts.pop() return exclude -- cgit v1.2.1 From 8f5ca6ed5efe1523a511325a1d1c620ead832646 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:02:01 -0400 Subject: Extract method for generating exclude names --- setuptools/command/install_lib.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index c0c271a4..259f0899 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -16,6 +16,22 @@ class install_lib(orig.install_lib): nsp = self.distribution.namespace_packages svem = (nsp and self.get_finalized_command('install') .single_version_externally_managed) + if svem: + for pkg in nsp: + parts = pkg.split('.') + while parts: + pkgdir = os.path.join(self.install_dir, *parts) + for f in self._gen_exclude_names(): + exclude[os.path.join(pkgdir, f)] = 1 + parts.pop() + return exclude + + @staticmethod + def _gen_exclude_names(): + """ + Generate the list of file paths to be excluded for namespace + packages (bytecode cache files). + """ exclude_names = ['__init__.py', '__init__.pyc', '__init__.pyo'] if hasattr(imp, 'get_tag'): exclude_names.extend(( @@ -28,15 +44,7 @@ class install_lib(orig.install_lib): '__init__.' + imp.get_tag() + '.pyo' ), )) - if svem: - for pkg in nsp: - parts = pkg.split('.') - while parts: - pkgdir = os.path.join(self.install_dir, *parts) - for f in exclude_names: - exclude[os.path.join(pkgdir, f)] = 1 - parts.pop() - return exclude + return exclude_names def copy_tree( self, infile, outfile, -- cgit v1.2.1 From 0de041b81f687f94391f7345f8164313723b93ef Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:05:18 -0400 Subject: Generate the filenames more directly. --- setuptools/command/install_lib.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 259f0899..3f39d945 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -29,22 +29,18 @@ class install_lib(orig.install_lib): @staticmethod def _gen_exclude_names(): """ - Generate the list of file paths to be excluded for namespace - packages (bytecode cache files). + Generate file paths to be excluded for namespace packages (bytecode + cache files). """ - exclude_names = ['__init__.py', '__init__.pyc', '__init__.pyo'] - if hasattr(imp, 'get_tag'): - exclude_names.extend(( - os.path.join( - '__pycache__', - '__init__.' + imp.get_tag() + '.pyc' - ), - os.path.join( - '__pycache__', - '__init__.' + imp.get_tag() + '.pyo' - ), - )) - return exclude_names + yield '__init__.py' + yield '__init__.pyc' + yield '__init__.pyo' + + if not hasattr(imp, 'get_tag'): + return + + yield os.path.join('__pycache__', '__init__.' + imp.get_tag() + '.pyc') + yield os.path.join('__pycache__', '__init__.' + imp.get_tag() + '.pyo') def copy_tree( self, infile, outfile, -- cgit v1.2.1 From 8993c7b73cbcaed6afb50e28a80139506f794d8d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:06:35 -0400 Subject: Extract calculation of base path --- setuptools/command/install_lib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 3f39d945..d1c91b7b 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -39,8 +39,9 @@ class install_lib(orig.install_lib): if not hasattr(imp, 'get_tag'): return - yield os.path.join('__pycache__', '__init__.' + imp.get_tag() + '.pyc') - yield os.path.join('__pycache__', '__init__.' + imp.get_tag() + '.pyo') + base = os.path.join('__pycache__', '__init__.' + imp.get_tag()) + yield base + '.pyc' + yield base + '.pyo' def copy_tree( self, infile, outfile, -- cgit v1.2.1 From 5f5fa224d8b2a34ad13026aa85c7928acd1f06cf Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:07:07 -0400 Subject: Add comment --- 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 d1c91b7b..a1cbd2aa 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -32,7 +32,9 @@ class install_lib(orig.install_lib): Generate file paths to be excluded for namespace packages (bytecode cache files). """ + # always exclude the package module itself yield '__init__.py' + yield '__init__.pyc' yield '__init__.pyo' -- cgit v1.2.1 From b894f59a0f502328aac96c872cb6ae5ac9d4c5b8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:08:48 -0400 Subject: Construct exclusions as a set --- setuptools/command/install_lib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index a1cbd2aa..f4b295cc 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -12,7 +12,7 @@ class install_lib(orig.install_lib): self.byte_compile(outfiles) def get_exclusions(self): - exclude = {} + exclude = set() nsp = self.distribution.namespace_packages svem = (nsp and self.get_finalized_command('install') .single_version_externally_managed) @@ -22,9 +22,9 @@ class install_lib(orig.install_lib): while parts: pkgdir = os.path.join(self.install_dir, *parts) for f in self._gen_exclude_names(): - exclude[os.path.join(pkgdir, f)] = 1 + exclude.add(os.path.join(pkgdir, f)) parts.pop() - return exclude + return dict.fromkeys(exclude, 1) @staticmethod def _gen_exclude_names(): -- cgit v1.2.1 From a783507ff995a5bff15b69441564ca1af224bbb4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:19:36 -0400 Subject: Add docstring for get_exclusions. Just return the set as it is a sized container. --- setuptools/command/install_lib.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index f4b295cc..91d2b25d 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -12,6 +12,10 @@ class install_lib(orig.install_lib): self.byte_compile(outfiles) def get_exclusions(self): + """ + Return a collections.Sized collections.Container of paths to be + excluded for single_version_externally_managed installations. + """ exclude = set() nsp = self.distribution.namespace_packages svem = (nsp and self.get_finalized_command('install') @@ -24,7 +28,7 @@ class install_lib(orig.install_lib): for f in self._gen_exclude_names(): exclude.add(os.path.join(pkgdir, f)) parts.pop() - return dict.fromkeys(exclude, 1) + return exclude @staticmethod def _gen_exclude_names(): -- cgit v1.2.1 From 313f500b15ddb1c81d7ead8abdbba6c0b6ad57f4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:29:38 -0400 Subject: Extract method for calculating namespace packages for single_version_externally_managed --- setuptools/command/install_lib.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 91d2b25d..bf587a04 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -17,19 +17,31 @@ class install_lib(orig.install_lib): excluded for single_version_externally_managed installations. """ exclude = set() - nsp = self.distribution.namespace_packages - svem = (nsp and self.get_finalized_command('install') - .single_version_externally_managed) - if svem: - for pkg in nsp: - parts = pkg.split('.') - while parts: - pkgdir = os.path.join(self.install_dir, *parts) - for f in self._gen_exclude_names(): - exclude.add(os.path.join(pkgdir, f)) - parts.pop() + for pkg in self._get_SVEM_NSPs(): + parts = pkg.split('.') + while parts: + pkgdir = os.path.join(self.install_dir, *parts) + for f in self._gen_exclude_names(): + exclude.add(os.path.join(pkgdir, f)) + parts.pop() return exclude + def _get_SVEM_NSPs(self): + """ + Get namespace packages (list) but only for + single_version_externally_managed installations and empty otherwise. + """ + # TODO: is it necessary to short-circuit here? i.e. what's the cost + # if get_finalized_command is called even when namespace_packages is + # False? + if not self.distribution.namespace_packages: + return [] + + install_cmd = self.get_finalized_command('install') + svem = install_cmd.single_version_externally_managed + + return self.distribution.namespace_packages if svem else [] + @staticmethod def _gen_exclude_names(): """ -- cgit v1.2.1 From b77f13ea93cae16c9bc46bc4262d61b66486d3e5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:39:53 -0400 Subject: Extract method for computing parent packages of a package --- setuptools/command/install_lib.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index bf587a04..88b35972 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -17,15 +17,24 @@ class install_lib(orig.install_lib): excluded for single_version_externally_managed installations. """ exclude = set() - for pkg in self._get_SVEM_NSPs(): - parts = pkg.split('.') - while parts: + for ns_pkg in self._get_SVEM_NSPs(): + for pkg in self._all_packages(ns_pkg): + parts = pkg.split('.') pkgdir = os.path.join(self.install_dir, *parts) for f in self._gen_exclude_names(): exclude.add(os.path.join(pkgdir, f)) - parts.pop() return exclude + @staticmethod + def _all_packages(pkg_name): + """ + >>> list(install_lib._all_packages('foo.bar.baz')) + ['foo.bar.baz', 'foo.bar', 'foo'] + """ + while pkg_name: + yield pkg_name + pkg_name, sep, child = pkg_name.partition('.') + def _get_SVEM_NSPs(self): """ Get namespace packages (list) but only for -- cgit v1.2.1 From 685164f8d3f722323be0917ebe083e02df40c03b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:41:49 -0400 Subject: Extract path calculation for paths --- setuptools/command/install_lib.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 88b35972..92490b6e 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -17,12 +17,11 @@ class install_lib(orig.install_lib): excluded for single_version_externally_managed installations. """ exclude = set() + pkg_path = lambda pkg: os.path.join(self.install_dir, *pkg.split('.')) for ns_pkg in self._get_SVEM_NSPs(): for pkg in self._all_packages(ns_pkg): - parts = pkg.split('.') - pkgdir = os.path.join(self.install_dir, *parts) for f in self._gen_exclude_names(): - exclude.add(os.path.join(pkgdir, f)) + exclude.add(os.path.join(pkg_path(pkg), f)) return exclude @staticmethod -- cgit v1.2.1 From 8cd78274dad7baaba5720b4b9de56e7d9b7a2508 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:43:35 -0400 Subject: Rewrite package traversal as a generator expression --- setuptools/command/install_lib.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 92490b6e..7f157a0f 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -18,8 +18,12 @@ class install_lib(orig.install_lib): """ exclude = set() pkg_path = lambda pkg: os.path.join(self.install_dir, *pkg.split('.')) - for ns_pkg in self._get_SVEM_NSPs(): - for pkg in self._all_packages(ns_pkg): + all_packages = ( + pkg + for ns_pkg in self._get_SVEM_NSPs() + for pkg in self._all_packages(ns_pkg) + ) + for pkg in all_packages: for f in self._gen_exclude_names(): exclude.add(os.path.join(pkg_path(pkg), f)) return exclude -- cgit v1.2.1 From 856231494f5b5df2b105c7275221c6ef17ddaa6d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:43:43 -0400 Subject: Reindent --- setuptools/command/install_lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 7f157a0f..371a9e72 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -24,8 +24,8 @@ class install_lib(orig.install_lib): for pkg in self._all_packages(ns_pkg) ) for pkg in all_packages: - for f in self._gen_exclude_names(): - exclude.add(os.path.join(pkg_path(pkg), f)) + for f in self._gen_exclude_names(): + exclude.add(os.path.join(pkg_path(pkg), f)) return exclude @staticmethod -- cgit v1.2.1 From 0306d5206bc40959af44055e3c28c5aabcebc6c1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:46:14 -0400 Subject: Use itertools.product for a cross-product of two iterables --- setuptools/command/install_lib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 371a9e72..c2730568 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -1,5 +1,6 @@ import distutils.command.install_lib as orig import os, imp +from itertools import product class install_lib(orig.install_lib): """Don't add compiled flags to filenames of non-Python files""" @@ -23,9 +24,8 @@ class install_lib(orig.install_lib): for ns_pkg in self._get_SVEM_NSPs() for pkg in self._all_packages(ns_pkg) ) - for pkg in all_packages: - for f in self._gen_exclude_names(): - exclude.add(os.path.join(pkg_path(pkg), f)) + for pkg, f in product(all_packages, self._gen_exclude_names()): + exclude.add(os.path.join(pkg_path(pkg), f)) return exclude @staticmethod -- cgit v1.2.1 From 37ccf84ed4f36ce077be65e4320ef2be28f92212 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:46:37 -0400 Subject: Reorganize imports --- setuptools/command/install_lib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index c2730568..cc531c01 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -1,6 +1,7 @@ -import distutils.command.install_lib as orig -import os, imp +import os +import imp from itertools import product +import distutils.command.install_lib as orig class install_lib(orig.install_lib): """Don't add compiled flags to filenames of non-Python files""" -- cgit v1.2.1 From 2cf0c24e2fc6521a6fd35fe2b44186b0bb2032d2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:52:20 -0400 Subject: Incorporate the exclusion path in the _exclude function. --- setuptools/command/install_lib.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index cc531c01..f36d8651 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -19,14 +19,18 @@ class install_lib(orig.install_lib): excluded for single_version_externally_managed installations. """ exclude = set() - pkg_path = lambda pkg: os.path.join(self.install_dir, *pkg.split('.')) + + def _exclude(pkg, exclusion_path): + parts = pkg.split('.') + [exclusion_path] + return os.path.join(self.install_dir, *parts) + all_packages = ( pkg for ns_pkg in self._get_SVEM_NSPs() for pkg in self._all_packages(ns_pkg) ) for pkg, f in product(all_packages, self._gen_exclude_names()): - exclude.add(os.path.join(pkg_path(pkg), f)) + exclude.add(_exclude(pkg, f)) return exclude @staticmethod -- cgit v1.2.1 From 4d538558d0d5744a18a67ead585583771f6cb795 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:56:24 -0400 Subject: Return the exclusions directly --- setuptools/command/install_lib.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index f36d8651..dcd85dec 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -1,6 +1,6 @@ import os import imp -from itertools import product +from itertools import product, starmap import distutils.command.install_lib as orig class install_lib(orig.install_lib): @@ -18,9 +18,11 @@ class install_lib(orig.install_lib): Return a collections.Sized collections.Container of paths to be excluded for single_version_externally_managed installations. """ - exclude = set() - def _exclude(pkg, exclusion_path): + """ + Given a package name and exclusion path within that package, + compute the full exclusion path. + """ parts = pkg.split('.') + [exclusion_path] return os.path.join(self.install_dir, *parts) @@ -29,9 +31,9 @@ class install_lib(orig.install_lib): for ns_pkg in self._get_SVEM_NSPs() for pkg in self._all_packages(ns_pkg) ) - for pkg, f in product(all_packages, self._gen_exclude_names()): - exclude.add(_exclude(pkg, f)) - return exclude + + excl_specs = product(all_packages, self._gen_exclude_names()) + return set(starmap(_exclude, excl_specs)) @staticmethod def _all_packages(pkg_name): -- cgit v1.2.1 From d2fce58956198d5d7d3b3a81f4d9cda5df6c0921 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 10:59:09 -0400 Subject: Move inline function into an instance method and rename for clarity. --- setuptools/command/install_lib.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index dcd85dec..3cd16a8f 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -18,22 +18,22 @@ class install_lib(orig.install_lib): Return a collections.Sized collections.Container of paths to be excluded for single_version_externally_managed installations. """ - def _exclude(pkg, exclusion_path): - """ - Given a package name and exclusion path within that package, - compute the full exclusion path. - """ - parts = pkg.split('.') + [exclusion_path] - return os.path.join(self.install_dir, *parts) - all_packages = ( pkg for ns_pkg in self._get_SVEM_NSPs() for pkg in self._all_packages(ns_pkg) ) - excl_specs = product(all_packages, self._gen_exclude_names()) - return set(starmap(_exclude, excl_specs)) + excl_specs = product(all_packages, self._gen_exclusion_paths()) + return set(starmap(self._exclude_pkg_path, excl_specs)) + + def _exclude_pkg_path(self, pkg, exclusion_path): + """ + Given a package name and exclusion path within that package, + compute the full exclusion path. + """ + parts = pkg.split('.') + [exclusion_path] + return os.path.join(self.install_dir, *parts) @staticmethod def _all_packages(pkg_name): @@ -62,7 +62,7 @@ class install_lib(orig.install_lib): return self.distribution.namespace_packages if svem else [] @staticmethod - def _gen_exclude_names(): + def _gen_exclusion_paths(): """ Generate file paths to be excluded for namespace packages (bytecode cache files). -- cgit v1.2.1 From fc200c9d8094685fa91ade69b9c1126c91bbfc37 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 11:09:32 -0400 Subject: Update changelog --- CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index a6e27372..4fae469b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -23,6 +23,8 @@ CHANGES Any users producing distributions with filenames that match those above case-insensitively, but not case-sensitively, should rename those files in their repository for better portability. +* Pull Request #72: When using ``single_version_externally_managed``, the + exclusion list now includes Python 3.2 ``__pycache__`` entries. --- 5.8 -- cgit v1.2.1 From 74d552e7f1cbbd3c1888abb14d7d5ae0a4132ec7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 26 Sep 2014 11:12:15 -0400 Subject: Update changelog --- CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 4fae469b..4b20333d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -25,6 +25,8 @@ CHANGES their repository for better portability. * Pull Request #72: When using ``single_version_externally_managed``, the exclusion list now includes Python 3.2 ``__pycache__`` entries. +* Pull Request #76 and Pull Request #78: lines in top_level.txt are now + ordered deterministically. --- 5.8 -- cgit v1.2.1