My particular problem is Django related, but I rewrote the relevant code to general Python for better understanding.
import pickle
class FieldTracker(object):
def patch_save(self, instance):
original_save = instance.save
def save(**kwargs):
ret = original_save(**kwargs)
# use properties of self, implement new stuff etc
print 'Used patched save'
return ret
instance.save = save
class Model(object):
name_field = 'joe'
field_tracker = FieldTracker()
def __init__(self):
self.field_tracker.patch_save(self)
def save(self):
print 'Used default save'
model = Model()
model.save() # Uses patched version of save
pickle.dumps(model) # Fails
Model is representation of DB row. FieldTracker tracks changes to fields in Model (name_field in this case). FieldTracker needs to patch save method after Model is instantiated. Patched save is closure inside of patch_save as it uses properties from FieldTracker, calls methods from passed instance etc.
FieldTracker cannot be pickled as one if its methods contains closure. From what I tried, save cannot be moved to class level as I get TypeError: can't pickle instancemethod objects. When I tried to move patch_save to top level it produced the same exception as above code (surprise, surprise). Moving save to top level would probably mean usage of global variables, which I want to avoid (but I haven't actually tried it).
And the question is: Is it possible to refactor FieldTracker code to be pickleable or should I use different approach (like move overriden save to model mixin)?
This is real FieldTracker if anyone cares.