Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 437 lines (322 sloc) 15.225 kB
cb48c22 @fabioz Fixing line endings.
authored
1 """
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
2 Based on the python xreload.
3
17803f0 @fabioz Docs
authored
4 Changes
5 ======================
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
6
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
7 1. we don't recreate the old namespace from new classes. Rather, we keep the existing namespace,
8 load a new version of it and update only some of the things we can inplace. That way, we don't break
9 things such as singletons or end up with a second representation of the same class in memory.
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
10
11 2. If we find it to be a __metaclass__, we try to update it as a regular class.
12
13 3. We don't remove old attributes (and leave them lying around even if they're no longer used).
14
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
15 4. Reload hooks were changed
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
16
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
17 These changes make it more stable, especially in the common case (where in a debug session only the
17803f0 @fabioz Docs
authored
18 contents of a function are changed), besides providing flexibility for users that want to extend
19 on it.
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
20
21
17803f0 @fabioz Docs
authored
22
23 Hooks
24 ======================
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
25
26 Classes/modules can be specially crafted to work with the reload (so that it can, for instance,
27 update some constant which was changed).
28
17803f0 @fabioz Docs
authored
29
30 1. To participate in the change of some attribute:
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
31
32 In a module:
33
34 __xreload_old_new__(namespace, name, old, new)
35
36 in a class:
37
38 @classmethod
39 __xreload_old_new__(cls, name, old, new)
40
41 A class or module may include a method called '__xreload_old_new__' which is called when we're
42 unable to reload a given attribute.
43
44
45
17803f0 @fabioz Docs
authored
46 2. To do something after the whole reload is finished:
47
48 In a module:
49
50 __xreload_after_reload_update__(namespace):
51
52 In a class:
53
54 @classmethod
55 __xreload_after_reload_update__(cls):
56
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
57
58 A class or module may include a method called '__xreload_after_reload_update__' which is called
59 after the reload finishes.
60
7eb4070 @fabioz Improving reload code a bit to deal with Kivy Widget based classes (i…
authored
61
17803f0 @fabioz Docs
authored
62 Current limitations
63 ======================
7eb4070 @fabioz Improving reload code a bit to deal with Kivy Widget based classes (i…
authored
64
65
17803f0 @fabioz Docs
authored
66 - Attributes/constants are added, but not changed (so singletons and the application state is not
67 broken -- use provided hooks to workaround it).
68
69 - Code using metaclasses may not always work.
70
71 - Functions and methods using decorators (other than classmethod and staticmethod) are not handled
72 correctly.
73
74 - Renamings are not handled correctly.
cb48c22 @fabioz Fixing line endings.
authored
75
17803f0 @fabioz Docs
authored
76 - Dependent modules are not reloaded.
cb48c22 @fabioz Fixing line endings.
authored
77
17803f0 @fabioz Docs
authored
78 - New __slots__ can't be added to existing classes.
cb48c22 @fabioz Fixing line endings.
authored
79
80
17803f0 @fabioz Docs
authored
81 Info
82 ======================
cb48c22 @fabioz Fixing line endings.
authored
83
17803f0 @fabioz Docs
authored
84 Original: http://svn.python.org/projects/sandbox/trunk/xreload/xreload.py
85 Note: it seems https://github.com/plone/plone.reload/blob/master/plone/reload/xreload.py enhances it (to check later)
cb48c22 @fabioz Fixing line endings.
authored
86
17803f0 @fabioz Docs
authored
87 Interesting alternative: https://code.google.com/p/reimport/
88
89 Alternative to reload().
cb48c22 @fabioz Fixing line endings.
authored
90
17803f0 @fabioz Docs
authored
91 This works by executing the module in a scratch namespace, and then patching classes, methods and
92 functions in place. This avoids the need to patch instances. New objects are copied into the
93 target namespace.
cb48c22 @fabioz Fixing line endings.
authored
94
95 """
96
97 import imp
cbefd1a @fabioz Live coding on debugger.
authored
98 from pydev_imports import Exec
54138d5 @fabioz Added a way to skip functions with #@DontTrace. For now must be enabl…
authored
99 import pydevd_dont_trace
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
100 import sys
101 import traceback
102 import types
7eb4070 @fabioz Improving reload code a bit to deal with Kivy Widget based classes (i…
authored
103
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
104 NO_DEBUG = 0
105 LEVEL1 = 1
106 LEVEL2 = 2
7eb4070 @fabioz Improving reload code a bit to deal with Kivy Widget based classes (i…
authored
107
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
108 DEBUG = NO_DEBUG
109
110 def write(*args):
111 new_lst = []
112 for a in args:
113 new_lst.append(str(a))
114
115 msg = ' '.join(new_lst)
116 sys.stdout.write('%s\n' % (msg,))
117
118 def write_err(*args):
119 new_lst = []
120 for a in args:
121 new_lst.append(str(a))
7eb4070 @fabioz Improving reload code a bit to deal with Kivy Widget based classes (i…
authored
122
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
123 msg = ' '.join(new_lst)
124 sys.stderr.write('pydev debugger: %s\n' % (msg,))
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
125
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
126 def notify_info0(*args):
127 write_err(*args)
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
128
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
129 def notify_info(*args):
130 if DEBUG >= LEVEL1:
131 write(*args)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
132
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
133 def notify_info2(*args):
134 if DEBUG >= LEVEL2:
135 write(*args)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
136
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
137 def notify_error(*args):
138 write_err(*args)
7eb4070 @fabioz Improving reload code a bit to deal with Kivy Widget based classes (i…
authored
139
140
141
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
142 #=======================================================================================================================
143 # code_objects_equal
144 #=======================================================================================================================
7eb4070 @fabioz Improving reload code a bit to deal with Kivy Widget based classes (i…
authored
145 def code_objects_equal(code0, code1):
146 for d in dir(code0):
147 if d.startswith('_') or 'lineno' in d:
148 continue
149 if getattr(code0, d) != getattr(code1, d):
150 return False
151 return True
cb48c22 @fabioz Fixing line endings.
authored
152
153
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
154 #=======================================================================================================================
155 # xreload
156 #=======================================================================================================================
cb48c22 @fabioz Fixing line endings.
authored
157 def xreload(mod):
158 """Reload a module in place, updating classes, methods and functions.
159
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
160 mod: a module object
cb48c22 @fabioz Fixing line endings.
authored
161 """
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
162 r = Reload(mod)
163 r.apply()
164 r = None
54138d5 @fabioz Added a way to skip functions with #@DontTrace. For now must be enabl…
authored
165 pydevd_dont_trace.clear_trace_filter_cache()
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
166
167
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
168 # This isn't actually used... Initially I planned to reload variables which are immutable on the
169 # namespace, but this can destroy places where we're saving state, which may not be what we want,
170 # so, we're being conservative and giving the user hooks if he wants to do a reload.
171 #
172 # immutable_types = [int, str, float, tuple] #That should be common to all Python versions
173 #
174 # for name in 'long basestr unicode frozenset'.split():
175 # try:
176 # immutable_types.append(__builtins__[name])
177 # except:
178 # pass #Just ignore: not all python versions are created equal.
179 # immutable_types = tuple(immutable_types)
180
181
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
182 #=======================================================================================================================
183 # Reload
184 #=======================================================================================================================
185 class Reload:
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
186
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
187 def __init__(self, mod):
188 self.mod = mod
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
189
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
190 def apply(self):
191 mod = self.mod
192 self._on_finish_callbacks = []
7eb4070 @fabioz Improving reload code a bit to deal with Kivy Widget based classes (i…
authored
193 try:
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
194 # Get the module name, e.g. 'foo.bar.whatever'
195 modname = mod.__name__
196 # Get the module namespace (dict) early; this is part of the type check
197 modns = mod.__dict__
198 # Parse it into package name and module name, e.g. 'foo.bar' and 'whatever'
199 i = modname.rfind(".")
200 if i >= 0:
201 pkgname, modname = modname[:i], modname[i + 1:]
7eb4070 @fabioz Improving reload code a bit to deal with Kivy Widget based classes (i…
authored
202 else:
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
203 pkgname = None
204 # Compute the search path
205 if pkgname:
206 # We're not reloading the package, only the module in it
207 pkg = sys.modules[pkgname]
208 path = pkg.__path__ # Search inside the package
209 else:
210 # Search the top-level module path
211 pkg = None
212 path = None # Make find_module() uses the default search path
213 # Find the module; may raise ImportError
214 (stream, filename, (suffix, mode, kind)) = imp.find_module(modname, path)
215 # Turn it into a code object
216 try:
217 # Is it Python source code or byte code read from a file?
218 if kind not in (imp.PY_COMPILED, imp.PY_SOURCE):
219 # Fall back to built-in reload()
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
220 notify_error('Could not find source to reload (mod: %s)' % (modname,))
221 return
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
222 if kind == imp.PY_SOURCE:
223 source = stream.read()
224 code = compile(source, filename, "exec")
225 else:
226 import marshal
227 code = marshal.load(stream)
228 finally:
229 if stream:
230 stream.close()
231 # Execute the code. We copy the module dict to a temporary; then
232 # clear the module dict; then execute the new code in the module
233 # dict; then swap things back and around. This trick (due to
234 # Glyph Lefkowitz) ensures that the (readonly) __globals__
235 # attribute of methods and functions is set to the correct dict
236 # object.
237 new_namespace = modns.copy()
238 new_namespace.clear()
239 new_namespace["__name__"] = modns["__name__"]
240 Exec(code, new_namespace)
241 # Now we get to the hard part
242 oldnames = set(modns)
243 newnames = set(new_namespace)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
244
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
245 # Create new tokens (note: not deleting existing)
246 for name in newnames - oldnames:
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
247 notify_info0('Added:', name, 'to namespace')
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
248 modns[name] = new_namespace[name]
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
249
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
250 # Update in-place what we can
251 for name in oldnames & newnames:
252 self._update(modns, name, modns[name], new_namespace[name])
253
254 self._handle_namespace(modns)
255
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
256 for c in self._on_finish_callbacks:
257 c()
258 del self._on_finish_callbacks[:]
259 except:
260 traceback.print_exc()
261
262
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
263 def _handle_namespace(self, namespace, is_class_namespace=False):
264 on_finish = None
265 if is_class_namespace:
266 xreload_after_update = getattr(namespace, '__xreload_after_reload_update__', None)
267 if xreload_after_update is not None:
268 on_finish = lambda: xreload_after_update()
269
270 elif '__xreload_after_reload_update__' in namespace:
271 xreload_after_update = namespace['__xreload_after_reload_update__']
272 on_finish = lambda: xreload_after_update(namespace)
273
274
275 if on_finish is not None:
276 # If a client wants to know about it, give him a chance.
277 self._on_finish_callbacks.append(on_finish)
278
279
280
281 def _update(self, namespace, name, oldobj, newobj, is_class_namespace=False):
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
282 """Update oldobj, if possible in place, with newobj.
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
283
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
284 If oldobj is immutable, this simply returns newobj.
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
285
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
286 Args:
287 oldobj: the object to be updated
288 newobj: the object used as the source for the update
289 """
4e1679f @fabioz Improving pydevd_reload.
authored
290 try:
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
291 notify_info2('Updating: ', oldobj)
4e1679f @fabioz Improving pydevd_reload.
authored
292 if oldobj is newobj:
293 # Probably something imported
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
294 return
295
4e1679f @fabioz Improving pydevd_reload.
authored
296 if type(oldobj) is not type(newobj):
297 # Cop-out: if the type changed, give up
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
298 notify_error('Type of: %s changed... Skipping.' % (oldobj,))
299 return
300
4e1679f @fabioz Improving pydevd_reload.
authored
301 if isinstance(newobj, types.FunctionType):
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
302 self._update_function(oldobj, newobj)
303 return
304
4e1679f @fabioz Improving pydevd_reload.
authored
305 if isinstance(newobj, types.MethodType):
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
306 self._update_method(oldobj, newobj)
307 return
308
4e1679f @fabioz Improving pydevd_reload.
authored
309 if isinstance(newobj, classmethod):
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
310 self._update_classmethod(oldobj, newobj)
311 return
312
4e1679f @fabioz Improving pydevd_reload.
authored
313 if isinstance(newobj, staticmethod):
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
314 self._update_staticmethod(oldobj, newobj)
315 return
316
4e1679f @fabioz Improving pydevd_reload.
authored
317 if hasattr(types, 'ClassType'):
318 classtype = (types.ClassType, type) #object is not instance of types.ClassType.
319 else:
320 classtype = type
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
321
4e1679f @fabioz Improving pydevd_reload.
authored
322 if isinstance(newobj, classtype):
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
323 self._update_class(oldobj, newobj)
324 return
325
4e1679f @fabioz Improving pydevd_reload.
authored
326 # New: dealing with metaclasses.
327 if hasattr(newobj, '__metaclass__') and hasattr(newobj, '__class__') and newobj.__metaclass__ == newobj.__class__:
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
328 self._update_class(oldobj, newobj)
329 return
330
331 if namespace is not None:
332
333 if oldobj != newobj and str(oldobj) != str(newobj) and repr(oldobj) != repr(newobj):
334 xreload_old_new = None
335 if is_class_namespace:
336 xreload_old_new = getattr(namespace, '__xreload_old_new__', None)
337 if xreload_old_new is not None:
338 xreload_old_new(name, oldobj, newobj)
339
340 elif '__xreload_old_new__' in namespace:
341 xreload_old_new = namespace['__xreload_old_new__']
342 xreload_old_new(namespace, name, oldobj, newobj)
343
344 else:
345 notify_info0('%s NOT updated. Create __xreload_old_new__(name, old, new) for custom reload' % (name,))
346
4e1679f @fabioz Improving pydevd_reload.
authored
347 except:
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
348 notify_error('Exception found when updating %s. Proceeding for other items.' % (name,))
4e1679f @fabioz Improving pydevd_reload.
authored
349 traceback.print_exc()
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
350
351
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
352 # All of the following functions have the same signature as _update()
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
353
354
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
355 def _update_function(self, oldfunc, newfunc):
356 """Update a function object."""
357 oldfunc.__doc__ = newfunc.__doc__
358 oldfunc.__dict__.update(newfunc.__dict__)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
359
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
360 try:
361 newfunc.__code__
362 attr_name = '__code__'
363 except AttributeError:
364 newfunc.func_code
365 attr_name = 'func_code'
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
366
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
367 old_code = getattr(oldfunc, attr_name)
368 new_code = getattr(newfunc, attr_name)
369 if not code_objects_equal(old_code, new_code):
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
370 notify_info0('Updated function code:', oldfunc)
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
371 setattr(oldfunc, attr_name, new_code)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
372
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
373 try:
374 oldfunc.__defaults__ = newfunc.__defaults__
375 except AttributeError:
376 oldfunc.func_defaults = newfunc.func_defaults
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
377
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
378 return oldfunc
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
379
380
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
381 def _update_method(self, oldmeth, newmeth):
382 """Update a method object."""
383 # XXX What if im_func is not a function?
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
384 if hasattr(oldmeth, 'im_func') and hasattr(newmeth, 'im_func'):
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
385 self._update(None, None, oldmeth.im_func, newmeth.im_func)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
386 elif hasattr(oldmeth, '__func__') and hasattr(newmeth, '__func__'):
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
387 self._update(None, None, oldmeth.__func__, newmeth.__func__)
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
388 return oldmeth
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
389
390
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
391 def _update_class(self, oldclass, newclass):
392 """Update a class object."""
393 olddict = oldclass.__dict__
394 newdict = newclass.__dict__
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
395
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
396 oldnames = set(olddict)
397 newnames = set(newdict)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
398
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
399 for name in newnames - oldnames:
400 setattr(oldclass, name, newdict[name])
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
401 notify_info0('Added:', name, 'to', oldclass)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
402
403 # Note: not removing old things...
404 # for name in oldnames - newnames:
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
405 # notify_info('Removed:', name, 'from', oldclass)
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
406 # delattr(oldclass, name)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
407
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
408 for name in (oldnames & newnames) - set(['__dict__', '__doc__']):
409 self._update(oldclass, name, olddict[name], newdict[name], is_class_namespace=True)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
410
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
411 old_bases = getattr(oldclass, '__bases__', None)
412 new_bases = getattr(newclass, '__bases__', None)
413 if str(old_bases) != str(new_bases):
414 notify_error('Changing the hierarchy of a class is not supported. %s may be inconsistent.' % (oldclass,))
415
416 self._handle_namespace(oldclass, is_class_namespace=True)
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
417
418
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
419 def _update_classmethod(self, oldcm, newcm):
420 """Update a classmethod update."""
421 # While we can't modify the classmethod object itself (it has no
422 # mutable attributes), we *can* extract the underlying function
423 # (by calling __get__(), which returns a method object) and update
424 # it in-place. We don't have the class available to pass to
425 # __get__() but any object except None will do.
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
426 self._update(None, None, oldcm.__get__(0), newcm.__get__(0))
c03e6ac @fabioz Fixed reload code to be Python 3 compatible.
authored
427
428
7b2801b @fabioz Making the reload handle less to be more stable (i.e.: only update wh…
authored
429 def _update_staticmethod(self, oldsm, newsm):
430 """Update a staticmethod update."""
431 # While we can't modify the staticmethod object itself (it has no
432 # mutable attributes), we *can* extract the underlying function
433 # (by calling __get__(), which returns it) and update it in-place.
434 # We don't have the class available to pass to __get__() but any
435 # object except None will do.
39fde65 @fabioz Improving pydevd_reload: more test-cases, hooks for clients, notifies…
authored
436 self._update(None, None, oldsm.__get__(0), newsm.__get__(0))
Something went wrong with that request. Please try again.