Anyone who's used reload() on a module that defines a class in the interactive interpreter must have experienced the frustration of then running around and making sure that all instances are updated to be instances of the new rather than the old class.
This metaclass tries to help with this.
Python, 69 lines
The problem this code is meant to help with is hopefully familiar.
You're editing a Python module in emacs (or vim or notepad or whatever). Let's say at some point it looks like this: <pre> -------- # mod.py -------- class Foo(object): def meth1(self, arg):
</pre> In another window, you have an interactive interpreter running to test your code: <pre>
</pre> Head back to the test session: <pre>
There are two things you can do about this: 1) regenerate the instance: <pre>
The first class is a metaclass that tracks instances of its instances (I hope you have your brain-splatter protection set up).
As metaclasses go, this isn't too complicated. New classes of this metatype get an extra __instance_refs__ class variable (used to store weak references to instances) and an __instances__ method (which strips dead references out of the __instance_refs__ list and returns real references to the still live instances). When a class of metatype MetaInstanceTracker is instantiated, a weak reference to the instances is stored in the __instance_refs__ list.
When the definition of a class of metatype MetaAutoReloader is executed, the namespace of the definition is examined to see if a class of the same name already exists. If it does, then it is assumed that instead of a class defintion, this is a class REdefinition, and all instances of the OLD class (MetaAutoReloader inherits from MetaInstanceTracker, so they can easily be found) are updated to the NEW class.
There should be more error checking (e.g. that old_class is an InstanceTracker, change_class can fail). This was omitted through a mixture of a desire for clarity and laziness.