[Python-checkins] cpython (merge 2.7 -> 2.7): Branch merge

eric.araujo python-checkins at python.org
Mon Aug 1 14:49:59 CEST 2011


http://hg.python.org/cpython/rev/8065f927b4f6
changeset:   71675:8065f927b4f6
branch:      2.7
parent:      71660:42f40f53fd73
parent:      71674:a425408f1e52
user:        Éric Araujo <merwok at netwok.org>
date:        Mon Aug 01 14:48:19 2011 +0200
summary:
  Branch merge

files:
  Doc/distutils/sourcedist.rst       |  29 ++++++----
  Lib/distutils/command/sdist.py     |  48 ++++++++++-------
  Lib/distutils/tests/test_sdist.py  |  43 ++++++++++++---
  Lib/lib2to3/tests/test_refactor.py |  18 ++++--
  Misc/ACKS                          |   2 +
  Misc/NEWS                          |   6 ++
  Tools/scripts/patchcheck.py        |  20 ++++--
  7 files changed, 112 insertions(+), 54 deletions(-)


diff --git a/Doc/distutils/sourcedist.rst b/Doc/distutils/sourcedist.rst
--- a/Doc/distutils/sourcedist.rst
+++ b/Doc/distutils/sourcedist.rst
@@ -111,12 +111,22 @@
 :file:`MANIFEST`, you must specify everything: the default set of files
 described above does not apply in this case.
 
-.. versionadded:: 2.7
+.. versionchanged:: 2.7
+   An existing generated :file:`MANIFEST` will be regenerated without
+   :command:`sdist` comparing its modification time to the one of
+   :file:`MANIFEST.in` or :file:`setup.py`.
+
+.. versionchanged:: 2.7.1
    :file:`MANIFEST` files start with a comment indicating they are generated.
    Files without this comment are not overwritten or removed.
 
+.. versionchanged:: 2.7.3
+   :command:`sdist` will read a :file:`MANIFEST` file if no :file:`MANIFEST.in`
+   exists, like it did before 2.7.
+
 See :ref:`manifest_template` section for a syntax reference.
 
+
 .. _manifest-options:
 
 Manifest-related options
@@ -124,16 +134,16 @@
 
 The normal course of operations for the :command:`sdist` command is as follows:
 
-* if the manifest file, :file:`MANIFEST` doesn't exist, read :file:`MANIFEST.in`
-  and create the manifest
+* if the manifest file (:file:`MANIFEST` by default) exists and the first line
+  does not have a comment indicating it is generated from :file:`MANIFEST.in`,
+  then it is used as is, unaltered
+
+* if the manifest file doesn't exist or has been previously automatically
+  generated, read :file:`MANIFEST.in` and create the manifest
 
 * if neither :file:`MANIFEST` nor :file:`MANIFEST.in` exist, create a manifest
   with just the default file set
 
-* if either :file:`MANIFEST.in` or the setup script (:file:`setup.py`) are more
-  recent than :file:`MANIFEST`, recreate :file:`MANIFEST` by reading
-  :file:`MANIFEST.in`
-
 * use the list of files now in :file:`MANIFEST` (either just generated or read
   in) to create the source distribution archive(s)
 
@@ -271,8 +281,3 @@
 ``a-z``, ``a-zA-Z``, ``a-f0-9_.``).  The definition of "regular filename
 character" is platform-specific: on Unix it is anything except slash; on Windows
 anything except backslash or colon.
-
-.. versionchanged:: 2.7
-    An existing generated :file:`MANIFEST` will be regenerated without
-    :command:`sdist` comparing its modification time to the one of
-    :file:`MANIFEST.in` or :file:`setup.py`.
diff --git a/Lib/distutils/command/sdist.py b/Lib/distutils/command/sdist.py
--- a/Lib/distutils/command/sdist.py
+++ b/Lib/distutils/command/sdist.py
@@ -182,14 +182,20 @@
         reading the manifest, or just using the default file set -- it all
         depends on the user's options.
         """
-        # new behavior:
+        # new behavior when using a template:
         # the file list is recalculated everytime because
         # even if MANIFEST.in or setup.py are not changed
         # the user might have added some files in the tree that
         # need to be included.
         #
-        #  This makes --force the default and only behavior.
+        #  This makes --force the default and only behavior with templates.
         template_exists = os.path.isfile(self.template)
+        if not template_exists and self._manifest_is_not_generated():
+            self.read_manifest()
+            self.filelist.sort()
+            self.filelist.remove_duplicates()
+            return
+
         if not template_exists:
             self.warn(("manifest template '%s' does not exist " +
                         "(using default file list)") %
@@ -352,23 +358,28 @@
         by 'add_defaults()' and 'read_template()') to the manifest file
         named by 'self.manifest'.
         """
