def test_unhashable(): '''Test `SleekCallArgs` on unhashable arguments.''' sca_dict = {} args = ([1, 2], {1: [1, 2]}, {'a', 1}) sca1 = SleekCallArgs(sca_dict, f, *args) hash(sca1) sca_dict[sca1] = 'meow' del args gc_tools.collect() # GCed because there's a `set` in `args`, and it's weakreffable: assert len(sca_dict) == 0 kwargs = { 'a': {1: 2}, 'b': [ set(), {frozenset((3, 4))} ] } sca2 = SleekCallArgs(sca_dict, f, **kwargs) hash(sca2) sca_dict[sca2] = 'meow' del kwargs gc_tools.collect() # Not GCed because all objects in `kwargs` are not weakreffable: assert len(sca_dict) == 1
def test(): '''Test the basic workings of `WeakKeyDefaultDict`.''' wkd_dict = WeakKeyDefaultDict(default_factory=lambda: 7) weakreffable_object_0 = WeakreffableObject() weakreffable_object_1 = WeakreffableObject() weakreffable_object_2 = WeakreffableObject() weakreffable_object_3 = WeakreffableObject() wkd_dict[weakreffable_object_0] = 2 assert wkd_dict[weakreffable_object_0] == 2 assert wkd_dict[weakreffable_object_1] == 7 assert wkd_dict[weakreffable_object_2] == 7 assert weakreffable_object_0 in wkd_dict assert weakreffable_object_1 in wkd_dict assert weakreffable_object_2 in wkd_dict assert 'meow' not in wkd_dict assert sorted(wkd_dict.items()) == sorted(wkd_dict.iteritems()) == sorted( ((weakreffable_object_0, 2), (weakreffable_object_1, 7), (weakreffable_object_2, 7), ) ) assert set(wkd_dict.iterkeys()) == set(wkd_dict.keys()) == \ set((ref() for ref in wkd_dict.iterkeyrefs())) == \ set((ref() for ref in wkd_dict.keyrefs())) == \ set((weakreffable_object_0, weakreffable_object_1, weakreffable_object_2)) weakreffable_object_3 = WeakreffableObject() wkd_dict[weakreffable_object_3] = 123 assert len(wkd_dict.keys()) == 4 del weakreffable_object_3 gc_tools.collect() assert len(wkd_dict.keys()) == 3 assert wkd_dict.pop(weakreffable_object_2) == 7 assert len(wkd_dict) == 2 popped_key, popped_value = wkd_dict.popitem() assert popped_key in (weakreffable_object_0, weakreffable_object_1) assert popped_value in (2, 7) weakreffable_object_4 = WeakreffableObject() weakreffable_object_5 = WeakreffableObject() weakreffable_object_6 = WeakreffableObject() assert weakreffable_object_4 not in wkd_dict wkd_dict.setdefault(weakreffable_object_4, 222) assert wkd_dict[weakreffable_object_4] == 222 wkd_dict.update({weakreffable_object_5: 444,}) assert wkd_dict[weakreffable_object_5] == 444
def test_container_iterator(self): # Bug #3680: tp_traverse was not implemented for dictiter objects class C(object): pass iterators = (CuteSleekValueDict.iteritems, CuteSleekValueDict.itervalues, CuteSleekValueDict.iterkeys) for i in iterators: obj = C() ref = weakref.ref(obj) container = CuteSleekValueDict(null_callback, {obj: 1}) obj.x = i(container) del obj, container gc_tools.collect() self.assertIs(ref(), None, "Cycle was not collected")
def test_weak_keyed_cascading_deletes(self): # SF bug 742860. For some reason, before 2.3 __delitem__ iterated # over the keys via self.data.iterkeys(). If things vanished from # the dict during this (or got added), that caused a RuntimeError. d = WeakKeyIdentityDict() mutate = False class C(object): def __init__(self, i): self.value = i def __hash__(self): return hash(self.value) def __eq__(self, other): if mutate: # Side effect that mutates the dict, by removing the # last strong reference to a key. del objs[-1] return self.value == other.value objs = [C(i) for i in range(4)] for o in objs: d[o] = o.value del o # now the only strong references to keys are in objs # Find the order in which iterkeys sees the keys. objs = list(d.keys()) # Reverse it, so that the iteration implementation of __delitem__ # has to keep looping to find the first object we delete. objs.reverse() # Turn on mutation in C.__eq__. The first time thru the loop, # under the iterkeys() business the first comparison will delete # the last item iterkeys() would see, and that causes a # RuntimeError: dictionary changed size during iteration # when the iterkeys() loop goes around to try comparing the next # key. After this was fixed, it just deletes the last object *our* # "for o in obj" loop would have gotten to. mutate = True count = 0 for o in objs: count += 1 del d[o] gc_tools.collect() self.assertEqual(len(d), 0) self.assertEqual(count, 2)
def test(): '''Test the basic workings of `SleekCallArgs`.''' sca_dict = {} args = (1, 2) sca1 = SleekCallArgs(sca_dict, f, *args) sca_dict[sca1] = 'meow' del args gc_tools.collect() assert len(sca_dict) == 1 args = (1, A()) sca2 = SleekCallArgs(sca_dict, f, *args) sca_dict[sca2] = 'meow' del args gc_tools.collect() assert len(sca_dict) == 1
def test_one_by_one(): volatile_things = [A(), 1, 4.5, 'meow', u'woof', [1, 2], (1, 2), {1: 2}, {1, 2, 3}] unvolatile_things = [__builtins__, list, type, sum] # Using len(csvd) as our key; just to guarantee we're not running over an # existing key. while volatile_things: volatile_thing = volatile_things.pop() csvd = CuteSleekValueDict(counter) if _is_weakreffable(volatile_thing): csvd[len(csvd)] = volatile_thing count = counter() del volatile_thing gc_tools.collect() assert counter() == count + 2 else: csvd[len(csvd)] = volatile_thing count = counter() del volatile_thing gc_tools.collect() assert counter() == count + 1 while unvolatile_things: unvolatile_thing = unvolatile_things.pop() csvd = CuteSleekValueDict(counter) csvd[len(csvd)] = unvolatile_thing count = counter() del unvolatile_thing gc_tools.collect() assert counter() == count + 1
def test_weakref(): '''Test that `cache` weakrefs weakreffable arguments.''' f = cache()(counting_func) class A: pass a = A() result = f(a) assert result == f(a) == f(a) == f(a) a_ref = weakref.ref(a) del a gc_tools.collect() assert a_ref() is None a = A() result = f(meow=a) assert result == f(meow=a) == f(meow=a) == f(meow=a) a_ref = weakref.ref(a) del a gc_tools.collect() assert a_ref() is None
def test_sleek_ref(): '''Test the basic workings of `SleekRef`.''' volatile_things = [A(), 1, 4.5, 'meow', u'woof', [1, 2], (1, 2), {1: 2}, set((1, 2, 3)), (None, 3, {None: 4})] unvolatile_things = [__builtins__, type, sum, None] # (Used to have `list` here too but Pypy 2.0b choked on it.) while volatile_things: volatile_thing = volatile_things.pop() sleek_ref = SleekRef(volatile_thing, counter) assert sleek_ref() is volatile_thing if _is_weakreffable(volatile_thing): count = counter() del volatile_thing gc_tools.collect() assert counter() == count + 2 nose.tools.assert_raises(SleekRefDied, sleek_ref) else: count = counter() del volatile_thing gc_tools.collect() assert counter() == count + 1 assert sleek_ref() is not None while unvolatile_things: unvolatile_thing = unvolatile_things.pop() sleek_ref = SleekRef(unvolatile_thing, counter) assert sleek_ref() is unvolatile_thing count = counter() del unvolatile_thing gc_tools.collect() assert counter() == count + 1 # Ensuring it will not raise `SleekRefDied`: sleek_ref()
def assert_garbage_collected(indexes): gc_tools.collect() assert set(indexes) == garbage_collected