Jim Fulton wrote:
I also think there is a real opportunity in allowing reload to fail.
That is, it should be possible for reload to visibly fail so the user
knows that they have to restart. Then we only reload when we *know*
we can make changes safely and fail otherwise. For example, in the common
case of updating a class, we can update the class in place. If there
aren't any other changes, then we know the reload is safe.
That's insightful. Zope 2's refresh really should refuse to reload
sometimes. Right now it just trusts whoever wrote the "refresh.txt" file.
Here's an idea: When we do a new-improved reload, we:
1. Reevaluate the code in the pyc, getting the original dictionary.
2. Recompile and evaluate the code without writing a new pyc.
Reloadable modules better not cause side effects at import time!
3. Compare the old and new dictionaries to find changes. If we
don't know how to compare 2 items, we assume a change. Note
removing a variable is considered an unsafe change. Adding a
variable is assumed to be a safe change as long as a variable of
the same name hasn't been added to the module dynamically.
4. We consider whether each of the changes is safe. If any change
is unsafe, we raise and error, aborting the reload. A change is
safe if the original and new variables are of the same type, the
values are mutable and if we know how to update the old value
based on the new value. In addition, for a change to be safe,
the original value and the value currently in the module must be
the same and have the same value. That is, it can't have been
changed dynamically.
It sounds like populating of any sort of registry in a module would
prevent the module from being reloaded. Take this for example:
# module "mimestuff.py"
content_types = {}
def add_content_type(name, extension):
content_types[name] = extension
As soon as anyone calls add_content_type(), including the module itself,
the state of the content_type dict changes from the original value.
That's fine by me if that's what you intended. Reloading modules
containing registries never seemed like a good idea to me anyway.
5. We apply the changes and write a new pyc.
The server might not have write access to its code directory. Maybe we
can't reload if the server can't write the .pyc, since writing the .pyc
is required to perform further reloads.
This boils down to merging differences at the Python level.
We fail if we don't know how to apply the diff. At that point,
the user knows they need to restart to get the change.
Hm. This feels kind of workable. It might even make a good PEP
for a "safe reload".
It's certainly an improvement. It's still possible for other modules to
retain state based on a reloadable module's old state. Should we worry
about that? Is it something that programmers understand intuitively
enough that when they run into it, they won't be baffled?
Shane
_______________________________________________
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com