[Python-checkins] cpython (merge default -> default): Merge

brett.cannon python-checkins at python.org
Thu Apr 26 02:19:05 CEST 2012


http://hg.python.org/cpython/rev/37b03d64883a
changeset:   76563:37b03d64883a
parent:      76562:8dab93ec19de
parent:      76561:004f8d96f573
user:        Brett Cannon <brett at python.org>
date:        Wed Apr 25 20:18:24 2012 -0400
summary:
  Merge

files:
  Lib/importlib/_bootstrap.py         |    7 ++
  Lib/test/test_logging.py            |   36 +++++++-------
  Lib/unittest/case.py                |    2 +-
  Lib/unittest/test/test_skipping.py  |   15 ++++++
  Makefile.pre.in                     |   15 +++++-
  Misc/NEWS                           |    6 ++
  Objects/longobject.c                |    2 +
  Objects/unicodeobject.c             |    8 ++-
  Python/importlib.h                  |  Bin 
  Tools/msi/msi.py                    |   22 +++++++-
  Tools/scripts/import_diagnostics.py |   39 ++++++++++++++++
  11 files changed, 126 insertions(+), 26 deletions(-)


diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -6,6 +6,13 @@
 work. One should use importlib as the public-facing version of this module.
 
 """
+#
+# IMPORTANT: Whenever making changes to this module, be sure to run
+# a top-level make in order to get the frozen version of the module
+# update. Not doing so, will result in the Makefile to fail for
+# all others who don't have a ./python around to freeze the module
+# in the early stages of compilation.
+#
 
 # See importlib._setup() for what is injected into the global namespace.
 
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -593,28 +593,28 @@
                     pass
                 time.sleep(0.004 * random.randint(0, 4))
 
-        def cleanup(remover, fn, handler):
-            handler.close()
-            remover.join()
-            if os.path.exists(fn):
-                os.unlink(fn)
-
-        fd, fn = tempfile.mkstemp('.log', 'test_logging-3-')
-        os.close(fd)
-        del_count = 1000
-        log_count = 1000
-        remover = threading.Thread(target=remove_loop, args=(fn, del_count))
-        remover.daemon = True
-        remover.start()
+        del_count = 500
+        log_count = 500
+
         for delay in (False, True):
+            fd, fn = tempfile.mkstemp('.log', 'test_logging-3-')
+            os.close(fd)
+            remover = threading.Thread(target=remove_loop, args=(fn, del_count))
+            remover.daemon = True
+            remover.start()
             h = logging.handlers.WatchedFileHandler(fn, delay=delay)
-            self.addCleanup(cleanup, remover, fn, h)
             f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s')
             h.setFormatter(f)
-            for _ in range(log_count):
-                time.sleep(0.005)
-                r = logging.makeLogRecord({'msg': 'testing' })
-                h.handle(r)
+            try:
+                for _ in range(log_count):
+                    time.sleep(0.005)
+                    r = logging.makeLogRecord({'msg': 'testing' })
+                    h.handle(r)
+            finally:
+                h.close()
+                remover.join()
+                if os.path.exists(fn):
+                    os.unlink(fn)
 
 
 class BadStream(object):
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -61,7 +61,7 @@
     Unconditionally skip a test.
     """
     def decorator(test_item):
-        if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
+        if not isinstance(test_item, type):
             @functools.wraps(test_item)
             def skip_wrapper(*args, **kwargs):
                 raise SkipTest(reason)
diff --git a/Lib/unittest/test/test_skipping.py b/Lib/unittest/test/test_skipping.py
--- a/Lib/unittest/test/test_skipping.py
+++ b/Lib/unittest/test/test_skipping.py
@@ -66,6 +66,21 @@
         self.assertEqual(result.skipped, [(test, "testing")])
         self.assertEqual(record, [])
 
+    def test_skip_non_unittest_class(self):
+        @unittest.skip("testing")
+        class Mixin:
+            def test_1(self):
+                record.append(1)
+        class Foo(Mixin, unittest.TestCase):
+            pass
+        record = []
+        result = unittest.TestResult()
+        test = Foo("test_1")
+        suite = unittest.TestSuite([test])
+        suite.run(result)
+        self.assertEqual(result.skipped, [(test, "testing")])
+        self.assertEqual(record, [])
+
     def test_expected_failure(self):
         class Foo(unittest.TestCase):
             @unittest.expectedFailure
