From 809a12e374fe702156c1c9a346a8dd74c28895fa Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Mon, 2 Apr 2018 10:19:16 +0200 Subject: tests: skip more getrefcount tests under PyPy --- pygtkcompat/generictreemodel.py | 11 ++++++-- tests/test_generictreemodel.py | 47 +++++++++++++++++++++---------- tests/test_gobject.py | 61 +++++++++++++++++++++++++---------------- tests/test_object_marshaling.py | 3 +- 4 files changed, 80 insertions(+), 42 deletions(-) diff --git a/pygtkcompat/generictreemodel.py b/pygtkcompat/generictreemodel.py index 1c264901..226dffc1 100644 --- a/pygtkcompat/generictreemodel.py +++ b/pygtkcompat/generictreemodel.py @@ -23,6 +23,7 @@ import sys import random import collections import ctypes +import platform # GObject from gi.repository import GObject @@ -41,9 +42,13 @@ class _CTreeIter(ctypes.Structure): return ctypes.POINTER(cls).from_address(id(iter) + offset) -def _get_user_data_as_pyobject(iter): - citer = _CTreeIter.from_iter(iter) - return ctypes.cast(citer.contents.user_data, ctypes.py_object).value +if platform.python_implementation() == "PyPy": + def _get_user_data_as_pyobject(iter): + raise NotImplementedError("Not yet supported under PyPy") +else: + def _get_user_data_as_pyobject(iter): + citer = _CTreeIter.from_iter(iter) + return ctypes.cast(citer.contents.user_data, ctypes.py_object).value def handle_exception(default_return): diff --git a/tests/test_generictreemodel.py b/tests/test_generictreemodel.py index d99c0560..5e9d716e 100644 --- a/tests/test_generictreemodel.py +++ b/tests/test_generictreemodel.py @@ -24,6 +24,7 @@ import gc import sys import weakref import unittest +import platform # pygobject from gi.repository import GObject @@ -137,6 +138,7 @@ class TestReferences(unittest.TestCase): def setUp(self): pass + @unittest.skipIf(platform.python_implementation() == "PyPy", "not with PyPy") def test_c_tree_iter_user_data_as_pyobject(self): obj = object() obj_id = id(obj) @@ -154,24 +156,28 @@ class TestReferences(unittest.TestCase): model = ATesterModel() obj_ref = weakref.ref(model.root) # Initial refcount is 1 for model.root + the temporary - self.assertEqual(sys.getrefcount(model.root), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 2) # Iter increases by 1 do to assignment to iter.user_data res, it = model.do_get_iter([0]) self.assertEqual(id(model.root), it.user_data) - self.assertEqual(sys.getrefcount(model.root), 3) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 3) # Verify getting a TreeIter more then once does not further increase # the ref count. res2, it2 = model.do_get_iter([0]) self.assertEqual(id(model.root), it2.user_data) - self.assertEqual(sys.getrefcount(model.root), 3) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 3) # Deleting the iter does not decrease refcount because references # leak by default (they are stored in the held_refs pool) del it gc.collect() - self.assertEqual(sys.getrefcount(model.root), 3) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 3) # Deleting a model should free all held references to user data # stored by TreeIters @@ -183,17 +189,20 @@ class TestReferences(unittest.TestCase): model = ATesterModel() obj_ref = weakref.ref(model.root) # Initial refcount is 1 for model.root + the temporary - self.assertEqual(sys.getrefcount(model.root), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 2) # Iter increases by 1 do to assignment to iter.user_data res, it = model.do_get_iter([0]) self.assertEqual(id(model.root), it.user_data) - self.assertEqual(sys.getrefcount(model.root), 3) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 3) # Notifying the underlying model of a row_deleted should decrease the # ref count. model.row_deleted(Gtk.TreePath('0'), model.root) - self.assertEqual(sys.getrefcount(model.root), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 2) # Finally deleting the actual object should collect it completely del model.root @@ -206,18 +215,21 @@ class TestReferences(unittest.TestCase): obj_ref = weakref.ref(model.root) # Initial refcount is 1 for model.root + the temporary - self.assertEqual(sys.getrefcount(model.root), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 2) # Iter does not increas count by 1 when leak_references is false res, it = model.do_get_iter([0]) self.assertEqual(id(model.root), it.user_data) - self.assertEqual(sys.getrefcount(model.root), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 2) # Deleting the iter does not decrease refcount because assigning user_data # eats references and does not release them. del it gc.collect() - self.assertEqual(sys.getrefcount(model.root), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(model.root), 2) # Deleting the model decreases the final ref, and the object is collected del model @@ -242,14 +254,16 @@ class TestReferences(unittest.TestCase): # 4 - ref held by the root/children graph itself # 5 - ref held by the model "held_refs" instance var for node in nodes: - self.assertEqual(sys.getrefcount(node), 5) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(node), 5) # A second iteration and storage of the nodes in a new list # should only increase refcounts by 1 even though new # iterators are created and assigned. nodes2 = [node for node in model.iter_depth_first()] for node in nodes2: - self.assertEqual(sys.getrefcount(node), 6) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(node), 6) # Hold weak refs and start verifying ref collection. node_refs = [weakref.ref(node) for node in nodes] @@ -258,14 +272,16 @@ class TestReferences(unittest.TestCase): del nodes2 gc.collect() for node in nodes: - self.assertEqual(sys.getrefcount(node), 5) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(node), 5) # Second round of collection, no more local lists of nodes. del nodes gc.collect() for ref in node_refs: node = ref() - self.assertEqual(sys.getrefcount(node), 4) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(node), 4) # Using invalidate_iters or row_deleted(path, node) will clear out # the pooled refs held internal to the GenericTreeModel implementation. @@ -274,7 +290,8 @@ class TestReferences(unittest.TestCase): gc.collect() for ref in node_refs: node = ref() - self.assertEqual(sys.getrefcount(node), 3) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(node), 3) # Deleting the root node at this point should allow all nodes to be collected # as there is no longer a way to reach the children diff --git a/tests/test_gobject.py b/tests/test_gobject.py index a72c41a8..3f7e0089 100644 --- a/tests/test_gobject.py +++ b/tests/test_gobject.py @@ -244,19 +244,23 @@ class TestPythonReferenceCounting(unittest.TestCase): def test_new_instance_has_two_refs(self): obj = GObject.GObject() - self.assertEqual(sys.getrefcount(obj), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(obj), 2) def test_new_instance_has_two_refs_using_gobject_new(self): obj = GObject.new(GObject.GObject) - self.assertEqual(sys.getrefcount(obj), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(obj), 2) def test_new_subclass_instance_has_two_refs(self): obj = A() - self.assertEqual(sys.getrefcount(obj), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(obj), 2) def test_new_subclass_instance_has_two_refs_using_gobject_new(self): obj = GObject.new(A) - self.assertEqual(sys.getrefcount(obj), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(obj), 2) class TestContextManagers(unittest.TestCase): @@ -281,14 +285,16 @@ class TestContextManagers(unittest.TestCase): self.assertEqual(self.tracking, [1, 2]) self.assertEqual(self.obj.__grefcount__, 1) - pyref_count = sys.getrefcount(self.obj) + if hasattr(sys, "getrefcount"): + pyref_count = sys.getrefcount(self.obj) # Using the context manager the tracking list should not be affected. # The GObject reference count should stay the same and the python # object ref-count should go up. with self.obj.freeze_notify(): self.assertEqual(self.obj.__grefcount__, 1) - self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1) self.obj.props.prop = 3 self.assertEqual(self.obj.props.prop, 3) self.assertEqual(self.tracking, [1, 2]) @@ -300,7 +306,8 @@ class TestContextManagers(unittest.TestCase): self.assertEqual(self.obj.props.prop, 3) self.assertEqual(self.tracking, [1, 2, 3]) self.assertEqual(self.obj.__grefcount__, 1) - self.assertEqual(sys.getrefcount(self.obj), pyref_count) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(self.obj), pyref_count) def test_handler_block_context(self): # Verify prop tracking list @@ -311,14 +318,16 @@ class TestContextManagers(unittest.TestCase): self.assertEqual(self.tracking, [1, 2]) self.assertEqual(self.obj.__grefcount__, 1) - pyref_count = sys.getrefcount(self.obj) + if hasattr(sys, "getrefcount"): + pyref_count = sys.getrefcount(self.obj) # Using the context manager the tracking list should not be affected. # The GObject reference count should stay the same and the python # object ref-count should go up. with self.obj.handler_block(self.handler): self.assertEqual(self.obj.__grefcount__, 1) - self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1) self.obj.props.prop = 3 self.assertEqual(self.obj.props.prop, 3) self.assertEqual(self.tracking, [1, 2]) @@ -330,7 +339,8 @@ class TestContextManagers(unittest.TestCase): self.assertEqual(self.obj.props.prop, 3) self.assertEqual(self.tracking, [1, 2]) self.assertEqual(self.obj.__grefcount__, 1) - self.assertEqual(sys.getrefcount(self.obj), pyref_count) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(self.obj), pyref_count) def test_freeze_notify_context_nested(self): self.assertEqual(self.tracking, []) @@ -513,17 +523,19 @@ class TestPropertyBindings(unittest.TestCase): self.assertEqual(user_data, test_data) return value // 2 - test_data_ref_count = sys.getrefcount(test_data) - transform_to_ref_count = sys.getrefcount(transform_to) - transform_from_ref_count = sys.getrefcount(transform_from) + if hasattr(sys, "getrefcount"): + test_data_ref_count = sys.getrefcount(test_data) + transform_to_ref_count = sys.getrefcount(transform_to) + transform_from_ref_count = sys.getrefcount(transform_from) # bidirectional bindings binding = self.source.bind_property('int_prop', self.target, 'int_prop', GObject.BindingFlags.BIDIRECTIONAL, transform_to, transform_from, test_data) binding = binding # PyFlakes - binding_ref_count = sys.getrefcount(binding) - binding_gref_count = binding.__grefcount__ + if hasattr(sys, "getrefcount"): + binding_ref_count = sys.getrefcount(binding) + binding_gref_count = binding.__grefcount__ self.source.int_prop = 1 self.assertEqual(self.source.int_prop, 1) @@ -533,13 +545,15 @@ class TestPropertyBindings(unittest.TestCase): self.assertEqual(self.source.int_prop, 2) self.assertEqual(self.target.int_prop, 4) - self.assertEqual(sys.getrefcount(binding), binding_ref_count) - self.assertEqual(binding.__grefcount__, binding_gref_count) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(binding), binding_ref_count) + self.assertEqual(binding.__grefcount__, binding_gref_count) # test_data ref count increases by 2, once for each callback. - self.assertEqual(sys.getrefcount(test_data), test_data_ref_count + 2) - self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count + 1) - self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count + 1) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(test_data), test_data_ref_count + 2) + self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count + 1) + self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count + 1) # Unbind should clear out the binding and its transforms binding.unbind() @@ -550,9 +564,10 @@ class TestPropertyBindings(unittest.TestCase): self.assertEqual(self.target.int_prop, 3) self.assertEqual(self.source.int_prop, 5) - self.assertEqual(sys.getrefcount(test_data), test_data_ref_count) - self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count) - self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(test_data), test_data_ref_count) + self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count) + self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count) def test_explicit_unbind_clears_connection(self): self.assertEqual(self.source.int_prop, 0) diff --git a/tests/test_object_marshaling.py b/tests/test_object_marshaling.py index 4fce5611..e50cbb61 100644 --- a/tests/test_object_marshaling.py +++ b/tests/test_object_marshaling.py @@ -110,7 +110,8 @@ class TestVFuncsWithObjectArg(unittest.TestCase): vfuncs.get_ref_info_for_vfunc_return_object_transfer_full() # Use any vfunc to test this. gc.collect() - self.assertEqual(sys.getrefcount(vfuncs), 2) + if hasattr(sys, "getrefcount"): + self.assertEqual(sys.getrefcount(vfuncs), 2) self.assertEqual(vfuncs.__grefcount__, 1) del vfuncs -- cgit v1.2.1