On 09/26/2014 11:15 AM, Nathaniel Smith wrote:
Option 1: allocate a new object, shallowly copy over all the old object properties into the new one, and then find all references to the old object and replace them with the new object. This is possible right now, but error prone: cloning a module object requires intimate knowledge of which fields exist, and swapping all the references requires that we be careful to perform the swap very early, when the only reference is the one in sys.modules.
Option 2: the __class__ switcheroo. This avoids the two issues above. In exchange it's fairly brain-hurty.
Option 3: Oh wait, I just thought of a third option. It only works for packages, but that's okay, you can always convert a module into a package by a simple mechanical transformation. The proposal is that before exec'ing __init__.py, we check for the existence of a __preinit__.py, and if found we do something like
sys.modules[package] = sentinel to block circular imports namespace = {} exec __preinit__.py in namespace cls = namespace.get("__metamodule___", ModuleType) mod = cls(name, doc, namespace) sys.modules[package] = mod exec __init__.py in namespace
So preinit runs in the same namespace as init, but with a special restriction that if it tries to (directly or indirectly) import the current package, then this will trigger an ImportError. This is somewhat restrictive, but it does allow arbitrary code to be run before the module object is created.
What about Option 4: have reload work with modules converted into classes ? This may mean having some extra fields in the class, and probably some extra code in the module loading, but it might be the simplest approach. -- ~Ethan~