diff --git a/Makefile.pre.in b/Makefile.pre.in
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -573,12 +573,23 @@
 
 Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
 	$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
+
 ############################################################################
 # Importlib
 
 Python/importlib.h: $(srcdir)/Lib/importlib/_bootstrap.py $(srcdir)/Python/freeze_importlib.py
-	./$(BUILDPYTHON) $(srcdir)/Python/freeze_importlib.py \
-	    $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h
+	@if test -f ./$(BUILDPYTHON); then \
+	    ./$(BUILDPYTHON) $(srcdir)/Python/freeze_importlib.py \
+		$(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h; \
+	else \
+	    echo "----------------------------------------------------------"; \
+	    echo "Python/importlib.h needs to be rebuilt, but no interpreter"; \
+	    echo "is available to do so. Leaving the previous version in"; \
+	    echo "place. You may want to run ''make'' a second time after"; \
+	    echo "this build is complete."; \
+	    echo "----------------------------------------------------------"; \
+	fi
+
 ############################################################################
 # Special rules for object files
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -71,6 +71,9 @@
 Library
 -------
 
+- Issue #14664: It is now possible to use @unittest.skip{If,Unless} on a
+  test class that doesn't inherit from TestCase (i.e. a mixin).
+
 - Issue #4892: multiprocessing Connections can now be transferred over
   multiprocessing Connections.  Patch by Richard Oudkerk (sbt).
 
@@ -186,6 +189,9 @@
 Tools / Demos
 -------------
 
+- Issue #3561: The Windows installer now has an option, off by default, for
+  placing the Python installation into the system "Path" environment variable.
+
 - Issue #13165: stringbench is now available in the Tools/stringbench folder.
   It used to live in its own SVN project.
 
diff --git a/Objects/longobject.c b/Objects/longobject.c
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -1657,6 +1657,7 @@
 
     /* check we've counted correctly */
     assert(p == PyUnicode_1BYTE_DATA(str));
+    assert(_PyUnicode_CheckConsistency(str, 1));
     Py_DECREF(scratch);
     return (PyObject *)str;
 }
@@ -1761,6 +1762,7 @@
     if (negative)
         *--p = '-';
     assert(p == PyUnicode_1BYTE_DATA(v));
+    assert(_PyUnicode_CheckConsistency(v, 1));
     return v;
 }
 
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -375,10 +375,13 @@
     {
         Py_ssize_t i;
         Py_UCS4 maxchar = 0;
-        void *data = PyUnicode_DATA(ascii);
+        void *data;
+        Py_UCS4 ch;
+
+        data = PyUnicode_DATA(ascii);
         for (i=0; i < ascii->length; i++)
         {
-            Py_UCS4 ch = PyUnicode_READ(kind, data, i);
+            ch = PyUnicode_READ(kind, data, i);
             if (ch > maxchar)
                 maxchar = ch;
         }
@@ -398,6 +401,7 @@
             assert(maxchar >= 0x10000);
             assert(maxchar <= MAX_UNICODE);
         }
+        assert(PyUnicode_READ(kind, data, ascii->length) == 0);
     }
     return 1;
 }
diff --git a/Python/importlib.h b/Python/importlib.h
index 8bc0d8128cdbb869055d5c9ddfb53b6cbc17e32d..9dbd8816f3060d4ea66d3db7b1980139214e3908
GIT binary patch
[stripped]
diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py
--- a/Tools/msi/msi.py
+++ b/Tools/msi/msi.py
@@ -454,6 +454,10 @@
               ("SetDLLDirToTarget", 'DLLDIR=""', 751),
              ])
 
