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)
예제 #2
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):