-        if os.path.isfile(self.manifest):
-            fp = open(self.manifest)
-            try:
-                first_line = fp.readline()
-            finally:
-                fp.close()
-
-            if first_line != '# file GENERATED by distutils, do NOT edit\n':
-                log.info("not writing to manually maintained "
-                         "manifest file '%s'" % self.manifest)
-                return
+        if self._manifest_is_not_generated():
+            log.info("not writing to manually maintained "
+                     "manifest file '%s'" % self.manifest)
+            return
 
         content = self.filelist.files[:]
         content.insert(0, '# file GENERATED by distutils, do NOT edit')
         self.execute(file_util.write_file, (self.manifest, content),
                      "writing manifest file '%s'" % self.manifest)
 
+    def _manifest_is_not_generated(self):
+        # check for special comment used in 2.7.1 and higher
+        if not os.path.isfile(self.manifest):
+            return False
+
+        fp = open(self.manifest, 'rU')
+        try:
+            first_line = fp.readline()
+        finally:
+            fp.close()
+        return first_line != '# file GENERATED by distutils, do NOT edit\n'
+
     def read_manifest(self):
         """Read the manifest file (named by 'self.manifest') and use it to
         fill in 'self.filelist', the list of files to include in the source
@@ -376,12 +387,11 @@
         """
         log.info("reading manifest file '%s'", self.manifest)
         manifest = open(self.manifest)
-        while 1:
-            line = manifest.readline()
-            if line == '':              # end of file
-                break
-            if line[-1] == '\n':
-                line = line[0:-1]
+        for line in manifest:
+            # ignore comments and blank lines
+            line = line.strip()
+            if line.startswith('#') or not line:
+                continue
             self.filelist.append(line)
         manifest.close()
 
diff --git a/Lib/distutils/tests/test_sdist.py b/Lib/distutils/tests/test_sdist.py
--- a/Lib/distutils/tests/test_sdist.py
+++ b/Lib/distutils/tests/test_sdist.py
@@ -1,9 +1,11 @@
 """Tests for distutils.command.sdist."""
 import os
+import tarfile
 import unittest
-import shutil
+import warnings
 import zipfile
-import tarfile
+from os.path import join
+from textwrap import dedent
 
 # zlib is not used here, but if it's not available
 # the tests that use zipfile may fail
@@ -19,19 +21,13 @@
 except ImportError:
     UID_GID_SUPPORT = False
 
-from os.path import join
-import sys
-import tempfile
-import warnings
-
 from test.test_support import captured_stdout, check_warnings, run_unittest
 
 from distutils.command.sdist import sdist, show_formats
 from distutils.core import Distribution
 from distutils.tests.test_config import PyPIRCCommandTestCase
-from distutils.errors import DistutilsExecError, DistutilsOptionError
+from distutils.errors import DistutilsOptionError
 from distutils.spawn import find_executable
-from distutils.tests import support
 from distutils.log import WARN
 from distutils.archive_util import ARCHIVE_FORMATS
 
@@ -405,13 +401,33 @@
         self.assertEqual(manifest[0],
                          '# file GENERATED by distutils, do NOT edit')
 
+    @unittest.skipUnless(zlib, 'requires zlib')
+    def test_manifest_comments(self):
+        # make sure comments don't cause exceptions or wrong includes
+        contents = dedent("""\
+            # bad.py
+            #bad.py
+            good.py
+            """)
+        dist, cmd = self.get_cmd()
+        cmd.ensure_finalized()
+        self.write_file((self.tmp_dir, cmd.manifest), contents)
+        self.write_file((self.tmp_dir, 'good.py'), '# pick me!')
+        self.write_file((self.tmp_dir, 'bad.py'), "# don't pick me!")
+        self.write_file((self.tmp_dir, '#bad.py'), "# don't pick me!")
+        cmd.run()
+        self.assertEqual(cmd.filelist.files, ['good.py'])
+
     @unittest.skipUnless(zlib, "requires zlib")
     def test_manual_manifest(self):
         # check that a MANIFEST without a marker is left alone
         dist, cmd = self.get_cmd()
         cmd.ensure_finalized()
         self.write_file((self.tmp_dir, cmd.manifest), 'README.manual')
+        self.write_file((self.tmp_dir, 'README.manual'),
+                         'This project maintains its MANIFEST file itself.')
         cmd.run()
+        self.assertEqual(cmd.filelist.files, ['README.manual'])
 
         f = open(cmd.manifest)
         try:
@@ -422,6 +438,15 @@
 
         self.assertEqual(manifest, ['README.manual'])
 
+        archive_name = join(self.tmp_dir, 'dist', 'fake-1.0.tar.gz')
+        archive = tarfile.open(archive_name)
+        try:
+            filenames = [tarinfo.name for tarinfo in archive]
+        finally:
+            archive.close()
+        self.assertEqual(sorted(filenames), ['fake-1.0', 'fake-1.0/PKG-INFO',
+                                             'fake-1.0/README.manual'])
+
 def test_suite():
     return unittest.makeSuite(SDistTestCase)
 
