Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed reload code to be Python 3 compatible.

  • Loading branch information...
commit c03e6acc0c3857fc525f36d24756fb59ac0ffebf 1 parent 282897b
@fabioz authored
View
15 plugins/org.python.pydev/pysrc/pydevd_custom_frames.py
@@ -84,11 +84,22 @@ def updateCustomFrame(frame_id, frame, thread_id, name=None):
CustomFramesContainer.custom_frames_lock.release()
-def getCustomFrame(frame_id):
+def getCustomFrame(thread_id, frame_id):
+ '''
+ :param thread_id: This should actually be the frame_id which is returned by addCustomFrame.
+ :param frame_id: This is the actual id() of the frame
+ '''
+
CustomFramesContainer.custom_frames_lock.acquire()
try:
- return CustomFramesContainer.custom_frames[frame_id].frame
+ frame_id = int(frame_id)
+ f = CustomFramesContainer.custom_frames[thread_id].frame
+ while f is not None:
+ if id(f) == frame_id:
+ return f
+ f = f.f_back
finally:
+ f = None
CustomFramesContainer.custom_frames_lock.release()
View
97 plugins/org.python.pydev/pysrc/pydevd_reload.py
@@ -71,7 +71,7 @@
class Helper:
DEBUG = NO_DEBUG
-
+
def write(*args):
new_lst = []
for a in args:
@@ -80,12 +80,12 @@ def write(*args):
msg = ' '.join(new_lst)
sys.stdout.write('%s\n' % (msg,))
write = staticmethod(write)
-
+
def info(*args):
if Helper.DEBUG >= LEVEL1:
Helper.write(*args)
info = staticmethod(info)
-
+
def info2(*args):
if Helper.DEBUG >= LEVEL2:
Helper.write(*args)
@@ -117,16 +117,16 @@ def xreload(mod):
r.apply()
r = None
pydevd_dont_trace.clear_trace_filter_cache()
-
-
+
+
#=======================================================================================================================
# Reload
#=======================================================================================================================
class Reload:
-
+
def __init__(self, mod):
self.mod = mod
-
+
def apply(self):
mod = self.mod
self._on_finish_callbacks = []
@@ -181,16 +181,16 @@ def apply(self):
# Now we get to the hard part
oldnames = set(modns)
newnames = set(new_namespace)
-
+
# Update in-place what we can
for name in oldnames & newnames:
self._update(modns[name], new_namespace[name])
-
+
# Create new tokens (note: not deleting existing)
for name in newnames - oldnames:
Helper.info('Created:', new_namespace[name])
modns[name] = new_namespace[name]
-
+
for c in self._on_finish_callbacks:
c()
del self._on_finish_callbacks[:]
@@ -200,9 +200,9 @@ def apply(self):
def _update(self, oldobj, newobj):
"""Update oldobj, if possible in place, with newobj.
-
+
If oldobj is immutable, this simply returns newobj.
-
+
Args:
oldobj: the object to be updated
newobj: the object used as the source for the update
@@ -211,104 +211,107 @@ def _update(self, oldobj, newobj):
if oldobj is newobj:
# Probably something imported
return newobj
-
+
if type(oldobj) is not type(newobj):
# Cop-out: if the type changed, give up
return newobj
-
+
if hasattr(newobj, "__reload_update__"):
# Provide a hook for updating
return newobj.__reload_update__(oldobj)
-
+
if hasattr(types, 'ClassType'):
classtype = types.ClassType
else:
classtype = type
-
+
if isinstance(newobj, classtype):
return self._update_class(oldobj, newobj)
-
+
if isinstance(newobj, types.FunctionType):
return self._update_function(oldobj, newobj)
-
+
if isinstance(newobj, types.MethodType):
return self._update_method(oldobj, newobj)
-
+
if isinstance(newobj, classmethod):
return self._update_classmethod(oldobj, newobj)
-
+
if isinstance(newobj, staticmethod):
return self._update_staticmethod(oldobj, newobj)
-
- #New: dealing with metaclasses.
+
+ # New: dealing with metaclasses.
if hasattr(newobj, '__metaclass__') and hasattr(newobj, '__class__') and newobj.__metaclass__ == newobj.__class__:
return self._update_class(oldobj, newobj)
-
+
# Not something we recognize, just give up
return newobj
-
-
+
+
# All of the following functions have the same signature as _update()
-
-
+
+
def _update_function(self, oldfunc, newfunc):
"""Update a function object."""
oldfunc.__doc__ = newfunc.__doc__
oldfunc.__dict__.update(newfunc.__dict__)
-
+
try:
newfunc.__code__
attr_name = '__code__'
except AttributeError:
newfunc.func_code
attr_name = 'func_code'
-
+
old_code = getattr(oldfunc, attr_name)
new_code = getattr(newfunc, attr_name)
if not code_objects_equal(old_code, new_code):
Helper.info('Update function:', oldfunc)
setattr(oldfunc, attr_name, new_code)
-
+
try:
oldfunc.__defaults__ = newfunc.__defaults__
except AttributeError:
oldfunc.func_defaults = newfunc.func_defaults
-
+
return oldfunc
-
-
+
+
def _update_method(self, oldmeth, newmeth):
"""Update a method object."""
# XXX What if im_func is not a function?
- self._update(oldmeth.im_func, newmeth.im_func)
+ if hasattr(oldmeth, 'im_func') and hasattr(newmeth, 'im_func'):
+ self._update(oldmeth.im_func, newmeth.im_func)
+ elif hasattr(oldmeth, '__func__') and hasattr(newmeth, '__func__'):
+ self._update(oldmeth.__func__, newmeth.__func__)
return oldmeth
-
-
+
+
def _update_class(self, oldclass, newclass):
"""Update a class object."""
olddict = oldclass.__dict__
newdict = newclass.__dict__
-
+
oldnames = set(olddict)
newnames = set(newdict)
-
+
for name in newnames - oldnames:
Helper.info('Created:', newdict[name], 'in', oldclass)
setattr(oldclass, name, newdict[name])
-
- #Note: not removing old things...
- #for name in oldnames - newnames:
+
+ # Note: not removing old things...
+ # for name in oldnames - newnames:
# Helper.info('Removed:', name, 'from', oldclass)
# delattr(oldclass, name)
-
+
for name in oldnames & newnames - set(['__dict__', '__doc__']):
self._update(olddict[name], newdict[name])
-
+
if hasattr(oldclass, "__after_reload_update__"):
# If a client wants to know about it, give him a chance.
self._on_finish_callbacks.append(oldclass.__after_reload_update__)
-
-
+
+
def _update_classmethod(self, oldcm, newcm):
"""Update a classmethod update."""
# While we can't modify the classmethod object itself (it has no
@@ -317,8 +320,8 @@ def _update_classmethod(self, oldcm, newcm):
# it in-place. We don't have the class available to pass to
# __get__() but any object except None will do.
self._update(oldcm.__get__(0), newcm.__get__(0))
-
-
+
+
def _update_staticmethod(self, oldsm, newsm):
"""Update a staticmethod update."""
# While we can't modify the staticmethod object itself (it has no
View
2  plugins/org.python.pydev/pysrc/pydevd_vars.py
@@ -283,7 +283,7 @@ def findFrame(thread_id, frame_id):
curr_thread_id = GetThreadId(threading.currentThread())
if thread_id != curr_thread_id :
try:
- return getCustomFrame(thread_id) #I.e.: thread_id could be a stackless frame id + thread_id.
+ return getCustomFrame(thread_id, frame_id) #I.e.: thread_id could be a stackless frame id + thread_id.
except:
pass
View
53 plugins/org.python.pydev/pysrc/test_pydevd_reload/test_pydevd_reload.py
@@ -94,7 +94,7 @@ def check(expected):
check(0)
- #modify mod and reload
+ # modify mod and reload
count = 0
while count < 1:
count += 1
@@ -131,6 +131,19 @@ def m1(self):
self.assertEqual(F().m1(), 2)
+ def testPydevdReload4(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(F, G)
+ self.assertEqual(F().m1(), 10)
+
+
def testIfCodeObjEquals(self):
class F:
@@ -143,46 +156,50 @@ class H:
def m1(self):
return 2
- 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))
+ 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 testMetaclass(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(F, G)
self.assertEqual(F().m1(), 2)
-
-
+
+
def testCreateClass(self):
SAMPLE_CODE1 = """
class C:
def foo(self):
return 0
"""
- #Creating a new class and using it from old class
+ # Creating a new class and using it from old class
SAMPLE_CODE2 = """
class B:
pass
-
+
class C:
def foo(self):
return B
@@ -195,10 +212,10 @@ def foo(self):
self.make_mod(sample=SAMPLE_CODE2)
pydevd_reload.xreload(x)
self.assertEqual(foo().__name__, 'B')
-
-
+
+
if __name__ == "__main__":
- #import sys;sys.argv = ['', 'Test.testPydevdReload']
- unittest.main()
+ # import sys;sys.argv = ['', 'Test.testPydevdReload']
+ unittest.main()
View
119 plugins/org.python.pydev/pysrc/tests_runfiles/test_pydevd_reload.py
@@ -1,119 +0,0 @@
-'''
-Changed the doctest frome the xreload to actual unittest.
-'''
-
-import sys
-import os.path
-
-import sys
-IS_JYTHON = sys.platform.find('java') != -1
-
-sys.path.append(os.path.split(os.path.split(__file__)[0])[0])
-
-if sys.version_info[0] == 2 and sys.version_info[1] <= 4:
- SAMPLE_CODE = """
-class C:
- attr = 42
- def foo(self):
- return 42
-
- def bar(cls):
- return 42, 42
-
- def stomp():
- return 42, 42, 42
-"""
-else:
- SAMPLE_CODE = """
-class C:
- attr = 42
- def foo(self):
- return 42
- @classmethod
- def bar(cls):
- return 42, 42
- @staticmethod
- def stomp():
- return 42, 42, 42
-"""
-
-import shutil
-from pydevd_reload import xreload
-import tempfile
-
-tempdir = None
-save_path = None
-import unittest
-
-class Test(unittest.TestCase):
-
-
- def setUp(self, nused=None):
- global tempdir, save_path
- tempdir = tempfile.mktemp()
- print(tempdir)
- os.makedirs(tempdir)
- save_path = list(sys.path)
- sys.path.append(tempdir)
-
-
- def tearDown(self, unused=None):
- global tempdir, save_path
- if save_path is not None:
- sys.path = save_path
- save_path = None
- if tempdir is not None:
- shutil.rmtree(tempdir)
- tempdir = None
-
-
- def make_mod(self, name="x", repl=None, subst=None):
- assert tempdir
- fn = os.path.join(tempdir, name + ".py")
- f = open(fn, "w")
- sample = SAMPLE_CODE
- if repl is not None and subst is not None:
- sample = sample.replace(repl, subst)
- try:
- f.write(sample)
- finally:
- f.close()
-
-
- def testMet1(self):
- self.make_mod()
- import x #@UnresolvedImport -- this is the module we created at runtime.
- from x import C as Foo #@UnresolvedImport
- C = x.C
- Cfoo = C.foo
- Cbar = C.bar
- Cstomp = C.stomp
- b = C()
- bfoo = b.foo
- in_list = [C]
- self.assertEqual(b.foo(), 42)
- self.assertEqual(bfoo(), 42)
- self.assertEqual(Cfoo(b), 42)
- self.assertEqual(Cbar(), (42, 42))
- self.assertEqual(Cstomp(), (42, 42, 42))
- self.assertEqual(in_list[0].attr, 42)
- self.assertEqual(Foo.attr, 42)
- self.make_mod(repl="42", subst="24")
- xreload(x)
- self.assertEqual(b.foo(), 24)
- self.assertEqual(bfoo(), 24)
- self.assertEqual(Cfoo(b), 24)
- self.assertEqual(Cbar(), (24, 24))
- self.assertEqual(Cstomp(), (24, 24, 24))
- self.assertEqual(in_list[0].attr, 24)
- self.assertEqual(Foo.attr, 24)
-
-
-#=======================================================================================================================
-# main
-#=======================================================================================================================
-if __name__ == '__main__':
- #this is so that we can run it frem the jython tests -- because we don't actually have an __main__ module
- #(so, it won't try importing the __main__ module)
- if not IS_JYTHON: #Doesn't really work in Jython
- unittest.TextTestRunner().run(unittest.makeSuite(Test))
Please sign in to comment.
Something went wrong with that request. Please try again.