blob: 062ead2b5ff895f691d591aa7991e7b288ff7117 [file] [log] [blame]
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()