Merge tag 'v3.9.0a1'
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
index 19290bf..f2e5463 100644
--- a/Doc/library/subprocess.rst
+++ b/Doc/library/subprocess.rst
@@ -630,7 +630,7 @@
Popen and the other functions in this module that use it raise an
:ref:`auditing event <auditing>` ``subprocess.Popen`` with arguments
- ``executable``, ``args``, ``cwd``, ``env``. The value for ``args``
+ ``executable``, ``args``, ``cwd``, and ``env``. The value for ``args``
may be a single string or a list of strings, depending on platform.
.. versionchanged:: 3.2
diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst
index 746cf76..7faecff 100644
--- a/Doc/library/unittest.mock.rst
+++ b/Doc/library/unittest.mock.rst
@@ -915,6 +915,7 @@
>>> mock.async_foo
<AsyncMock name='mock.async_foo' id='...'>
+ .. versionadded:: 3.8
.. method:: assert_awaited()
diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst
index 9e66a2c..e2e4f2c 100644
--- a/Doc/library/unittest.rst
+++ b/Doc/library/unittest.rst
@@ -1563,7 +1563,7 @@
if __name__ == "__main__":
unittest.main()
- After running the test ``events`` would contain ``["setUp", "asyncSetUp", "test_response", "asyncTearDown", "tearDown", "cleanup"]``
+ After running the test, ``events`` would contain ``["setUp", "asyncSetUp", "test_response", "asyncTearDown", "tearDown", "cleanup"]``.
.. class:: FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None)
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h
index d89dbea..16baf10 100644
--- a/Include/internal/pycore_pylifecycle.h
+++ b/Include/internal/pycore_pylifecycle.h
@@ -57,6 +57,7 @@
extern PyStatus _PyTypes_Init(void);
extern PyStatus _PyImportZip_Init(PyThreadState *tstate);
+extern PyStatus _PyGC_Init(struct pyruntimestate *runtime);
/* Various internal finalizers */
diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h
index 535f99e..97d8fd9 100644
--- a/Include/internal/pycore_pymem.h
+++ b/Include/internal/pycore_pymem.h
@@ -144,7 +144,7 @@
Py_ssize_t long_lived_pending;
};
-PyAPI_FUNC(void) _PyGC_Initialize(struct _gc_runtime_state *);
+PyAPI_FUNC(void) _PyGC_InitializeRuntime(struct _gc_runtime_state *);
/* Set the memory allocator of the specified domain to the default.
diff --git a/Lib/asynchat.py b/Lib/asynchat.py
index fc1146a..f4ba361 100644
--- a/Lib/asynchat.py
+++ b/Lib/asynchat.py
@@ -117,7 +117,7 @@
data = self.recv(self.ac_in_buffer_size)
except BlockingIOError:
return
- except OSError as why:
+ except OSError:
self.handle_error()
return
diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py
index 830d8ed..8338449 100644
--- a/Lib/asyncio/proactor_events.py
+++ b/Lib/asyncio/proactor_events.py
@@ -711,7 +711,7 @@
raise exceptions.SendfileNotAvailableError("not a regular file")
try:
fsize = os.fstat(fileno).st_size
- except OSError as err:
+ except OSError:
raise exceptions.SendfileNotAvailableError("not a regular file")
blocksize = count if count else fsize
if not blocksize:
diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py
index 6621372..632546a 100644
--- a/Lib/asyncio/unix_events.py
+++ b/Lib/asyncio/unix_events.py
@@ -330,7 +330,7 @@
async def _sock_sendfile_native(self, sock, file, offset, count):
try:
os.sendfile
- except AttributeError as exc:
+ except AttributeError:
raise exceptions.SendfileNotAvailableError(
"os.sendfile() is not available")
try:
@@ -339,7 +339,7 @@
raise exceptions.SendfileNotAvailableError("not a regular file")
try:
fsize = os.fstat(fileno).st_size
- except OSError as err:
+ except OSError:
raise exceptions.SendfileNotAvailableError("not a regular file")
blocksize = count if count else fsize
if not blocksize:
diff --git a/Lib/codeop.py b/Lib/codeop.py
index e5c7ade..fc7e1e7 100644
--- a/Lib/codeop.py
+++ b/Lib/codeop.py
@@ -80,7 +80,7 @@
try:
code = compiler(source, filename, symbol)
- except SyntaxError as err:
+ except SyntaxError:
pass
try:
diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py
index 97973bc..01176bf 100644
--- a/Lib/ctypes/util.py
+++ b/Lib/ctypes/util.py
@@ -302,7 +302,7 @@
res = re.search(expr, os.fsdecode(out))
if res:
result = res.group(0)
- except Exception as e:
+ except Exception:
pass # result will be None
return result
diff --git a/Lib/distutils/tests/support.py b/Lib/distutils/tests/support.py
index 0413098..259af88 100644
--- a/Lib/distutils/tests/support.py
+++ b/Lib/distutils/tests/support.py
@@ -39,8 +39,6 @@
self.logs.append((level, msg, args))
def get_logs(self, *levels):
- def _format(msg, args):
- return msg % args
return [msg % args for level, msg, args
in self.logs if level in levels]
diff --git a/Lib/enum.py b/Lib/enum.py
index 8a6e5d2..06f42a9 100644
--- a/Lib/enum.py
+++ b/Lib/enum.py
@@ -420,7 +420,7 @@
if module is None:
try:
module = sys._getframe(2).f_globals['__name__']
- except (AttributeError, ValueError, KeyError) as exc:
+ except (AttributeError, ValueError, KeyError):
pass
if module is None:
_make_class_unpicklable(enum_class)
diff --git a/Lib/filecmp.py b/Lib/filecmp.py
index e5ad839..cfdca1e 100644
--- a/Lib/filecmp.py
+++ b/Lib/filecmp.py
@@ -156,12 +156,12 @@
ok = 1
try:
a_stat = os.stat(a_path)
- except OSError as why:
+ except OSError:
# print('Can\'t stat', a_path, ':', why.args[1])
ok = 0
try:
b_stat = os.stat(b_path)
- except OSError as why:
+ except OSError:
# print('Can\'t stat', b_path, ':', why.args[1])
ok = 0
diff --git a/Lib/getpass.py b/Lib/getpass.py
index 36e17e4..6911f41 100644
--- a/Lib/getpass.py
+++ b/Lib/getpass.py
@@ -52,7 +52,7 @@
stack.enter_context(input)
if not stream:
stream = input
- except OSError as e:
+ except OSError:
# If that fails, see if stdin can be controlled.
stack.close()
try:
diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py
index 4b2d3de..b1b5ccc 100644
--- a/Lib/importlib/abc.py
+++ b/Lib/importlib/abc.py
@@ -10,7 +10,7 @@
_frozen_importlib = None
try:
import _frozen_importlib_external
-except ImportError as exc:
+except ImportError:
_frozen_importlib_external = _bootstrap_external
import abc
import warnings
diff --git a/Lib/lib2to3/main.py b/Lib/lib2to3/main.py
index d6b7088..c51626b 100644
--- a/Lib/lib2to3/main.py
+++ b/Lib/lib2to3/main.py
@@ -90,11 +90,11 @@
if os.path.lexists(backup):
try:
os.remove(backup)
- except OSError as err:
+ except OSError:
self.log_message("Can't remove backup %s", backup)
try:
os.rename(filename, backup)
- except OSError as err:
+ except OSError:
self.log_message("Can't rename %s to %s", filename, backup)
# Actually write the new file
write = super(StdoutRefactoringTool, self).write_file
diff --git a/Lib/msilib/__init__.py b/Lib/msilib/__init__.py
index 0bc8dd9..0e85aa2 100644
--- a/Lib/msilib/__init__.py
+++ b/Lib/msilib/__init__.py
@@ -116,7 +116,7 @@
raise TypeError("Unsupported type %s" % field.__class__.__name__)
try:
v.Modify(MSIMODIFY_INSERT, r)
- except Exception as e:
+ except Exception:
raise MSIError("Could not insert "+repr(values)+" into "+table)
r.ClearData()
diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py
index 75b5150..1f9c2da 100644
--- a/Lib/multiprocessing/managers.py
+++ b/Lib/multiprocessing/managers.py
@@ -248,7 +248,7 @@
try:
obj, exposed, gettypeid = \
self.id_to_local_proxy_obj[ident]
- except KeyError as second_ke:
+ except KeyError:
raise ke
if methodname not in exposed:
@@ -296,7 +296,7 @@
try:
try:
send(msg)
- except Exception as e:
+ except Exception:
send(('#UNSERIALIZABLE', format_exc()))
except Exception as e:
util.info('exception in thread serving %r',
diff --git a/Lib/multiprocessing/popen_fork.py b/Lib/multiprocessing/popen_fork.py
index 11e2160..a65b06f 100644
--- a/Lib/multiprocessing/popen_fork.py
+++ b/Lib/multiprocessing/popen_fork.py
@@ -25,7 +25,7 @@
if self.returncode is None:
try:
pid, sts = os.waitpid(self.pid, flag)
- except OSError as e:
+ except OSError:
# Child process not yet created. See #1731717
# e.errno == errno.ECHILD == 10
return None
diff --git a/Lib/multiprocessing/process.py b/Lib/multiprocessing/process.py
index c62c826..be13c07 100644
--- a/Lib/multiprocessing/process.py
+++ b/Lib/multiprocessing/process.py
@@ -301,6 +301,8 @@
_current_process = self
_parent_process = _ParentProcess(
self._parent_name, self._parent_pid, parent_sentinel)
+ if threading._HAVE_THREAD_NATIVE_ID:
+ threading.main_thread()._set_native_id()
try:
util._finalizer_registry.clear()
util._run_after_forkers()
diff --git a/Lib/poplib.py b/Lib/poplib.py
index e3bd2ab..0b6750d 100644
--- a/Lib/poplib.py
+++ b/Lib/poplib.py
@@ -385,7 +385,7 @@
for capline in rawcaps:
capnm, capargs = _parsecap(capline)
caps[capnm] = capargs
- except error_proto as _err:
+ except error_proto:
raise error_proto('-ERR CAPA not supported by server')
return caps
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index f7bebc6..611291c 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -361,6 +361,28 @@
self.assertNotIn(p, self.active_children())
close_queue(q)
+ @unittest.skipUnless(threading._HAVE_THREAD_NATIVE_ID, "needs native_id")
+ def test_process_mainthread_native_id(self):
+ if self.TYPE == 'threads':
+ self.skipTest('test not appropriate for {}'.format(self.TYPE))
+
+ current_mainthread_native_id = threading.main_thread().native_id
+
+ q = self.Queue(1)
+ p = self.Process(target=self._test_process_mainthread_native_id, args=(q,))
+ p.start()
+
+ child_mainthread_native_id = q.get()
+ p.join()
+ close_queue(q)
+
+ self.assertNotEqual(current_mainthread_native_id, child_mainthread_native_id)
+
+ @classmethod
+ def _test_process_mainthread_native_id(cls, q):
+ mainthread_native_id = threading.main_thread().native_id
+ q.put(mainthread_native_id)
+
@classmethod
def _sleep_some(cls):
time.sleep(100)
diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py
index c8fedc7..c0bb051 100644
--- a/Lib/test/libregrtest/cmdline.py
+++ b/Lib/test/libregrtest/cmdline.py
@@ -207,10 +207,17 @@
group.add_argument('-m', '--match', metavar='PAT',
dest='match_tests', action='append',
help='match test cases and methods with glob pattern PAT')
+ group.add_argument('-i', '--ignore', metavar='PAT',
+ dest='ignore_tests', action='append',
+ help='ignore test cases and methods with glob pattern PAT')
group.add_argument('--matchfile', metavar='FILENAME',
dest='match_filename',
help='similar to --match but get patterns from a '
'text file, one pattern per line')
+ group.add_argument('--ignorefile', metavar='FILENAME',
+ dest='ignore_filename',
+ help='similar to --matchfile but it receives patterns '
+ 'from text file to ignore')
group.add_argument('-G', '--failfast', action='store_true',
help='fail as soon as a test fails (only with -v or -W)')
group.add_argument('-u', '--use', metavar='RES1,RES2,...',
@@ -317,7 +324,8 @@
findleaks=1, use_resources=None, trace=False, coverdir='coverage',
runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,
random_seed=None, use_mp=None, verbose3=False, forever=False,
- header=False, failfast=False, match_tests=None, pgo=False)
+ header=False, failfast=False, match_tests=None, ignore_tests=None,
+ pgo=False)
for k, v in kwargs.items():
if not hasattr(ns, k):
raise TypeError('%r is an invalid keyword argument '
@@ -395,6 +403,12 @@
with open(ns.match_filename) as fp:
for line in fp:
ns.match_tests.append(line.strip())
+ if ns.ignore_filename:
+ if ns.ignore_tests is None:
+ ns.ignore_tests = []
+ with open(ns.ignore_filename) as fp:
+ for line in fp:
+ ns.ignore_tests.append(line.strip())
if ns.forever:
# --forever implies --failfast
ns.failfast = True
diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
index 76ad335..1de51b7 100644
--- a/Lib/test/libregrtest/main.py
+++ b/Lib/test/libregrtest/main.py
@@ -287,7 +287,7 @@
def list_cases(self):
support.verbose = False
- support.set_match_tests(self.ns.match_tests)
+ support.set_match_tests(self.ns.match_tests, self.ns.ignore_tests)
for test_name in self.selected:
abstest = get_abs_module(self.ns, test_name)
diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py
index eeb108b..558f209 100644
--- a/Lib/test/libregrtest/runtest.py
+++ b/Lib/test/libregrtest/runtest.py
@@ -123,7 +123,7 @@
start_time = time.perf_counter()
try:
- support.set_match_tests(ns.match_tests)
+ support.set_match_tests(ns.match_tests, ns.ignore_tests)
support.junit_xml_list = xml_list = [] if ns.xmlpath else None
if ns.failfast:
support.failfast = True
diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py
index 797b3af..eab82c3 100644
--- a/Lib/test/pythoninfo.py
+++ b/Lib/test/pythoninfo.py
@@ -754,7 +754,7 @@
):
try:
collect_func(info_add)
- except Exception as exc:
+ except Exception:
error = True
print("ERROR: %s() failed" % (collect_func.__name__),
file=sys.stderr)
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 5ad32b8..7e1b30c 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -2096,7 +2096,9 @@
# By default, don't filter tests
_match_test_func = None
-_match_test_patterns = None
+
+_accept_test_patterns = None
+_ignore_test_patterns = None
def match_test(test):
@@ -2112,18 +2114,45 @@
# as a full test identifier.
# Example: 'test.test_os.FileTests.test_access'.
#
- # Reject patterns which contain fnmatch patterns: '*', '?', '[...]'
- # or '[!...]'. For example, reject 'test_access*'.
+ # ignore patterns which contain fnmatch patterns: '*', '?', '[...]'
+ # or '[!...]'. For example, ignore 'test_access*'.
return ('.' in pattern) and (not re.search(r'[?*\[\]]', pattern))
-def set_match_tests(patterns):
- global _match_test_func, _match_test_patterns
+def set_match_tests(accept_patterns=None, ignore_patterns=None):
+ global _match_test_func, _accept_test_patterns, _ignore_test_patterns
- if patterns == _match_test_patterns:
- # No change: no need to recompile patterns.
- return
+ if accept_patterns is None:
+ accept_patterns = ()
+ if ignore_patterns is None:
+ ignore_patterns = ()
+
+ accept_func = ignore_func = None
+
+ if accept_patterns != _accept_test_patterns:
+ accept_patterns, accept_func = _compile_match_function(accept_patterns)
+ if ignore_patterns != _ignore_test_patterns:
+ ignore_patterns, ignore_func = _compile_match_function(ignore_patterns)
+
+ # Create a copy since patterns can be mutable and so modified later
+ _accept_test_patterns = tuple(accept_patterns)
+ _ignore_test_patterns = tuple(ignore_patterns)
+
+ if accept_func is not None or ignore_func is not None:
+ def match_function(test_id):
+ accept = True
+ ignore = False
+ if accept_func:
+ accept = accept_func(test_id)
+ if ignore_func:
+ ignore = ignore_func(test_id)
+ return accept and not ignore
+
+ _match_test_func = match_function
+
+
+def _compile_match_function(patterns):
if not patterns:
func = None
# set_match_tests(None) behaves as set_match_tests(())
@@ -2151,10 +2180,7 @@
func = match_test_regex
- # Create a copy since patterns can be mutable and so modified later
- _match_test_patterns = tuple(patterns)
- _match_test_func = func
-
+ return patterns, func
def run_unittest(*classes):
diff --git a/Lib/test/test_asyncgen.py b/Lib/test/test_asyncgen.py
index 23eb6a4..58d8aee 100644
--- a/Lib/test/test_asyncgen.py
+++ b/Lib/test/test_asyncgen.py
@@ -735,6 +735,33 @@
self.loop.run_until_complete(run())
self.assertEqual(DONE, 10)
+ def test_async_gen_asyncio_aclose_12(self):
+ DONE = 0
+
+ async def target():
+ await asyncio.sleep(0.01)
+ 1 / 0
+
+ async def foo():
+ nonlocal DONE
+ task = asyncio.create_task(target())
+ try:
+ yield 1
+ finally:
+ try:
+ await task
+ except ZeroDivisionError:
+ DONE = 1
+
+ async def run():
+ gen = foo()
+ it = gen.__aiter__()
+ await it.__anext__()
+ await gen.aclose()
+
+ self.loop.run_until_complete(run())
+ self.assertEqual(DONE, 1)
+
def test_async_gen_asyncio_asend_01(self):
DONE = 0
diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py
index 14c0ec4..74041ed 100644
--- a/Lib/test/test_asynchat.py
+++ b/Lib/test/test_asynchat.py
@@ -73,14 +73,14 @@
self.set_terminator(terminator)
self.buffer = b""
- def handle_connect(self):
- pass
+ def handle_connect(self):
+ pass
- if sys.platform == 'darwin':
- # select.poll returns a select.POLLHUP at the end of the tests
- # on darwin, so just ignore it
- def handle_expt(self):
- pass
+ if sys.platform == 'darwin':
+ # select.poll returns a select.POLLHUP at the end of the tests
+ # on darwin, so just ignore it
+ def handle_expt(self):
+ pass
def collect_incoming_data(self, data):
self.buffer += data
diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py
index 5fa52bf..0aa7801 100644
--- a/Lib/test/test_buffer.py
+++ b/Lib/test/test_buffer.py
@@ -969,8 +969,6 @@
m.tobytes() # Releasing mm didn't release m
def verify_getbuf(self, orig_ex, ex, req, sliced=False):
- def simple_fmt(ex):
- return ex.format == '' or ex.format == 'B'
def match(req, flag):
return ((req&flag) == flag)
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index abccf32..6a88454 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -765,6 +765,7 @@
self.assertEqual(hash('spam'), hash(b'spam'))
hash((0,1,2,3))
def f(): pass
+ hash(f)
self.assertRaises(TypeError, hash, [])
self.assertRaises(TypeError, hash, {})
# Bug 1536021: Allow hash to return long objects
diff --git a/Lib/test/test_cgitb.py b/Lib/test/test_cgitb.py
index e299ec3..8991bc1 100644
--- a/Lib/test/test_cgitb.py
+++ b/Lib/test/test_cgitb.py
@@ -31,7 +31,7 @@
def test_text(self):
try:
raise ValueError("Hello World")
- except ValueError as err:
+ except ValueError:
text = cgitb.text(sys.exc_info())
self.assertIn("ValueError", text)
self.assertIn("Hello World", text)
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index 456f1be..7524f58 100644
--- a/Lib/test/test_class.py
+++ b/Lib/test/test_class.py
@@ -529,7 +529,7 @@
# In debug mode, printed XXX undetected error and
# raises AttributeError
I()
- except AttributeError as x:
+ except AttributeError:
pass
else:
self.fail("attribute error for I.__init__ got masked")
diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py
index 0d80af4..656c46c 100644
--- a/Lib/test/test_code.py
+++ b/Lib/test/test_code.py
@@ -241,7 +241,7 @@
def func2():
y = 2
return y
- code2 = func.__code__
+ code2 = func2.__code__
for attr, value in (
("co_argcount", 0),
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
index e1638c1..3aec34c 100644
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -11,7 +11,7 @@
try:
import _testcapi
-except ImportError as exc:
+except ImportError:
_testcapi = None
try:
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index 1f37b53..fe0cfc7 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -5600,13 +5600,13 @@
args, kwds = mkargs(C, c_sig)
try:
getattr(c_type(9), attr)(*args, **kwds)
- except Exception as err:
+ except Exception:
raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
args, kwds = mkargs(P, p_sig)
try:
getattr(p_type(9), attr)(*args, **kwds)
- except Exception as err:
+ except Exception:
raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
doit('Decimal')
diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py
index b0e4641..b8eef82 100644
--- a/Lib/test/test_ftplib.py
+++ b/Lib/test/test_ftplib.py
@@ -346,7 +346,7 @@
if err.args[0] in (ssl.SSL_ERROR_WANT_READ,
ssl.SSL_ERROR_WANT_WRITE):
return
- except OSError as err:
+ except OSError:
# Any "socket error" corresponds to a SSL_ERROR_SYSCALL return
# from OpenSSL's SSL_shutdown(), corresponding to a
# closed socket condition. See also:
diff --git a/Lib/test/test_importlib/import_/test_relative_imports.py b/Lib/test/test_importlib/import_/test_relative_imports.py
index 586a9bf..41aa182 100644
--- a/Lib/test/test_importlib/import_/test_relative_imports.py
+++ b/Lib/test/test_importlib/import_/test_relative_imports.py
@@ -133,6 +133,7 @@
self.assertEqual(module.__name__, 'pkg')
self.assertTrue(hasattr(module, 'subpkg2'))
self.assertEqual(module.subpkg2.attr, 'pkg.subpkg2.__init__')
+ self.relative_import_test(create, globals_, callback)
def test_deep_import(self):
# [deep import]
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index 5df7886..93f8d44 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -155,6 +155,24 @@
self.assertTrue(ns.single)
self.checkError([opt, '-f', 'foo'], "don't go together")
+ def test_ignore(self):
+ for opt in '-i', '--ignore':
+ with self.subTest(opt=opt):
+ ns = libregrtest._parse_args([opt, 'pattern'])
+ self.assertEqual(ns.ignore_tests, ['pattern'])
+ self.checkError([opt], 'expected one argument')
+
+ self.addCleanup(support.unlink, support.TESTFN)
+ with open(support.TESTFN, "w") as fp:
+ print('matchfile1', file=fp)
+ print('matchfile2', file=fp)
+
+ filename = os.path.abspath(support.TESTFN)
+ ns = libregrtest._parse_args(['-m', 'match',
+ '--ignorefile', filename])
+ self.assertEqual(ns.ignore_tests,
+ ['matchfile1', 'matchfile2'])
+
def test_match(self):
for opt in '-m', '--match':
with self.subTest(opt=opt):
@@ -961,6 +979,42 @@
regex = re.compile("^(test[^ ]+).*ok$", flags=re.MULTILINE)
return [match.group(1) for match in regex.finditer(output)]
+ def test_ignorefile(self):
+ code = textwrap.dedent("""
+ import unittest
+
+ class Tests(unittest.TestCase):
+ def test_method1(self):
+ pass
+ def test_method2(self):
+ pass
+ def test_method3(self):
+ pass
+ def test_method4(self):
+ pass
+ """)
+ all_methods = ['test_method1', 'test_method2',
+ 'test_method3', 'test_method4']
+ testname = self.create_test(code=code)
+
+ # only run a subset
+ filename = support.TESTFN
+ self.addCleanup(support.unlink, filename)
+
+ subset = [
+ # only ignore the method name
+ 'test_method1',
+ # ignore the full identifier
+ '%s.Tests.test_method3' % testname]
+ with open(filename, "w") as fp:
+ for name in subset:
+ print(name, file=fp)
+
+ output = self.run_tests("-v", "--ignorefile", filename, testname)
+ methods = self.parse_methods(output)
+ subset = ['test_method2', 'test_method4']
+ self.assertEqual(methods, subset)
+
def test_matchfile(self):
code = textwrap.dedent("""
import unittest
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
index 8f0746a..e3ce670 100644
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -527,6 +527,7 @@
test_access = Test('test.test_os.FileTests.test_access')
test_chdir = Test('test.test_os.Win32ErrorTests.test_chdir')
+ # Test acceptance
with support.swap_attr(support, '_match_test_func', None):
# match all
support.set_match_tests([])
@@ -534,45 +535,92 @@
self.assertTrue(support.match_test(test_chdir))
# match all using None
- support.set_match_tests(None)
+ support.set_match_tests(None, None)
self.assertTrue(support.match_test(test_access))
self.assertTrue(support.match_test(test_chdir))
# match the full test identifier
- support.set_match_tests([test_access.id()])
+ support.set_match_tests([test_access.id()], None)
self.assertTrue(support.match_test(test_access))
self.assertFalse(support.match_test(test_chdir))
# match the module name
- support.set_match_tests(['test_os'])
+ support.set_match_tests(['test_os'], None)
self.assertTrue(support.match_test(test_access))
self.assertTrue(support.match_test(test_chdir))
# Test '*' pattern
- support.set_match_tests(['test_*'])
+ support.set_match_tests(['test_*'], None)
self.assertTrue(support.match_test(test_access))
self.assertTrue(support.match_test(test_chdir))
# Test case sensitivity
- support.set_match_tests(['filetests'])
+ support.set_match_tests(['filetests'], None)
self.assertFalse(support.match_test(test_access))
- support.set_match_tests(['FileTests'])
+ support.set_match_tests(['FileTests'], None)
self.assertTrue(support.match_test(test_access))
# Test pattern containing '.' and a '*' metacharacter
- support.set_match_tests(['*test_os.*.test_*'])
+ support.set_match_tests(['*test_os.*.test_*'], None)
self.assertTrue(support.match_test(test_access))
self.assertTrue(support.match_test(test_chdir))
# Multiple patterns
- support.set_match_tests([test_access.id(), test_chdir.id()])
+ support.set_match_tests([test_access.id(), test_chdir.id()], None)
self.assertTrue(support.match_test(test_access))
self.assertTrue(support.match_test(test_chdir))
- support.set_match_tests(['test_access', 'DONTMATCH'])
+ support.set_match_tests(['test_access', 'DONTMATCH'], None)
self.assertTrue(support.match_test(test_access))
self.assertFalse(support.match_test(test_chdir))
+ # Test rejection
+ with support.swap_attr(support, '_match_test_func', None):
+ # match all
+ support.set_match_tests(ignore_patterns=[])
+ self.assertTrue(support.match_test(test_access))
+ self.assertTrue(support.match_test(test_chdir))
+
+ # match all using None
+ support.set_match_tests(None, None)
+ self.assertTrue(support.match_test(test_access))
+ self.assertTrue(support.match_test(test_chdir))
+
+ # match the full test identifier
+ support.set_match_tests(None, [test_access.id()])
+ self.assertFalse(support.match_test(test_access))
+ self.assertTrue(support.match_test(test_chdir))
+
+ # match the module name
+ support.set_match_tests(None, ['test_os'])
+ self.assertFalse(support.match_test(test_access))
+ self.assertFalse(support.match_test(test_chdir))
+
+ # Test '*' pattern
+ support.set_match_tests(None, ['test_*'])
+ self.assertFalse(support.match_test(test_access))
+ self.assertFalse(support.match_test(test_chdir))
+
+ # Test case sensitivity
+ support.set_match_tests(None, ['filetests'])
+ self.assertTrue(support.match_test(test_access))
+ support.set_match_tests(None, ['FileTests'])
+ self.assertFalse(support.match_test(test_access))
+
+ # Test pattern containing '.' and a '*' metacharacter
+ support.set_match_tests(None, ['*test_os.*.test_*'])
+ self.assertFalse(support.match_test(test_access))
+ self.assertFalse(support.match_test(test_chdir))
+
+ # Multiple patterns
+ support.set_match_tests(None, [test_access.id(), test_chdir.id()])
+ self.assertFalse(support.match_test(test_access))
+ self.assertFalse(support.match_test(test_chdir))
+
+ support.set_match_tests(None, ['test_access', 'DONTMATCH'])
+ self.assertFalse(support.match_test(test_access))
+ self.assertTrue(support.match_test(test_chdir))
+
def test_fd_count(self):
# We cannot test the absolute value of fd_count(): on old Linux
# kernel or glibc versions, os.urandom() keeps a FD open on
diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py
index fdd7894..d4e1ac2 100644
--- a/Lib/test/test_sys_settrace.py
+++ b/Lib/test/test_sys_settrace.py
@@ -161,8 +161,8 @@
def test_raise():
try:
raises()
- except Exception as exc:
- x = 1
+ except Exception:
+ pass
test_raise.events = [(0, 'call'),
(1, 'line'),
@@ -191,7 +191,7 @@
def settrace_and_raise(tracefunc):
try:
_settrace_and_raise(tracefunc)
- except RuntimeError as exc:
+ except RuntimeError:
pass
settrace_and_raise.events = [(2, 'exception'),
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
index 8d8d31e..80e43fa 100644
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -825,7 +825,7 @@
try:
result = pytime_converter(value, time_rnd)
expected = expected_func(value)
- except Exception as exc:
+ except Exception:
self.fail("Error on timestamp conversion: %s" % debug_info)
self.assertEqual(result,
expected,
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index 72dc7af..7135d99 100644
--- a/Lib/test/test_traceback.py
+++ b/Lib/test/test_traceback.py
@@ -313,7 +313,7 @@
with captured_output("stderr") as stderr_f:
try:
f()
- except RecursionError as exc:
+ except RecursionError:
render_exc()
else:
self.fail("no recursion occurred")
@@ -360,7 +360,7 @@
with captured_output("stderr") as stderr_g:
try:
g()
- except ValueError as exc:
+ except ValueError:
render_exc()
else:
self.fail("no value error was raised")
@@ -396,7 +396,7 @@
with captured_output("stderr") as stderr_h:
try:
h()
- except ValueError as exc:
+ except ValueError:
render_exc()
else:
self.fail("no value error was raised")
@@ -424,7 +424,7 @@
with captured_output("stderr") as stderr_g:
try:
g(traceback._RECURSIVE_CUTOFF)
- except ValueError as exc:
+ except ValueError:
render_exc()
else:
self.fail("no error raised")
@@ -452,7 +452,7 @@
with captured_output("stderr") as stderr_g:
try:
g(traceback._RECURSIVE_CUTOFF + 1)
- except ValueError as exc:
+ except ValueError:
render_exc()
else:
self.fail("no error raised")
diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py
index 040a2ce..bb0500e 100644
--- a/Lib/test/test_urllib2net.py
+++ b/Lib/test/test_urllib2net.py
@@ -199,7 +199,7 @@
try:
with urllib.request.urlopen(URL) as res:
pass
- except ValueError as e:
+ except ValueError:
self.fail("urlopen failed for site not sending \
Connection:close")
else:
diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py
index ddf7e6d..b76c60e 100644
--- a/Lib/test/test_uuid.py
+++ b/Lib/test/test_uuid.py
@@ -471,7 +471,7 @@
# the value from too_large_getter above.
try:
self.uuid.uuid1(node=node)
- except ValueError as e:
+ except ValueError:
self.fail('uuid1 was given an invalid node ID')
def test_uuid1(self):
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
index bac9789..fa64a6e 100644
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -712,7 +712,7 @@
function, args, kwargs = cls._class_cleanups.pop()
try:
function(*args, **kwargs)
- except Exception as exc:
+ except Exception:
cls.tearDown_exceptions.append(sys.exc_info())
def __call__(self, *args, **kwds):
diff --git a/Lib/unittest/test/testmock/testasync.py b/Lib/unittest/test/testmock/testasync.py
index 6b2d49d..0d2cdb0 100644
--- a/Lib/unittest/test/testmock/testasync.py
+++ b/Lib/unittest/test/testmock/testasync.py
@@ -335,6 +335,7 @@
@patch.object(AsyncClass, 'async_method', spec_set=True)
def test_async(async_method):
self.assertIsInstance(async_method, AsyncMock)
+ test_async()
def test_is_async_AsyncMock(self):
mock = AsyncMock(spec_set=AsyncClass.async_method)
diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
index 721c152..ebc4118 100644
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -1778,7 +1778,7 @@
hdrs = fp.info()
fp.close()
return url2pathname(_splithost(url1)[1]), hdrs
- except OSError as msg:
+ except OSError:
pass
fp = self.open(url, data)
try:
diff --git a/Lib/xml/sax/__init__.py b/Lib/xml/sax/__init__.py
index a0f5d40..17b7587 100644
--- a/Lib/xml/sax/__init__.py
+++ b/Lib/xml/sax/__init__.py
@@ -78,7 +78,7 @@
for parser_name in list(parser_list) + default_parser_list:
try:
return _create_parser(parser_name)
- except ImportError as e:
+ except ImportError:
import sys
if parser_name in sys.modules:
# The parser module was found, but importing it
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-07-13-18-01-13.bpo-35409.ozbcsR.rst b/Misc/NEWS.d/next/Core and Builtins/2019-07-13-18-01-13.bpo-35409.ozbcsR.rst
new file mode 100644
index 0000000..0f35a91
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-07-13-18-01-13.bpo-35409.ozbcsR.rst
@@ -0,0 +1,2 @@
+Ignore GeneratorExit exceptions when throwing an exception into the aclose
+coroutine of an asynchronous generator.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-11-08-00-36-10.bpo-38707.SZL036.rst b/Misc/NEWS.d/next/Core and Builtins/2019-11-08-00-36-10.bpo-38707.SZL036.rst
new file mode 100644
index 0000000..4ef9ed8
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-11-08-00-36-10.bpo-38707.SZL036.rst
@@ -0,0 +1 @@
+``MainThread.native_id`` is now correctly reset in child processes spawned using :class:`multiprocessing.Process`, instead of retaining the parent's value.
diff --git a/Misc/NEWS.d/next/Tests/2019-10-30-00-01-43.bpo-37957.X1r78F.rst b/Misc/NEWS.d/next/Tests/2019-10-30-00-01-43.bpo-37957.X1r78F.rst
new file mode 100644
index 0000000..75e186e
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2019-10-30-00-01-43.bpo-37957.X1r78F.rst
@@ -0,0 +1,3 @@
+test.regrtest now can receive a list of test patterns to ignore (using the
+-i/--ignore argument) or a file with a list of patterns to ignore (using the
+--ignore-file argument). Patch by Pablo Galindo.
diff --git a/Misc/NEWS.d/next/Tests/2019-11-18-22-10-55.bpo-38839.di6tXv.rst b/Misc/NEWS.d/next/Tests/2019-11-18-22-10-55.bpo-38839.di6tXv.rst
new file mode 100644
index 0000000..80c5a5b
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2019-11-18-22-10-55.bpo-38839.di6tXv.rst
@@ -0,0 +1 @@
+Fix some unused functions in tests. Patch by Adam Johnson.
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 129a104..d128053 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -1334,25 +1334,36 @@
#ifdef MS_WINDOWS
/* RaiseException() codes (prefixed by an underscore) */
if (PyModule_AddIntConstant(m, "_EXCEPTION_ACCESS_VIOLATION",
- EXCEPTION_ACCESS_VIOLATION))
- return NULL;
+ EXCEPTION_ACCESS_VIOLATION)) {
+ goto error;
+ }
if (PyModule_AddIntConstant(m, "_EXCEPTION_INT_DIVIDE_BY_ZERO",
- EXCEPTION_INT_DIVIDE_BY_ZERO))
- return NULL;
+ EXCEPTION_INT_DIVIDE_BY_ZERO)) {
+ goto error;
+ }
if (PyModule_AddIntConstant(m, "_EXCEPTION_STACK_OVERFLOW",
- EXCEPTION_STACK_OVERFLOW))
- return NULL;
+ EXCEPTION_STACK_OVERFLOW)) {
+ goto error;
+ }
/* RaiseException() flags (prefixed by an underscore) */
if (PyModule_AddIntConstant(m, "_EXCEPTION_NONCONTINUABLE",
- EXCEPTION_NONCONTINUABLE))
- return NULL;
+ EXCEPTION_NONCONTINUABLE)) {
+ goto error;
+ }
if (PyModule_AddIntConstant(m, "_EXCEPTION_NONCONTINUABLE_EXCEPTION",
- EXCEPTION_NONCONTINUABLE_EXCEPTION))
- return NULL;
+ EXCEPTION_NONCONTINUABLE_EXCEPTION)) {
+ goto error;
+ }
#endif
return m;
+
+#ifdef MS_WINDOWS
+error:
+ Py_DECREF(m);
+ return NULL;
+#endif
}
static int
diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c
index 1e5b0f7..11906aa 100644
--- a/Modules/fcntlmodule.c
+++ b/Modules/fcntlmodule.c
@@ -668,8 +668,10 @@
return NULL;
/* Add some symbolic constants to the module */
- if (all_ins(m) < 0)
+ if (all_ins(m) < 0) {
+ Py_DECREF(m);
return NULL;
+ }
return m;
}
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index cb7a3de..78f6631 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -25,7 +25,9 @@
#include "Python.h"
#include "pycore_context.h"
+#include "pycore_initconfig.h"
#include "pycore_object.h"
+#include "pycore_pyerrors.h"
#include "pycore_pymem.h"
#include "pycore_pystate.h"
#include "frameobject.h" /* for PyFrame_ClearFreeList */
@@ -129,7 +131,7 @@
#define GEN_HEAD(state, n) (&(state)->generations[n].head)
void
-_PyGC_Initialize(struct _gc_runtime_state *state)
+_PyGC_InitializeRuntime(struct _gc_runtime_state *state)
{
state->enabled = 1; /* automatic collection enabled? */
@@ -151,6 +153,21 @@
state->permanent_generation = permanent_generation;
}
+
+PyStatus
+_PyGC_Init(_PyRuntimeState *runtime)
+{
+ struct _gc_runtime_state *state = &runtime->gc;
+ if (state->garbage == NULL) {
+ state->garbage = PyList_New(0);
+ if (state->garbage == NULL) {
+ return _PyStatus_NO_MEMORY();
+ }
+ }
+ return _PyStatus_OK();
+}
+
+
/*
_gc_prev values
---------------
@@ -901,23 +918,20 @@
* merged into the old list regardless.
*/
static void
-handle_legacy_finalizers(struct _gc_runtime_state *state,
+handle_legacy_finalizers(PyThreadState *tstate,
+ struct _gc_runtime_state *state,
PyGC_Head *finalizers, PyGC_Head *old)
{
- assert(!PyErr_Occurred());
+ assert(!_PyErr_Occurred(tstate));
+ assert(state->garbage != NULL);
PyGC_Head *gc = GC_NEXT(finalizers);
- if (state->garbage == NULL) {
- state->garbage = PyList_New(0);
- if (state->garbage == NULL)
- Py_FatalError("gc couldn't create gc.garbage list");
- }
for (; gc != finalizers; gc = GC_NEXT(gc)) {
PyObject *op = FROM_GC(gc);
if ((state->debug & DEBUG_SAVEALL) || has_legacy_finalizer(op)) {
if (PyList_Append(state->garbage, op) < 0) {
- PyErr_Clear();
+ _PyErr_Clear(tstate);
break;
}
}
@@ -967,10 +981,10 @@
* objects may be freed. It is possible I screwed something up here.
*/
static void
-delete_garbage(struct _gc_runtime_state *state,
+delete_garbage(PyThreadState *tstate, struct _gc_runtime_state *state,
PyGC_Head *collectable, PyGC_Head *old)
{
- assert(!PyErr_Occurred());
+ assert(!_PyErr_Occurred(tstate));
while (!gc_list_is_empty(collectable)) {
PyGC_Head *gc = GC_NEXT(collectable);
@@ -982,7 +996,7 @@
if (state->debug & DEBUG_SAVEALL) {
assert(state->garbage != NULL);
if (PyList_Append(state->garbage, op) < 0) {
- PyErr_Clear();
+ _PyErr_Clear(tstate);
}
}
else {
@@ -990,7 +1004,7 @@
if ((clear = Py_TYPE(op)->tp_clear) != NULL) {
Py_INCREF(op);
(void) clear(op);
- if (PyErr_Occurred()) {
+ if (_PyErr_Occurred(tstate)) {
_PyErr_WriteUnraisableMsg("in tp_clear of",
(PyObject*)Py_TYPE(op));
}
@@ -1131,7 +1145,7 @@
/* This is the main function. Read this to understand how the
* collection process works. */
static Py_ssize_t
-collect(struct _gc_runtime_state *state, int generation,
+collect(PyThreadState *tstate, struct _gc_runtime_state *state, int generation,
Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, int nofail)
{
int i;
@@ -1233,7 +1247,7 @@
* in finalizers to be freed.
*/
m += gc_list_size(&final_unreachable);
- delete_garbage(state, &final_unreachable, old);
+ delete_garbage(tstate, state, &final_unreachable, old);
/* Collect statistics on uncollectable objects found and print
* debugging information. */
@@ -1254,7 +1268,7 @@
* reachable list of garbage. The programmer has to deal with
* this if they insist on creating this type of structure.
*/
- handle_legacy_finalizers(state, &finalizers, old);
+ handle_legacy_finalizers(tstate, state, &finalizers, old);
validate_list(old, collecting_clear_unreachable_clear);
/* Clear free list only during the collection of the highest
@@ -1263,9 +1277,9 @@
clear_freelists();
}
- if (PyErr_Occurred()) {
+ if (_PyErr_Occurred(tstate)) {
if (nofail) {
- PyErr_Clear();
+ _PyErr_Clear(tstate);
}
else {
if (gc_str == NULL)
@@ -1289,11 +1303,11 @@
stats->uncollectable += n;
if (PyDTrace_GC_DONE_ENABLED()) {
- PyDTrace_GC_DONE(n+m);
+ PyDTrace_GC_DONE(n + m);
}
- assert(!PyErr_Occurred());
- return n+m;
+ assert(!_PyErr_Occurred(tstate));
+ return n + m;
}
/* Invoke progress callbacks to notify clients that garbage collection
@@ -1344,19 +1358,20 @@
* progress callbacks.
*/
static Py_ssize_t
-collect_with_callback(struct _gc_runtime_state *state, int generation)
+collect_with_callback(PyThreadState *tstate, struct _gc_runtime_state *state,
+ int generation)
{
assert(!PyErr_Occurred());
Py_ssize_t result, collected, uncollectable;
invoke_gc_callback(state, "start", generation, 0, 0);
- result = collect(state, generation, &collected, &uncollectable, 0);
+ result = collect(tstate, state, generation, &collected, &uncollectable, 0);
invoke_gc_callback(state, "stop", generation, collected, uncollectable);
assert(!PyErr_Occurred());
return result;
}
static Py_ssize_t
-collect_generations(struct _gc_runtime_state *state)
+collect_generations(PyThreadState *tstate, struct _gc_runtime_state *state)
{
/* Find the oldest generation (highest numbered) where the count
* exceeds the threshold. Objects in the that generation and
@@ -1371,7 +1386,7 @@
if (i == NUM_GENERATIONS - 1
&& state->long_lived_pending < state->long_lived_total / 4)
continue;
- n = collect_with_callback(state, i);
+ n = collect_with_callback(tstate, state, i);
break;
}
}
@@ -1439,9 +1454,10 @@
gc_collect_impl(PyObject *module, int generation)
/*[clinic end generated code: output=b697e633043233c7 input=40720128b682d879]*/
{
+ PyThreadState *tstate = _PyThreadState_GET();
if (generation < 0 || generation >= NUM_GENERATIONS) {
- PyErr_SetString(PyExc_ValueError, "invalid generation");
+ _PyErr_SetString(tstate, PyExc_ValueError, "invalid generation");
return -1;
}
@@ -1453,7 +1469,7 @@
}
else {
state->collecting = 1;
- n = collect_with_callback(state, generation);
+ n = collect_with_callback(tstate, state, generation);
state->collecting = 0;
}
return n;
@@ -1928,7 +1944,9 @@
Py_ssize_t
PyGC_Collect(void)
{
+ PyThreadState *tstate = _PyThreadState_GET();
struct _gc_runtime_state *state = &_PyRuntime.gc;
+
if (!state->enabled) {
return 0;
}
@@ -1941,9 +1959,9 @@
else {
PyObject *exc, *value, *tb;
state->collecting = 1;
- PyErr_Fetch(&exc, &value, &tb);
- n = collect_with_callback(state, NUM_GENERATIONS - 1);
- PyErr_Restore(exc, value, tb);
+ _PyErr_Fetch(tstate, &exc, &value, &tb);
+ n = collect_with_callback(tstate, state, NUM_GENERATIONS - 1);
+ _PyErr_Restore(tstate, exc, value, tb);
state->collecting = 0;
}
@@ -1959,7 +1977,8 @@
Py_ssize_t
_PyGC_CollectNoFail(void)
{
- assert(!PyErr_Occurred());
+ PyThreadState *tstate = _PyThreadState_GET();
+ assert(!_PyErr_Occurred(tstate));
struct _gc_runtime_state *state = &_PyRuntime.gc;
Py_ssize_t n;
@@ -1975,7 +1994,7 @@
}
else {
state->collecting = 1;
- n = collect(state, NUM_GENERATIONS - 1, NULL, NULL, 1);
+ n = collect(tstate, state, NUM_GENERATIONS - 1, NULL, NULL, 1);
state->collecting = 0;
}
return n;
@@ -2086,19 +2105,23 @@
_PyObject_GC_Alloc(int use_calloc, size_t basicsize)
{
struct _gc_runtime_state *state = &_PyRuntime.gc;
- PyObject *op;
+ if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) {
+ return PyErr_NoMemory();
+ }
+ size_t size = sizeof(PyGC_Head) + basicsize;
+
PyGC_Head *g;
- size_t size;
- if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head))
- return PyErr_NoMemory();
- size = sizeof(PyGC_Head) + basicsize;
- if (use_calloc)
+ if (use_calloc) {
g = (PyGC_Head *)PyObject_Calloc(1, size);
- else
+ }
+ else {
g = (PyGC_Head *)PyObject_Malloc(size);
- if (g == NULL)
+ }
+ if (g == NULL) {
return PyErr_NoMemory();
+ }
assert(((uintptr_t)g & 3) == 0); // g must be aligned 4bytes boundary
+
g->_gc_next = 0;
g->_gc_prev = 0;
state->generations[0].count++; /* number of allocated GC objects */
@@ -2106,12 +2129,14 @@
state->enabled &&
state->generations[0].threshold &&
!state->collecting &&
- !PyErr_Occurred()) {
+ !PyErr_Occurred())
+ {
+ PyThreadState *tstate = _PyThreadState_GET();
state->collecting = 1;
- collect_generations(state);
+ collect_generations(tstate, state);
state->collecting = 0;
}
- op = FROM_GC(g);
+ PyObject *op = FROM_GC(g);
return op;
}
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 98eb9c3..c5fe999 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -1932,6 +1932,17 @@
PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
return NULL;
}
+ if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
+ PyErr_ExceptionMatches(PyExc_GeneratorExit))
+ {
+ /* when aclose() is called we don't want to propagate
+ StopAsyncIteration or GeneratorExit; just raise
+ StopIteration, signalling that this 'aclose()' await
+ is done.
+ */
+ PyErr_Clear();
+ PyErr_SetNone(PyExc_StopIteration);
+ }
return retval;
}
}
diff --git a/Python/marshal.c b/Python/marshal.c
index cb11c8c..ec6b3da 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -1829,6 +1829,9 @@
PyObject *mod = PyModule_Create(&marshalmodule);
if (mod == NULL)
return NULL;
- PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION);
+ if (PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION) < 0) {
+ Py_DECREF(mod);
+ return NULL;
+ }
return mod;
}
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index add7519..9739bb1 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -558,26 +558,29 @@
static PyStatus
-pycore_init_types(void)
+pycore_init_types(_PyRuntimeState *runtime)
{
- PyStatus status = _PyTypes_Init();
+ PyStatus status;
+
+ status = _PyGC_Init(runtime);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
+ status = _PyTypes_Init();
+ if (_PyStatus_EXCEPTION(status)) {
+ return status;
+ }
+
+ if (!_PyLong_Init()) {
+ return _PyStatus_ERR("can't init longs");
+ }
+
status = _PyUnicode_Init();
if (_PyStatus_EXCEPTION(status)) {
return status;
}
- if (_PyStructSequence_Init() < 0) {
- return _PyStatus_ERR("can't initialize structseq");
- }
-
- if (!_PyLong_Init()) {
- return _PyStatus_ERR("can't init longs");
- }
-
status = _PyExc_Init();
if (_PyStatus_EXCEPTION(status)) {
return status;
@@ -587,8 +590,8 @@
return _PyStatus_ERR("can't init float");
}
- if (!_PyContext_Init()) {
- return _PyStatus_ERR("can't init context");
+ if (_PyStructSequence_Init() < 0) {
+ return _PyStatus_ERR("can't initialize structseq");
}
status = _PyErr_Init();
@@ -596,6 +599,10 @@
return status;
}
+ if (!_PyContext_Init()) {
+ return _PyStatus_ERR("can't init context");
+ }
+
return _PyStatus_OK();
}
@@ -683,7 +690,7 @@
config = &tstate->interp->config;
*tstate_p = tstate;
- status = pycore_init_types();
+ status = pycore_init_types(runtime);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
@@ -1447,16 +1454,7 @@
}
config = &interp->config;
- status = _PyExc_Init();
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- status = _PyErr_Init();
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
+ status = pycore_init_types(runtime);
/* XXX The following is lax in error checking */
PyObject *modules = PyDict_New();
diff --git a/Python/pystate.c b/Python/pystate.c
index b4b1247..06cc9a8 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -58,7 +58,7 @@
runtime->open_code_userdata = open_code_userdata;
runtime->audit_hook_head = audit_hook_head;
- _PyGC_Initialize(&runtime->gc);
+ _PyGC_InitializeRuntime(&runtime->gc);
_PyEval_Initialize(&runtime->ceval);
PyPreConfig_InitPythonConfig(&runtime->preconfig);
diff --git a/Tools/ccbench/ccbench.py b/Tools/ccbench/ccbench.py
index 4f77a65..ab1465a 100644
--- a/Tools/ccbench/ccbench.py
+++ b/Tools/ccbench/ccbench.py
@@ -84,13 +84,6 @@
pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)', re.MULTILINE)
with open(__file__, "r") as f:
arg = f.read(2000)
-
- def findall(s):
- t = time.time()
- try:
- return pat.findall(s)
- finally:
- print(time.time() - t)
return pat.findall, (arg, )
def task_sort():