+    # Prepend TARGETDIR to the system path, and remove it on uninstall.
+    add_data(db, "Environment",
+             [("PathAddition", "=-*Path", "[TARGETDIR];[~]", "REGISTRY.path")])
+
     # Execute Sequences
     add_data(db, "InstallExecuteSequence",
             [("InitialTargetDir", 'TARGETDIR=""', 750),
@@ -677,11 +681,11 @@
     c=features.xbutton("Advanced", "Advanced", None, 0.30)
     c.event("SpawnDialog", "AdvancedDlg")
 
-    c=features.text("ItemDescription", 140, 180, 210, 30, 3,
+    c=features.text("ItemDescription", 140, 180, 210, 40, 3,
                   "Multiline description of the currently selected item.")
     c.mapping("SelectionDescription","Text")
 
-    c=features.text("ItemSize", 140, 210, 210, 45, 3,
+    c=features.text("ItemSize", 140, 225, 210, 33, 3,
                     "The size of the currently selected item.")
     c.mapping("SelectionSize", "Text")
 
@@ -835,7 +839,7 @@
     # (i.e. additional Python libraries) need to follow the parent feature.
     # Features that have no advertisement trigger (e.g. the test suite)
     # must not support advertisement
-    global default_feature, tcltk, htmlfiles, tools, testsuite, ext_feature, private_crt
+    global default_feature, tcltk, htmlfiles, tools, testsuite, ext_feature, private_crt, prepend_path
     default_feature = Feature(db, "DefaultFeature", "Python",
                               "Python Interpreter and Libraries",
                               1, directory = "TARGETDIR")
@@ -860,6 +864,15 @@
     testsuite = Feature(db, "Testsuite", "Test suite",
                         "Python test suite (Lib/test/)", 11,
                         parent = default_feature, attributes=2|8)
+    # prepend_path is an additional feature which is to be off by default.
+    # Since the default level for the above features is 1, this needs to be
+    # at least level higher.
+    prepend_path = Feature(db, "PrependPath", "Add python.exe to Path",
+                        "Prepend [TARGETDIR] to the system Path variable. "
+                        "This allows you to type 'python' into a command "
+                        "prompt without needing the full path.", 13,
+                        parent = default_feature, attributes=2|8,
+                        level=2)
 
 def extract_msvcr90():
     # Find the redistributable files
@@ -1146,6 +1159,8 @@
                "InstallPath"),
               ("REGISTRY.doc", msilib.gen_uuid(), "TARGETDIR", registry_component, None,
                "Documentation"),
+              ("REGISTRY.path", msilib.gen_uuid(), "TARGETDIR", registry_component, None,
+              None),
               ("REGISTRY.def", msilib.gen_uuid(), "TARGETDIR", registry_component,
                None, None)] + tcldata)
     # See "FeatureComponents Table".
@@ -1162,6 +1177,7 @@
     add_data(db, "FeatureComponents",
              [(default_feature.id, "REGISTRY"),
               (htmlfiles.id, "REGISTRY.doc"),
+              (prepend_path.id, "REGISTRY.path"),
               (ext_feature.id, "REGISTRY.def")] +
               tcldata
               )
diff --git a/Tools/scripts/import_diagnostics.py b/Tools/scripts/import_diagnostics.py
new file mode 100755
--- /dev/null
+++ b/Tools/scripts/import_diagnostics.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+"""Miscellaneous diagnostics for the import system"""
+
+import sys
+import argparse
+from pprint import pprint
+
+def _dump_state(args):
+    print(sys.version)
+    print("sys.path:")
+    pprint(sys.path)
+    print("sys.meta_path")
+    pprint(sys.meta_path)
+    print("sys.path_hooks")
+    pprint(sys.path_hooks)
+    print("sys.path_importer_cache")
+    pprint(sys.path_importer_cache)
+    print("sys.modules:")
+    pprint(sys.modules)
+
+COMMANDS = (
+  ("dump", "Dump import state", _dump_state),
+)
+
+def _make_parser():
+    parser = argparse.ArgumentParser()
+    sub = parser.add_subparsers(title="Commands")
+    for name, description, implementation in COMMANDS:
+        cmd = sub.add_parser(name, help=description)
+        cmd.set_defaults(command=implementation)
+    return parser
+
+def main(args):
+    parser = _make_parser()
+    args = parser.parse_args(args)
+    return args.command(args)
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv[1:]))

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


More information about the Python-checkins mailing list