Created
August 10, 2012 07:01
-
-
Save spin6lock/3312053 to your computer and use it in GitHub Desktop.
python update
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
# -*- coding: utf-8 -*- | |
def update(module_name): | |
import types, gc, re | |
def test_and_process_list(obj, old, new): | |
if not isinstance(obj, list): return | |
# find the references in list | |
refs = [ index for index, item in enumerate(obj) if item is old ] | |
# update the list | |
for index in refs: obj[index] = new | |
def test_and_process_dict(obj, old, new): | |
if not isinstance(obj, dict): return | |
# if the reference is in the key | |
refs = [ key for key,_ in obj.iteritems() if key is old ] | |
for key in refs: | |
obj[new] = obj[key] | |
del obj[key] | |
# if the reference is in the value | |
refs = [ key for key,value in obj.iteritems() if value is old ] | |
for key in refs: obj[key] = new | |
def test_and_process_method(obj, old, new): | |
return | |
# fix-me: method reference have some bug to fix | |
# 2010-03-15 15:27:51 by BlueQ | |
if not isinstance(obj, (types.MethodType, types.UnboundMethodType)): return | |
obj.im_self.__class__ = new | |
func = obj | |
new_func = getattr(obj.im_self, obj.im_func, obj.func_name) | |
objs = gc.get_referrers(func) | |
[ map( lambda fun:fun(obj, func, new_func), | |
[test_and_process_list, | |
test_and_process_dict] | |
) for obj in objs] | |
def test_and_process_object(obj, old, new): | |
if not isclass(old): return | |
if not isinstance(obj, old): return | |
obj.__class__ = new | |
def process_default(obj, old, new): | |
# do nothing | |
pass | |
def update_one_reference((obj, old, new)): | |
# process update by the type of object | |
map( lambda fun: fun(obj, old, new), | |
[test_and_process_dict, | |
test_and_process_list, | |
test_and_process_method, | |
test_and_process_object, | |
process_default]) | |
def update_references((old_value, new_value)): | |
objs = gc.get_referrers(old_value) | |
map( update_one_reference, [(obj, old_value, new_value) for obj in objs] ) | |
def isclass(cls): | |
return isinstance(cls, types.TypeType) | |
# Test the variable, if it need update return True else return False | |
def need_update_variable((key, old_value)): | |
# rules: | |
# 1. internal variables (start with '__' and end with '__') use the OLD value | |
# 2. classes use the NEW value | |
# 3. functions use the NEW value | |
# 4. variables with the name is all upper charaters use the NEW value | |
# 5. other variables use OLD value | |
if re.match(r'__.*__', key): # rule 1 | |
setattr(module, key, old_value) | |
return False | |
if isclass(old_value): # rule 2 | |
print ">>> [U] class: %s"%key | |
return True | |
if callable(old_value): # rule 3 | |
print ">>> [U] function: %s"%key | |
return True | |
if key.isupper(): # rule 4 | |
print ">>> [U] const: %s"%key | |
return True | |
# these variables use the cached value, replace it back | |
setattr(module, key, old_value) # rule 5 | |
return False | |
def update_module(module, update_items): | |
print ">>> [I] the following variables are updated" | |
# find all the variables that need update | |
vars = filter( need_update_variable, update_items.iteritems() ) | |
# update all the reference of each variable | |
map( update_references, [(old_value, getattr(module, key)) for key, old_value in vars] ) | |
gc.disable() | |
try: | |
print "" | |
print ">>> ==============================" | |
print ">>> [I] updating module %s...."%module_name | |
# collect garbage before gc.get_referrers | |
gc.collect() | |
module = __import__(module_name) | |
update_items = dict(module.__dict__) | |
reload(module) | |
update_module(module, update_items) | |
print ">>> [I] update %s success" % module_name | |
print ">>> ==============================" | |
print "" | |
finally: | |
gc.enable() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment