Skip to content

Instantly share code, notes, and snippets.

@lostsnow
Created October 14, 2021 11:16
Show Gist options
  • Save lostsnow/d0fc7d4bc5157e98f27d7d8d33565c15 to your computer and use it in GitHub Desktop.
Save lostsnow/d0fc7d4bc5157e98f27d7d8d33565c15 to your computer and use it in GitHub Desktop.
import types
def both_instance_of(first, second, klass):
return isinstance(first, klass) and isinstance(second, klass)
def update_function(old_func, new_func):
if not both_instance_of(old_func, new_func, types.FunctionType):
return
if len(old_func.__code__.co_freevars) != len(new_func.__code__.co_freevars):
return
old_func.__code__ = new_func.__code__
old_func.__defaults__ = new_func.__defaults__
old_func.__doc__ = new_func.__doc__
old_func.__dict__ = new_func.__dict__
if not old_func.__closure__ or not new_func.__closure__:
return
for old_cell, new_cell in zip(old_func.__closure__, new_func.__closure__):
if not both_instance_of(old_cell.cell_contents, new_cell.cell_contents, types.FunctionType):
continue
update_function(old_cell.cell_contents, new_cell.cell_contents)
def update_class(old_class, new_class):
for name, new_attr in new_class.__dict__.items():
if name not in old_class.__dict__:
setattr(old_class, name, new_attr)
else:
old_attr = old_class.__dict__[name]
if both_instance_of(old_attr, new_attr, types.FunctionType):
update_function(old_attr, new_attr)
elif both_instance_of(old_attr, new_attr, staticmethod):
update_function(old_attr.__func__, new_attr.__func__)
elif both_instance_of(old_attr, new_attr, classmethod):
update_function(old_attr.__func__, new_attr.__func__)
elif both_instance_of(old_attr, new_attr, property):
update_function(old_attr.fdel, new_attr.fdel)
update_function(old_attr.fget, new_attr.fget)
update_function(old_attr.fset, new_attr.fset)
elif both_instance_of(old_attr, new_attr, type):
update_class(old_attr, new_attr)
def update_module(old_module, new_module):
for name, new_val in new_module.__dict__.items():
if name not in old_module.__dict__:
setattr(old_module, name, new_val)
else:
old_val = old_module.__dict__[name]
if both_instance_of(old_val, new_val, types.FunctionType):
update_function(old_val, new_val)
elif both_instance_of(old_val, new_val, type):
update_class(old_val, new_val)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment