summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/xreload.py39
1 files changed, 36 insertions, 3 deletions
diff --git a/Lib/xreload.py b/Lib/xreload.py
index 360dc67..8d2dfc0 100644
--- a/Lib/xreload.py
+++ b/Lib/xreload.py
@@ -65,6 +65,7 @@ def xreload(mod):
for name in newnames - oldnames:
modns[name] = tmpns[name]
# Delete names that are no longer current
+ # XXX What to do about renamed objects?
for name in oldnames - newnames - {"__name__"}:
del modns[name]
# Now update the rest in place
@@ -86,6 +87,9 @@ def _update(oldobj, newobj):
Returns:
either oldobj, updated in place, or 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
@@ -98,11 +102,18 @@ def _update(oldobj, newobj):
return _update_function(oldobj, newobj)
if isinstance(newobj, types.MethodType):
return _update_method(oldobj, newobj)
- # XXX Support class methods, static methods, other decorators
+ if isinstance(newobj, classmethod):
+ return _update_classmethod(oldobj, newobj)
+ if isinstance(newobj, staticmethod):
+ return _update_staticmethod(oldobj, newobj)
+ # XXX How to support decorators?
# Not something we recognize, just give up
return newobj
+# All of the following functions have the same signature as _update()
+
+
def _update_function(oldfunc, newfunc):
"""Update a function object."""
oldfunc.__doc__ = newfunc.__doc__
@@ -116,7 +127,7 @@ def _update_function(oldfunc, newfunc):
def _update_method(oldmeth, newmeth):
"""Update a method object."""
# XXX What if im_func is not a function?
- _update_function(oldmeth.im_func, newmeth.im_func)
+ _update(oldmeth.im_func, newmeth.im_func)
return oldmeth
@@ -132,5 +143,27 @@ def _update_class(oldclass, newclass):
for name in oldnames - newnames:
delattr(oldclass, name)
for name in oldnames & newnames - {"__dict__", "__doc__"}:
- setattr(oldclass, name, newdict[name])
+ setattr(oldclass, name, _update(olddict[name], newdict[name]))
return oldclass
+
+
+def _update_classmethod(oldcm, newcm):
+ """Update a classmethod update."""
+ # While we can't modify the classmethod object itself (it has no
+ # mutable attributes), we *can* extract the underlying function
+ # (by calling __get__(), which returns a method object) and update
+ # it in-place. We don't have the class available to pass to
+ # __get__() but any object except None will do.
+ _update(oldcm.__get__(0), newcm.__get__(0))
+ return newcm
+
+
+def _update_staticmethod(oldsm, newsm):
+ """Update a staticmethod update."""
+ # While we can't modify the staticmethod object itself (it has no
+ # mutable attributes), we *can* extract the underlying function
+ # (by calling __get__(), which returns it) and update it in-place.
+ # We don't have the class available to pass to __get__() but any
+ # object except None will do.
+ _update(oldsm.__get__(0), newsm.__get__(0))
+ return newsm