Add support for static and class methods.

This commit is contained in:
Guido van Rossum 2007-02-25 16:19:20 +00:00
parent 88470ec348
commit 9a7e77401b
1 changed files with 36 additions and 3 deletions

View File

@ -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