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.