summaryrefslogtreecommitdiff
path: root/python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py')
-rw-r--r--python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py516
1 files changed, 516 insertions, 0 deletions
diff --git a/python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py b/python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py
new file mode 100644
index 000000000000..062ead2b5ff8
--- /dev/null
+++ b/python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py
@@ -0,0 +1,516 @@
+import os # @NoMove
+import sys # @NoMove
+sys.path.insert(0, os.path.realpath(os.path.abspath('..')))
+
+import pydevd_reload
+import tempfile
+import unittest
+
+
+SAMPLE_CODE = """
+class C:
+ def foo(self):
+ return 0
+
+ @classmethod
+ def bar(cls):
+ return (0, 0)
+
+ @staticmethod
+ def stomp():
+ return (0, 0, 0)
+
+ def unchanged(self):
+ return 'unchanged'
+"""
+
+
+
+class Test(unittest.TestCase):
+
+
+ def setUp(self):
+ unittest.TestCase.setUp(self)
+ self.tempdir = None
+ self.save_path = None
+ self.tempdir = tempfile.mkdtemp()
+ self.save_path = list(sys.path)
+ sys.path.append(self.tempdir)
+ try:
+ del sys.modules['x']
+ except:
+ pass
+
+
+ def tearDown(self):
+ unittest.TestCase.tearDown(self)
+ sys.path = self.save_path
+ try:
+ del sys.modules['x']
+ except:
+ pass
+
+ def make_mod(self, name="x", repl=None, subst=None, sample=SAMPLE_CODE):
+ fn = os.path.join(self.tempdir, name + ".py")
+ f = open(fn, "w")
+ if repl is not None and subst is not None:
+ sample = sample.replace(repl, subst)
+ try:
+ f.write(sample)
+ finally:
+ f.close()
+
+
+ def test_pydevd_reload(self):
+
+ self.make_mod()
+ import x
+
+ C = x.C
+ COut = C
+ Cfoo = C.foo
+ Cbar = C.bar
+ Cstomp = C.stomp
+
+ def check2(expected):
+ C = x.C
+ Cfoo = C.foo
+ Cbar = C.bar
+ Cstomp = C.stomp
+ b = C()
+ bfoo = b.foo
+ self.assertEqual(expected, b.foo())
+ self.assertEqual(expected, bfoo())
+ self.assertEqual(expected, Cfoo(b))
+
+ def check(expected):
+ b = COut()
+ bfoo = b.foo
+ self.assertEqual(expected, b.foo())
+ self.assertEqual(expected, bfoo())
+ self.assertEqual(expected, Cfoo(b))
+ self.assertEqual((expected, expected), Cbar())
+ self.assertEqual((expected, expected, expected), Cstomp())
+ check2(expected)
+
+ check(0)
+
+ # modify mod and reload
+ count = 0
+ while count < 1:
+ count += 1
+ self.make_mod(repl="0", subst=str(count))
+ pydevd_reload.xreload(x)
+ check(count)
+
+
+ def test_pydevd_reload2(self):
+
+ self.make_mod()
+ import x
+
+ c = x.C()
+ cfoo = c.foo
+ self.assertEqual(0, c.foo())
+ self.assertEqual(0, cfoo())
+
+ self.make_mod(repl="0", subst='1')
+ pydevd_reload.xreload(x)
+ self.assertEqual(1, c.foo())
+ self.assertEqual(1, cfoo())
+
+ def test_pydevd_reload3(self):
+ class F:
+ def m1(self):
+ return 1
+ class G:
+ def m1(self):
+ return 2
+
+ self.assertEqual(F().m1(), 1)
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertEqual(F().m1(), 2)
+
+
+ def test_pydevd_reload4(self):
+ class F:
+ pass
+ F.m1 = lambda a:None
+ class G:
+ pass
+ G.m1 = lambda a:10
+
+ self.assertEqual(F().m1(), None)
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertEqual(F().m1(), 10)
+
+
+
+ def test_if_code_obj_equals(self):
+ class F:
+ def m1(self):
+ return 1
+ class G:
+ def m1(self):
+ return 1
+ class H:
+ def m1(self):
+ return 2
+
+ if hasattr(F.m1, 'func_code'):
+ self.assertTrue(pydevd_reload.code_objects_equal(F.m1.func_code, G.m1.func_code))
+ self.assertFalse(pydevd_reload.code_objects_equal(F.m1.func_code, H.m1.func_code))
+ else:
+ self.assertTrue(pydevd_reload.code_objects_equal(F.m1.__code__, G.m1.__code__))
+ self.assertFalse(pydevd_reload.code_objects_equal(F.m1.__code__, H.m1.__code__))
+
+
+
+ def test_metaclass(self):
+
+ class Meta(type):
+ def __init__(cls, name, bases, attrs):
+ super(Meta, cls).__init__(name, bases, attrs)
+
+ class F:
+ __metaclass__ = Meta
+
+ def m1(self):
+ return 1
+
+
+ class G:
+ __metaclass__ = Meta
+
+ def m1(self):
+ return 2
+
+ self.assertEqual(F().m1(), 1)
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertEqual(F().m1(), 2)
+
+
+
+ def test_change_hierarchy(self):
+
+ class F(object):
+
+ def m1(self):
+ return 1
+
+
+ class B(object):
+ def super_call(self):
+ return 2
+
+ class G(B):
+
+ def m1(self):
+ return self.super_call()
+
+ self.assertEqual(F().m1(), 1)
+ old = pydevd_reload.notify_error
+ self._called = False
+ def on_error(*args):
+ self._called = True
+ try:
+ pydevd_reload.notify_error = on_error
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertTrue(self._called)
+ finally:
+ pydevd_reload.notify_error = old
+
+
+ def test_change_hierarchy_old_style(self):
+
+ class F:
+
+ def m1(self):
+ return 1
+
+
+ class B:
+ def super_call(self):
+ return 2
+
+ class G(B):
+
+ def m1(self):
+ return self.super_call()
+
+
+ self.assertEqual(F().m1(), 1)
+ old = pydevd_reload.notify_error
+ self._called = False
+ def on_error(*args):
+ self._called = True
+ try:
+ pydevd_reload.notify_error = on_error
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertTrue(self._called)
+ finally:
+ pydevd_reload.notify_error = old
+
+
+ def test_create_class(self):
+ SAMPLE_CODE1 = """
+class C:
+ def foo(self):
+ return 0
+"""
+ # Creating a new class and using it from old class
+ SAMPLE_CODE2 = """
+class B:
+ pass
+
+class C:
+ def foo(self):
+ return B
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.C().foo
+ self.assertEqual(foo(), 0)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo().__name__, 'B')
+
+ def test_create_class2(self):
+ SAMPLE_CODE1 = """
+class C(object):
+ def foo(self):
+ return 0
+"""
+ # Creating a new class and using it from old class
+ SAMPLE_CODE2 = """
+class B(object):
+ pass
+
+class C(object):
+ def foo(self):
+ return B
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.C().foo
+ self.assertEqual(foo(), 0)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo().__name__, 'B')
+
+ def test_parent_function(self):
+ SAMPLE_CODE1 = """
+class B(object):
+ def foo(self):
+ return 0
+
+class C(B):
+ def call(self):
+ return self.foo()
+"""
+ # Creating a new class and using it from old class
+ SAMPLE_CODE2 = """
+class B(object):
+ def foo(self):
+ return 0
+ def bar(self):
+ return 'bar'
+
+class C(B):
+ def call(self):
+ return self.bar()
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ call = x.C().call
+ self.assertEqual(call(), 0)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(call(), 'bar')
+
+
+ def test_update_constant(self):
+ SAMPLE_CODE1 = """
+CONSTANT = 1
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+ SAMPLE_CODE2 = """
+CONSTANT = 2
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 1) #Just making it explicit we don't reload constants.
+
+
+ def test_update_constant_with_custom_code(self):
+ SAMPLE_CODE1 = """
+CONSTANT = 1
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+ SAMPLE_CODE2 = """
+CONSTANT = 2
+
+def __xreload_old_new__(namespace, name, old, new):
+ if name == 'CONSTANT':
+ namespace[name] = new
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 2) #Actually updated it now!
+
+
+ def test_reload_custom_code_after_changes(self):
+ SAMPLE_CODE1 = """
+CONSTANT = 1
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+ SAMPLE_CODE2 = """
+CONSTANT = 1
+
+def __xreload_after_reload_update__(namespace):
+ namespace['CONSTANT'] = 2
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 2) #Actually updated it now!
+
+
+ def test_reload_custom_code_after_changes_in_class(self):
+ SAMPLE_CODE1 = """
+
+class B(object):
+ CONSTANT = 1
+
+ def foo(self):
+ return self.CONSTANT
+"""
+ SAMPLE_CODE2 = """
+
+
+class B(object):
+ CONSTANT = 1
+
+ @classmethod
+ def __xreload_after_reload_update__(cls):
+ cls.CONSTANT = 2
+
+ def foo(self):
+ return self.CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 2) #Actually updated it now!
+
+
+ def test_update_constant_with_custom_code(self):
+ SAMPLE_CODE1 = """
+
+class B(object):
+ CONSTANT = 1
+
+ def foo(self):
+ return self.CONSTANT
+"""
+ SAMPLE_CODE2 = """
+
+
+class B(object):
+
+ CONSTANT = 2
+
+ def __xreload_old_new__(cls, name, old, new):
+ if name == 'CONSTANT':
+ cls.CONSTANT = new
+ __xreload_old_new__ = classmethod(__xreload_old_new__)
+
+ def foo(self):
+ return self.CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 2) #Actually updated it now!
+
+
+ def test_update_with_slots(self):
+ SAMPLE_CODE1 = """
+class B(object):
+
+ __slots__ = ['bar']
+
+"""
+ SAMPLE_CODE2 = """
+class B(object):
+
+ __slots__ = ['bar', 'foo']
+
+ def m1(self):
+ self.bar = 10
+ return 1
+
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ B = x.B
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ b = B()
+ self.assertEqual(1, b.m1())
+ self.assertEqual(10, b.bar)
+ self.assertRaises(Exception, setattr, b, 'foo', 20) #__slots__ can't be updated
+
+
+
+
+if __name__ == "__main__":
+# import sys;sys.argv = ['', 'Test.test_reload_custom_code_after_changes_in_class']
+ unittest.main()