Commit 5a5d6a10 authored by Brett Cannon's avatar Brett Cannon

Merge

parents 8923a4d4 718fbf07
...@@ -6,6 +6,13 @@ such it requires the injection of specific modules and attributes in order to ...@@ -6,6 +6,13 @@ such it requires the injection of specific modules and attributes in order to
work. One should use importlib as the public-facing version of this module. 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. # See importlib._setup() for what is injected into the global namespace.
......
...@@ -593,28 +593,28 @@ class HandlerTest(BaseTest): ...@@ -593,28 +593,28 @@ class HandlerTest(BaseTest):
pass pass
time.sleep(0.004 * random.randint(0, 4)) time.sleep(0.004 * random.randint(0, 4))
def cleanup(remover, fn, handler): del_count = 500
handler.close() log_count = 500
remover.join()
if os.path.exists(fn):
os.unlink(fn)
for delay in (False, True):
fd, fn = tempfile.mkstemp('.log', 'test_logging-3-') fd, fn = tempfile.mkstemp('.log', 'test_logging-3-')
os.close(fd) os.close(fd)
del_count = 1000
log_count = 1000
remover = threading.Thread(target=remove_loop, args=(fn, del_count)) remover = threading.Thread(target=remove_loop, args=(fn, del_count))
remover.daemon = True remover.daemon = True
remover.start() remover.start()
for delay in (False, True):
h = logging.handlers.WatchedFileHandler(fn, delay=delay) h = logging.handlers.WatchedFileHandler(fn, delay=delay)
self.addCleanup(cleanup, remover, fn, h)
f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s') f = logging.Formatter('%(asctime)s: %(levelname)s: %(message)s')
h.setFormatter(f) h.setFormatter(f)
try:
for _ in range(log_count): for _ in range(log_count):
time.sleep(0.005) time.sleep(0.005)
r = logging.makeLogRecord({'msg': 'testing' }) r = logging.makeLogRecord({'msg': 'testing' })
h.handle(r) h.handle(r)
finally:
h.close()
remover.join()
if os.path.exists(fn):
os.unlink(fn)
class BadStream(object): class BadStream(object):
......
...@@ -61,7 +61,7 @@ def skip(reason): ...@@ -61,7 +61,7 @@ def skip(reason):
Unconditionally skip a test. Unconditionally skip a test.
""" """
def decorator(test_item): 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) @functools.wraps(test_item)
def skip_wrapper(*args, **kwargs): def skip_wrapper(*args, **kwargs):
raise SkipTest(reason) raise SkipTest(reason)
......
...@@ -66,6 +66,21 @@ class Test_TestSkipping(unittest.TestCase): ...@@ -66,6 +66,21 @@ class Test_TestSkipping(unittest.TestCase):
self.assertEqual(result.skipped, [(test, "testing")]) self.assertEqual(result.skipped, [(test, "testing")])
self.assertEqual(record, []) 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): def test_expected_failure(self):
class Foo(unittest.TestCase): class Foo(unittest.TestCase):
@unittest.expectedFailure @unittest.expectedFailure
......
...@@ -573,12 +573,23 @@ Modules/Setup: $(srcdir)/Modules/Setup.dist ...@@ -573,12 +573,23 @@ Modules/Setup: $(srcdir)/Modules/Setup.dist
Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST) $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
############################################################################ ############################################################################
# Importlib # Importlib
Python/importlib.h: $(srcdir)/Lib/importlib/_bootstrap.py $(srcdir)/Python/freeze_importlib.py Python/importlib.h: $(srcdir)/Lib/importlib/_bootstrap.py $(srcdir)/Python/freeze_importlib.py
@if test -f ./$(BUILDPYTHON); then \
./$(BUILDPYTHON) $(srcdir)/Python/freeze_importlib.py \ ./$(BUILDPYTHON) $(srcdir)/Python/freeze_importlib.py \
$(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h $(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 # Special rules for object files
......
...@@ -71,6 +71,9 @@ Core and Builtins ...@@ -71,6 +71,9 @@ Core and Builtins
Library 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 - Issue #4892: multiprocessing Connections can now be transferred over
multiprocessing Connections. Patch by Richard Oudkerk (sbt). multiprocessing Connections. Patch by Richard Oudkerk (sbt).
...@@ -186,6 +189,9 @@ Tests ...@@ -186,6 +189,9 @@ Tests
Tools / Demos 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. - Issue #13165: stringbench is now available in the Tools/stringbench folder.
It used to live in its own SVN project. It used to live in its own SVN project.
......
...@@ -1657,6 +1657,7 @@ long_to_decimal_string(PyObject *aa) ...@@ -1657,6 +1657,7 @@ long_to_decimal_string(PyObject *aa)
/* check we've counted correctly */ /* check we've counted correctly */
assert(p == PyUnicode_1BYTE_DATA(str)); assert(p == PyUnicode_1BYTE_DATA(str));
assert(_PyUnicode_CheckConsistency(str, 1));
Py_DECREF(scratch); Py_DECREF(scratch);
return (PyObject *)str; return (PyObject *)str;
} }
...@@ -1761,6 +1762,7 @@ _PyLong_Format(PyObject *aa, int base) ...@@ -1761,6 +1762,7 @@ _PyLong_Format(PyObject *aa, int base)
if (negative) if (negative)
*--p = '-'; *--p = '-';
assert(p == PyUnicode_1BYTE_DATA(v)); assert(p == PyUnicode_1BYTE_DATA(v));
assert(_PyUnicode_CheckConsistency(v, 1));
return v; return v;
} }
......
...@@ -375,10 +375,13 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) ...@@ -375,10 +375,13 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
{ {
Py_ssize_t i; Py_ssize_t i;
Py_UCS4 maxchar = 0; 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++) for (i=0; i < ascii->length; i++)
{ {
Py_UCS4 ch = PyUnicode_READ(kind, data, i); ch = PyUnicode_READ(kind, data, i);
if (ch > maxchar) if (ch > maxchar)
maxchar = ch; maxchar = ch;
} }
...@@ -398,6 +401,7 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) ...@@ -398,6 +401,7 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
assert(maxchar >= 0x10000); assert(maxchar >= 0x10000);
assert(maxchar <= MAX_UNICODE); assert(maxchar <= MAX_UNICODE);
} }
assert(PyUnicode_READ(kind, data, ascii->length) == 0);
} }
return 1; return 1;
} }
......
No preview for this file type
...@@ -454,6 +454,10 @@ def add_ui(db): ...@@ -454,6 +454,10 @@ def add_ui(db):
("SetDLLDirToTarget", 'DLLDIR=""', 751), ("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 # Execute Sequences
add_data(db, "InstallExecuteSequence", add_data(db, "InstallExecuteSequence",
[("InitialTargetDir", 'TARGETDIR=""', 750), [("InitialTargetDir", 'TARGETDIR=""', 750),
...@@ -677,11 +681,11 @@ def add_ui(db): ...@@ -677,11 +681,11 @@ def add_ui(db):
c=features.xbutton("Advanced", "Advanced", None, 0.30) c=features.xbutton("Advanced", "Advanced", None, 0.30)
c.event("SpawnDialog", "AdvancedDlg") 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.") "Multiline description of the currently selected item.")
c.mapping("SelectionDescription","Text") 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.") "The size of the currently selected item.")
c.mapping("SelectionSize", "Text") c.mapping("SelectionSize", "Text")
...@@ -835,7 +839,7 @@ def add_features(db): ...@@ -835,7 +839,7 @@ def add_features(db):
# (i.e. additional Python libraries) need to follow the parent feature. # (i.e. additional Python libraries) need to follow the parent feature.
# Features that have no advertisement trigger (e.g. the test suite) # Features that have no advertisement trigger (e.g. the test suite)
# must not support advertisement # 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", default_feature = Feature(db, "DefaultFeature", "Python",
"Python Interpreter and Libraries", "Python Interpreter and Libraries",
1, directory = "TARGETDIR") 1, directory = "TARGETDIR")
...@@ -860,6 +864,15 @@ def add_features(db): ...@@ -860,6 +864,15 @@ def add_features(db):
testsuite = Feature(db, "Testsuite", "Test suite", testsuite = Feature(db, "Testsuite", "Test suite",
"Python test suite (Lib/test/)", 11, "Python test suite (Lib/test/)", 11,
parent = default_feature, attributes=2|8) 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(): def extract_msvcr90():
# Find the redistributable files # Find the redistributable files
...@@ -1146,6 +1159,8 @@ def add_registry(db): ...@@ -1146,6 +1159,8 @@ def add_registry(db):
"InstallPath"), "InstallPath"),
("REGISTRY.doc", msilib.gen_uuid(), "TARGETDIR", registry_component, None, ("REGISTRY.doc", msilib.gen_uuid(), "TARGETDIR", registry_component, None,
"Documentation"), "Documentation"),
("REGISTRY.path", msilib.gen_uuid(), "TARGETDIR", registry_component, None,
None),
("REGISTRY.def", msilib.gen_uuid(), "TARGETDIR", registry_component, ("REGISTRY.def", msilib.gen_uuid(), "TARGETDIR", registry_component,
None, None)] + tcldata) None, None)] + tcldata)
# See "FeatureComponents Table". # See "FeatureComponents Table".
...@@ -1162,6 +1177,7 @@ def add_registry(db): ...@@ -1162,6 +1177,7 @@ def add_registry(db):
add_data(db, "FeatureComponents", add_data(db, "FeatureComponents",
[(default_feature.id, "REGISTRY"), [(default_feature.id, "REGISTRY"),
(htmlfiles.id, "REGISTRY.doc"), (htmlfiles.id, "REGISTRY.doc"),
(prepend_path.id, "REGISTRY.path"),
(ext_feature.id, "REGISTRY.def")] + (ext_feature.id, "REGISTRY.def")] +
tcldata tcldata
) )
......
#!/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:]))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment