def wait_threads_exit(timeout=None): """ bpo-31234: Context manager to wait until all threads created in the with statement exit. Use _thread.count() to check if threads exited. Indirectly, wait until threads exit the internal t_bootstrap() C function of the _thread module. threading_setup() and threading_cleanup() are designed to emit a warning if a test leaves running threads in the background. This context manager is designed to cleanup threads started by the _thread.start_new_thread() which doesn't allow to wait for thread exit, whereas thread.Thread has a join() method. """ if timeout is None: timeout = support.SHORT_TIMEOUT old_count = _thread._count() try: yield finally: start_time = time.monotonic() deadline = start_time + timeout while True: count = _thread._count() if count <= old_count: break if time.monotonic() > deadline: dt = time.monotonic() - start_time msg = (f"wait_threads() failed to cleanup {count - old_count} " f"threads after {dt:.1f} seconds " f"(count: {count}, old count: {old_count})") raise AssertionError(msg) time.sleep(0.010) support.gc_collect()
def threading_cleanup(*original_values): _MAX_COUNT = 100 for count in range(_MAX_COUNT): values = _thread._count(), threading._dangling if values == original_values: break if not count: # Display a warning at the first iteration support.environment_altered = True dangling_threads = values[1] support.print_warning(f"threading_cleanup() failed to cleanup " f"{values[0] - original_values[0]} threads " f"(count: {values[0]}, " f"dangling: {len(dangling_threads)})") for thread in dangling_threads: support.print_warning(f"Dangling thread: {thread!r}") # Don't hold references to threads dangling_threads = None values = None time.sleep(0.01) support.gc_collect()
def testWeakRefs(self): # verify weak references p = proxy(self.f) p.write(bytes(range(10))) self.assertEqual(self.f.tell(), p.tell()) self.f.close() self.f = None gc_collect() # For PyPy or other GCs. self.assertRaises(ReferenceError, getattr, p, 'tell')
def _runtest_inner2(ns: Namespace, test_name: str) -> bool: # Load the test function, run the test function, handle huntrleaks # and findleaks to detect leaks abstest = get_abs_module(ns, test_name) # remove the module from sys.module to reload it if it was already imported try: del sys.modules[abstest] except KeyError: pass the_module = importlib.import_module(abstest) if ns.huntrleaks: from yp_test.libregrtest.refleak import dash_R # If the test has a test_main, that will run the appropriate # tests. If not, use normal unittest test loading. test_runner = getattr(the_module, "test_main", None) if test_runner is None: test_runner = functools.partial(_test_module, the_module) try: with save_env(ns, test_name): if ns.huntrleaks: # Return True if the test leaked references refleak = dash_R(ns, test_name, test_runner) else: test_runner() refleak = False finally: cleanup_test_droppings(test_name, ns.verbose) support.gc_collect() if gc.garbage: support.environment_altered = True print_warning(f"{test_name} created {len(gc.garbage)} " f"uncollectable object(s).") # move the uncollectable objects somewhere, # so we don't see them again FOUND_GARBAGE.extend(gc.garbage) gc.garbage.clear() support.reap_children() return refleak
def __exit__(self, exc_type, exc_val, exc_tb): saved_values = self.saved_values self.saved_values = None # Some resources use weak references support.gc_collect() for name, get, restore, original in saved_values: current = get() # Check for changes to the resource's value if current != original: support.environment_altered = True restore(original) if not self.quiet and not self.pgo: print_warning(f"{name} was modified by {self.testname}") print(f" Before: {original}\n After: {current} ", file=sys.stderr, flush=True) return False
def test_deepcopy_weakkeydict(self): class C(object): def __init__(self, i): self.i = i a, b, c, d = [C(i) for i in range(4)] u = weakref.WeakKeyDictionary() u[a] = b u[c] = d # Keys aren't copied, values are v = copy.deepcopy(u) self.assertNotEqual(v, u) self.assertEqual(yp_len(v), 2) self.assertIsNot(v[a], b) self.assertIsNot(v[c], d) self.assertEqual(v[a].i, b.i) self.assertEqual(v[c].i, d.i) del c support.gc_collect() # For PyPy or other GCs. self.assertEqual(yp_len(v), 1)
def check_no_warnings(testcase, message='', category=Warning, force_gc=False): """Context manager to check that no warnings are emitted. This context manager enables a given warning within its scope and checks that no warnings are emitted even with that warning enabled. If force_gc is True, a garbage collection is attempted before checking for warnings. This may help to catch warnings emitted when objects are deleted, such as ResourceWarning. Other keyword arguments are passed to warnings.filterwarnings(). """ from yp_test.support import gc_collect with warnings.catch_warnings(record=True) as warns: warnings.filterwarnings('always', message=message, category=category) yield if force_gc: gc_collect() testcase.assertEqual(warns, [])
def _check_copy_weakdict(self, _dicttype): class C(object): pass a, b, c, d = [C() for i in range(4)] u = _dicttype() u[a] = b u[c] = d v = copy.copy(u) self.assertIsNot(v, u) self.assertEqual(v, u) self.assertEqual(v[a], b) self.assertEqual(v[c], d) self.assertEqual(yp_len(v), 2) del c, d support.gc_collect() # For PyPy or other GCs. self.assertEqual(yp_len(v), 1) x, y = C(), C() # The underlying containers are decoupled v[x] = y self.assertNotIn(x, u)
def cleanup_test_droppings(test_name: str, verbose: int) -> None: # First kill any dangling references to open files etc. # This can also issue some ResourceWarnings which would otherwise get # triggered during the following test run, and possibly produce failures. support.gc_collect() # Try to clean up junk commonly left behind. While tests shouldn't leave # any files or directories behind, when a test fails that can be tedious # for it to arrange. The consequences can be especially nasty on Windows, # since if a test leaves a file open, it cannot be deleted by name (while # there's nothing we can do about that here either, we can display the # name of the offending test, which is a real help). for name in (os_helper.TESTFN, ): if not os.path.exists(name): continue if os.path.isdir(name): import shutil kind, nuker = "directory", shutil.rmtree elif os.path.isfile(name): kind, nuker = "file", os.unlink else: raise RuntimeError(f"os.path says {name!r} exists but is neither " f"directory nor file") if verbose: print_warning(f"{test_name} left behind {kind} {name!r}") support.environment_altered = True try: import stat # fix possible permissions problems that might prevent cleanup os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) nuker(name) except Exception as exc: print_warning(f"{test_name} left behind {kind} {name!r} " f"and it couldn't be removed: {exc}")
def test_deepcopy_weakvaluedict(self): class C(object): def __init__(self, i): self.i = i a, b, c, d = [C(i) for i in range(4)] u = weakref.WeakValueDictionary() u[a] = b u[c] = d # Keys are copied, values aren't v = copy.deepcopy(u) self.assertNotEqual(v, u) self.assertEqual(yp_len(v), 2) (x, y), (z, t) = sorted(v.items(), key=lambda pair: pair[0].i) self.assertIsNot(x, a) self.assertEqual(x.i, a.i) self.assertIs(y, b) self.assertIsNot(z, c) self.assertEqual(z.i, c.i) self.assertIs(t, d) del x, y, z, t del d support.gc_collect() # For PyPy or other GCs. self.assertEqual(yp_len(v), 1)
def clear_caches(): # Clear the warnings registry, so they can be displayed again for mod in sys.modules.values(): if hasattr(mod, '__warningregistry__'): del mod.__warningregistry__ # Flush standard output, so that buffered data is sent to the OS and # associated Python objects are reclaimed. for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__): if stream is not None: stream.flush() # Clear assorted module caches. # Don't worry about resetting the cache if the module is not loaded try: distutils_dir_util = sys.modules['distutils.dir_util'] except KeyError: pass else: distutils_dir_util._path_created.clear() try: re = sys.modules['re'] except KeyError: pass else: re.purge() try: _strptime = sys.modules['_strptime'] except KeyError: pass else: _strptime._regex_cache.clear() try: urllib_parse = sys.modules['urllib.parse'] except KeyError: pass else: urllib_parse.clear_cache() try: urllib_request = sys.modules['urllib.request'] except KeyError: pass else: urllib_request.urlcleanup() try: linecache = sys.modules['linecache'] except KeyError: pass else: linecache.clearcache() try: mimetypes = sys.modules['mimetypes'] except KeyError: pass else: mimetypes._default_mime_types() try: filecmp = sys.modules['filecmp'] except KeyError: pass else: filecmp._cache.clear() try: struct = sys.modules['struct'] except KeyError: pass else: struct._clearcache() try: doctest = sys.modules['doctest'] except KeyError: pass else: doctest.master = None try: ctypes = sys.modules['ctypes'] except KeyError: pass else: ctypes._reset_cache() try: typing = sys.modules['typing'] except KeyError: pass else: for f in typing._cleanups: f() support.gc_collect()