
from __future__ import print_function, absolute_import

import gc
import weakref

from numba import unittest_support as unittest
from numba.utils import IS_PY3
from numba import jit, types
from .support import TestCase


def global_func(x):
    return x + 1


class TestFuncLifetime(TestCase):
    """
    Test the lifetime of compiled function objects.
    """
    # NOTE: there's a test for closure lifetime in test_closure

    def check_local_func_lifetime(self, **jitargs):
        def f(x):
            return x + 1

        c_f = jit(**jitargs)(f)
        self.assertPreciseEqual(c_f(1), 2)

        refs = [weakref.ref(obj) for obj in (f, c_f)]
        obj = f = c_f = None
        gc.collect()
        self.assertEqual([wr() for wr in refs], [None] * len(refs))

    def test_local_func_lifetime(self):
        self.check_local_func_lifetime(forceobj=True)

    def test_local_func_lifetime_npm(self):
        self.check_local_func_lifetime(nopython=True)

    def check_global_func_lifetime(self, **jitargs):
        c_f = jit(**jitargs)(global_func)
        self.assertPreciseEqual(c_f(1), 2)

        wr = weakref.ref(c_f)
        c_f = None
        gc.collect()
        self.assertIs(wr(), None)

    def test_global_func_lifetime(self):
        self.check_global_func_lifetime(forceobj=True)

    def test_global_func_lifetime_npm(self):
        self.check_global_func_lifetime(nopython=True)


if __name__ == '__main__':
    unittest.main()

@@ -215,16 +215,95 @@
 tCase%0A%0A%0A
+class Dummy(object):%0A%0A    def __add__(self, other):%0A        return other + 5%0A%0A%0A
 def glob
@@ -305,20 +305,24 @@
  global_
-func
+usecase1
 (x):%0A   
@@ -336,16 +336,66 @@
  x + 1%0A%0A
+def global_usecase2():%0A    return global_obj + 1%0A%0A
 %0Aclass T
@@ -479,16 +479,39 @@
  objects
+ and their dependencies
 .%0A    %22%22
@@ -1205,20 +1205,24 @@
 (global_
-func
+usecase1
 )%0A      
@@ -1562,16 +1562,786 @@
 =True)%0A%0A
+    def check_global_obj_lifetime(self, **jitargs):%0A        # Since global objects can be recorded for typing purposes,%0A        # check that they are not kept around after they are removed%0A        # from the globals.%0A        global global_obj%0A        global_obj = Dummy()%0A%0A        c_f = jit(**jitargs)(global_usecase2)%0A        self.assertPreciseEqual(c_f(), 6)%0A%0A        # XXX global_obj will survive, perhaps because of buggy code%0A        # generation.%0A        refs = %5Bweakref.ref(obj) for obj in (c_f, global_obj)%5D%0A        obj = c_f = global_obj = None%0A        gc.collect()%0A        self.assertEqual(%5Bwr() for wr in refs%5D, %5BNone%5D * len(refs))%0A%0A    @unittest.expectedFailure%0A    def test_global_obj_lifetime(self):%0A        self.check_global_obj_lifetime(forceobj=True)%0A%0A%0A
 %0Aif __na

Add failing test (because of separate lifetime issues?)