summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2007-02-25 21:22:21 (GMT)
committerGuido van Rossum <guido@python.org>2007-02-25 21:22:21 (GMT)
commit5c0a6de79acfa39cc5e5b522d638c65dc1347030 (patch)
treef17367d4a3665787e8014aa2ce695cc0fc9eb579
parent55b4a4a1a97ed880bbc1e12cbc8975fe9f84e32e (diff)
downloadcpython-5c0a6de79acfa39cc5e5b522d638c65dc1347030.zip
cpython-5c0a6de79acfa39cc5e5b522d638c65dc1347030.tar.gz
cpython-5c0a6de79acfa39cc5e5b522d638c65dc1347030.tar.bz2
Use Glyph's trick to ensure that __globals__ is set properly.
-rw-r--r--Lib/xreload.py28
1 files changed, 14 insertions, 14 deletions
diff --git a/Lib/xreload.py b/Lib/xreload.py
index 0730be5..921d87e 100644
--- a/Lib/xreload.py
+++ b/Lib/xreload.py
@@ -55,22 +55,22 @@ def xreload(mod):
finally:
if stream:
stream.close()
- # Execute the code in a temporary namespace; if this fails, no changes
- tmpns = {}
- exec(code, tmpns)
+ # Execute the code. We copy the module dict to a temporary; then
+ # clear the module dict; then execute the new code in the module
+ # dict; then swap things back and around. This trick (due to
+ # Glyph Lefkowitz) ensures that the (readonly) __globals__
+ # attribute of methods and functions is set to the correct dict
+ # object.
+ tmpns = modns.copy()
+ modns.clear()
+ modns["__name__"] = tmpns["__name__"]
+ exec(code, modns)
# Now we get to the hard part
- oldnames = set(modns)
- newnames = set(tmpns)
- # Add newly introduced names
- for name in newnames - oldnames:
- modns[name] = tmpns[name]
- # Delete names that are no longer current
- # XXX What to do about renamed objects?
- for name in oldnames - newnames - {"__name__"}:
- del modns[name]
- # Now update the rest in place
+ oldnames = set(tmpns)
+ newnames = set(modns)
+ # Update attributes in place
for name in oldnames & newnames:
- modns[name] = _update(modns[name], tmpns[name])
+ modns[name] = _update(tmpns[name], modns[name])
# Done!
return mod