diff --git a/Lib/lib2to3/tests/test_refactor.py b/Lib/lib2to3/tests/test_refactor.py
--- a/Lib/lib2to3/tests/test_refactor.py
+++ b/Lib/lib2to3/tests/test_refactor.py
@@ -177,22 +177,26 @@
         self.assertEqual(results, expected)
 
     def check_file_refactoring(self, test_file, fixers=_2TO3_FIXERS):
+        tmpdir = tempfile.mkdtemp(prefix="2to3-test_refactor")
+        self.addCleanup(shutil.rmtree, tmpdir)
+        # make a copy of the tested file that we can write to
+        shutil.copy(test_file, tmpdir)
+        test_file = os.path.join(tmpdir, os.path.basename(test_file))
+        os.chmod(test_file, 0o644)
+
         def read_file():
             with open(test_file, "rb") as fp:
                 return fp.read()
+
         old_contents = read_file()
         rt = self.rt(fixers=fixers)
 
         rt.refactor_file(test_file)
         self.assertEqual(old_contents, read_file())
 
-        try:
-            rt.refactor_file(test_file, True)
-            new_contents = read_file()
-            self.assertNotEqual(old_contents, new_contents)
-        finally:
-            with open(test_file, "wb") as fp:
-                fp.write(old_contents)
+        rt.refactor_file(test_file, True)
+        new_contents = read_file()
+        self.assertNotEqual(old_contents, new_contents)
         return new_contents
 
     def test_refactor_file(self):
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -194,6 +194,7 @@
 Vincent Delft
 Arnaud Delobelle
 Erik Demaine
+John Dennis
 Roger Dev
 Raghuram Devarakonda
 Catherine Devlin
@@ -813,6 +814,7 @@
 Tobias Thelen
 James Thomas
 Robin Thomas
+Stephen Thorne
 Eric Tiedemann
 Tracy Tims
 Oren Tirosh
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -37,6 +37,9 @@
 Library
 -------
 
+- Issues #11104, #8688: Fix the behavior of distutils' sdist command with
+  manually-maintained MANIFEST files.
+
 - Issue #8887: "pydoc somebuiltin.somemethod" (or help('somebuiltin.somemethod')
   in Python code) now finds the doc of the method.
 
@@ -158,6 +161,9 @@
 Tests
 -----
 
+- Issue #12331: The test suite for lib2to3 can now run from an installed
+  Python.
+
 - Issue #12549: Correct test_platform to not fail when OS X returns 'x86_64'
   as the processor type on some Mac systems.
 
diff --git a/Tools/scripts/patchcheck.py b/Tools/scripts/patchcheck.py
--- a/Tools/scripts/patchcheck.py
+++ b/Tools/scripts/patchcheck.py
@@ -4,11 +4,15 @@
 import shutil
 import os.path
 import subprocess
+import sysconfig
 
 import reindent
 import untabify
 
 
+SRCDIR = sysconfig.get_config_var('srcdir')
+
+
 def n_files_str(count):
     """Return 'N file(s)' with the proper plurality on 'file'."""
     return "{} file{}".format(count, "s" if count != 1 else "")
@@ -36,7 +40,7 @@
         info=lambda x: n_files_str(len(x)))
 def changed_files():
     """Get the list of changed or added files from the VCS."""
-    if os.path.isdir('.hg'):
+    if os.path.isdir(os.path.join(SRCDIR, '.hg')):
         vcs = 'hg'
         cmd = 'hg status --added --modified --no-status'
     elif os.path.isdir('.svn'):
@@ -75,7 +79,7 @@
     reindent.makebackup = False  # No need to create backups.
     fixed = []
     for path in (x for x in file_paths if x.endswith('.py')):
-        if reindent.check(path):
+        if reindent.check(os.path.join(SRCDIR, path)):
             fixed.append(path)
     return fixed
 
@@ -85,10 +89,11 @@
     """Report if any C files """
     fixed = []
     for path in file_paths:
-        with open(path, 'r') as f:
+        abspath = os.path.join(SRCDIR, path)
+        with open(abspath, 'r') as f:
             if '\t' not in f.read():
                 continue
-        untabify.process(path, 8, verbose=False)
+        untabify.process(abspath, 8, verbose=False)
         fixed.append(path)
     return fixed
 
@@ -99,13 +104,14 @@
 def normalize_docs_whitespace(file_paths):
     fixed = []
     for path in file_paths:
+        abspath = os.path.join(SRCDIR, path)
         try:
-            with open(path, 'rb') as f:
+            with open(abspath, 'rb') as f:
                 lines = f.readlines()
             new_lines = [ws_re.sub(br'\1', line) for line in lines]
             if new_lines != lines:
-                shutil.copyfile(path, path + '.bak')
-                with open(path, 'wb') as f:
+                shutil.copyfile(abspath, abspath + '.bak')
+                with open(abspath, 'wb') as f:
                     f.writelines(new_lines)
                 fixed.append(path)
         except Exception as err:

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list