summaryrefslogtreecommitdiff
path: root/numpy/testing/_private/utils.py
diff options
context:
space:
mode:
authorTyler Reddy <tyler.je.reddy@gmail.com>2019-04-22 10:02:38 -0700
committerGitHub <noreply@github.com>2019-04-22 10:02:38 -0700
commit2b59dcb273f00e7be13cdc32c5f396a55781c2f4 (patch)
tree6cba210849f975707bd0d6d5313294297765483b /numpy/testing/_private/utils.py
parent365e8b319c3756afe80d1b41de1a812f76be872c (diff)
parentf402a691a9c99e0ba2e090d4f8269ea81aac1a50 (diff)
downloadnumpy-2b59dcb273f00e7be13cdc32c5f396a55781c2f4.tar.gz
Merge pull request #12594 from mattip/pypy3-testing
DEV, BUILD: add pypy3 to azure CI
Diffstat (limited to 'numpy/testing/_private/utils.py')
-rw-r--r--numpy/testing/_private/utils.py21
1 files changed, 20 insertions, 1 deletions
diff --git a/numpy/testing/_private/utils.py b/numpy/testing/_private/utils.py
index 1f7b516b3..24e26d65c 100644
--- a/numpy/testing/_private/utils.py
+++ b/numpy/testing/_private/utils.py
@@ -6,6 +6,7 @@ from __future__ import division, absolute_import, print_function
import os
import sys
+import platform
import re
import gc
import operator
@@ -39,6 +40,7 @@ __all__ = [
'SkipTest', 'KnownFailureException', 'temppath', 'tempdir', 'IS_PYPY',
'HAS_REFCOUNT', 'suppress_warnings', 'assert_array_compare',
'_assert_valid_refcount', '_gen_alignment_data', 'assert_no_gc_cycles',
+ 'break_cycles',
]
@@ -50,7 +52,7 @@ class KnownFailureException(Exception):
KnownFailureTest = KnownFailureException # backwards compat
verbose = 0
-IS_PYPY = '__pypy__' in sys.modules
+IS_PYPY = platform.python_implementation() == 'PyPy'
HAS_REFCOUNT = getattr(sys, 'getrefcount', None) is not None
@@ -2245,6 +2247,7 @@ def _assert_no_gc_cycles_context(name=None):
# not meaningful to test if there is no refcounting
if not HAS_REFCOUNT:
+ yield
return
assert_(gc.isenabled())
@@ -2323,3 +2326,19 @@ def assert_no_gc_cycles(*args, **kwargs):
args = args[1:]
with _assert_no_gc_cycles_context(name=func.__name__):
func(*args, **kwargs)
+
+def break_cycles():
+ """
+ Break reference cycles by calling gc.collect
+ Objects can call other objects' methods (for instance, another object's
+ __del__) inside their own __del__. On PyPy, the interpreter only runs
+ between calls to gc.collect, so multiple calls are needed to completely
+ release all cycles.
+ """
+
+ gc.collect()
+ if IS_PYPY:
+ # interpreter runs now, to call deleted objects' __del__ methods
+ gc.collect()
+ # one more, just to make sure
+ gc.collect()