Created
October 14, 2021 11:16
-
-
Save lostsnow/d0fc7d4bc5157e98f27d7d8d33565c15 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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