def test_cache_non_weak_referenceable_objects(self): cache = LocalWeakReferencedCache() k1 = None k2 = 1 k3 = [1, 2, 3] cache[k1] = 1 cache[k2] = 2 cache[k3] = 3 self.assertNotIn(k1, cache) self.assertNotIn(k2, cache) self.assertNotIn(k3, cache) self.assertEqual(len(cache), 0)
def test_cache_with_limit(self): cache = LocalWeakReferencedCache(limit=2) r1 = Request('https://example.org') r2 = Request('https://example.com') r3 = Request('https://example.net') cache[r1] = 1 cache[r2] = 2 cache[r3] = 3 self.assertEqual(len(cache), 2) self.assertNotIn(r1, cache) self.assertIn(r2, cache) self.assertIn(r3, cache) self.assertEqual(cache[r2], 2) self.assertEqual(cache[r3], 3) del r2 # PyPy takes longer to collect dead references garbage_collect() self.assertEqual(len(cache), 1)
def test_cache_without_limit(self): max = 10**4 cache = LocalWeakReferencedCache() refs = [] for x in range(max): refs.append(Request(f'https://example.org/{x}')) cache[refs[-1]] = x self.assertEqual(len(cache), max) for i, r in enumerate(refs): self.assertIn(r, cache) self.assertEqual(cache[r], i) del r # delete reference to the last object in the list # delete half of the objects, make sure that is reflected in the cache for _ in range(max // 2): refs.pop() # PyPy takes longer to collect dead references garbage_collect() self.assertEqual(len(cache), max // 2) for i, r in enumerate(refs): self.assertIn(r, cache) self.assertEqual(cache[r], i)
"""Similar to ``ast.walk``, but walks only function body and skips nested functions defined within the node. """ todo = deque([node]) walked_func_def = False while todo: node = todo.popleft() if isinstance(node, ast.FunctionDef): if walked_func_def: continue walked_func_def = True todo.extend(ast.iter_child_nodes(node)) yield node _generator_callbacks_cache = LocalWeakReferencedCache(limit=128) def is_generator_with_return_value(callable): """ Returns True if a callable is a generator function which includes a 'return' statement with a value different than None, False otherwise """ if callable in _generator_callbacks_cache: return _generator_callbacks_cache[callable] def returns_none(return_node): value = return_node.value return value is None or isinstance(value, ast.NameConstant) and value.value is None if inspect.isgeneratorfunction(callable):