[pypy-commit] pypy py3.5: Backed out changeset f80cb4368b95
rlamy
pypy.commits at gmail.com
Sat Oct 21 08:53:57 EDT 2017
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5
Changeset: r92812:142c785bb994
Date: 2017-10-21 13:53 +0100
http://bitbucket.org/pypy/pypy/changeset/142c785bb994/
Log: Backed out changeset f80cb4368b95
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -574,6 +574,10 @@
except ValueError:
pass # ignore "2 is not a valid file descriptor"
+ if we_are_translated():
+ import __pypy__
+ __pypy__.save_module_content_for_future_reload(sys)
+
mainmodule = type(sys)('__main__')
sys.modules['__main__'] = mainmodule
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -515,8 +515,9 @@
# patcher relies on this behaviour.
w_mod2 = Module(self, w_name)
self.setitem(w_modules, w_name, w_mod2)
- w_dict = w_mod.getdict(self) # unlazy
- self.call_method(w_mod2.getdict(self), 'update', w_dict)
+ w_mod.getdict(self) # unlazy w_initialdict
+ self.call_method(w_mod2.getdict(self), 'update',
+ w_mod.w_initialdict)
return w_mod2
self.setitem(w_modules, w_name, w_mod)
w_mod.init(self)
diff --git a/pypy/interpreter/mixedmodule.py b/pypy/interpreter/mixedmodule.py
--- a/pypy/interpreter/mixedmodule.py
+++ b/pypy/interpreter/mixedmodule.py
@@ -10,7 +10,11 @@
class MixedModule(Module):
applevel_name = None
- initialized = False
+
+ # The following attribute is None as long as the module has not been
+ # imported yet, and when it has been, it is mod.__dict__.copy() just
+ # after startup().
+ w_initialdict = None
lazy = False
submodule_name = None
@@ -19,6 +23,7 @@
Module.__init__(self, space, w_name)
init_extra_module_attrs(space, self)
self.lazy = True
+ self.lazy_initial_values_w = {}
self.__class__.buildloaders()
self.loaders = self.loaders.copy() # copy from the class to the inst
self.submodules_w = []
@@ -42,14 +47,27 @@
def init(self, space):
"""This is called each time the module is imported or reloaded
"""
+ if self.w_initialdict is not None:
+ # the module was already imported. Refresh its content with
+ # the saved dict, as done with built-in and extension modules
+ # on CPython.
+ space.call_method(self.w_dict, 'update', self.w_initialdict)
+
for w_submodule in self.submodules_w:
name = space.text0_w(w_submodule.w_name)
space.setitem(self.w_dict, space.newtext(name.split(".")[-1]), w_submodule)
space.getbuiltinmodule(name)
- if not self.initialized:
+ if self.w_initialdict is None:
Module.init(self, space)
- self.initialized = True
+ if not self.lazy and self.w_initialdict is None:
+ self.save_module_content_for_future_reload()
+
+ def save_module_content_for_future_reload(self):
+ # Save the current dictionary in w_initialdict, for future
+ # reloads. This forces the dictionary if needed.
+ w_dict = self.getdict(self.space)
+ self.w_initialdict = self.space.call_method(w_dict, 'copy')
@classmethod
@not_rpython
@@ -78,6 +96,13 @@
return w_value
def setdictvalue(self, space, attr, w_value):
+ if self.lazy and attr not in self.lazy_initial_values_w:
+ # in lazy mode, the first time an attribute changes,
+ # we save away the old (initial) value. This allows
+ # a future getdict() call to build the correct
+ # self.w_initialdict, containing the initial value.
+ w_initial_value = self._load_lazily(space, attr)
+ self.lazy_initial_values_w[attr] = w_initial_value
space.setitem_str(self.w_dict, attr, w_value)
return True
@@ -117,11 +142,23 @@
def _force_lazy_dict_now(self):
# Force the dictionary by calling all lazy loaders now.
+ # This also saves in self.w_initialdict a copy of all the
+ # initial values, including if they have already been
+ # modified by setdictvalue().
space = self.space
for name in self.loaders:
w_value = self.get(name)
space.setitem(self.w_dict, space.new_interned_str(name), w_value)
self.lazy = False
+ self.save_module_content_for_future_reload()
+ for key, w_initial_value in self.lazy_initial_values_w.items():
+ w_key = space.new_interned_str(key)
+ if w_initial_value is not None:
+ space.setitem(self.w_initialdict, w_key, w_initial_value)
+ else:
+ if space.finditem(self.w_initialdict, w_key) is not None:
+ space.delitem(self.w_initialdict, w_key)
+ del self.lazy_initial_values_w
def _cleanup_(self):
self.getdict(self.space)
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -92,6 +92,8 @@
'set_debug' : 'interp_magic.set_debug',
'locals_to_fast' : 'interp_magic.locals_to_fast',
'set_code_callback' : 'interp_magic.set_code_callback',
+ 'save_module_content_for_future_reload':
+ 'interp_magic.save_module_content_for_future_reload',
'decode_long' : 'interp_magic.decode_long',
'_promote' : 'interp_magic._promote',
'normalize_exc' : 'interp_magic.normalize_exc',
@@ -129,7 +131,7 @@
raise
else:
pass # ok fine to ignore in this case
-
+
if self.space.config.translation.jit:
features = detect_cpu.getcpufeatures(model)
self.extra_interpdef('jit_backend_features',
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -145,6 +145,10 @@
assert isinstance(w_frame, PyFrame)
w_frame.locals2fast()
+ at unwrap_spec(w_module=MixedModule)
+def save_module_content_for_future_reload(space, w_module):
+ w_module.save_module_content_for_future_reload()
+
def set_code_callback(space, w_callable):
cache = space.fromcache(CodeHookCache)
if space.is_none(w_callable):
diff --git a/pypy/module/__pypy__/test/test_magic.py b/pypy/module/__pypy__/test/test_magic.py
--- a/pypy/module/__pypy__/test/test_magic.py
+++ b/pypy/module/__pypy__/test/test_magic.py
@@ -2,6 +2,18 @@
class AppTestMagic:
spaceconfig = dict(usemodules=['__pypy__'])
+ def test_save_module_content_for_future_reload(self):
+ import sys, __pypy__, imp
+ d = sys.dont_write_bytecode
+ sys.dont_write_bytecode = "hello world"
+ __pypy__.save_module_content_for_future_reload(sys)
+ sys.dont_write_bytecode = d
+ imp.reload(sys)
+ assert sys.dont_write_bytecode == "hello world"
+ #
+ sys.dont_write_bytecode = d
+ __pypy__.save_module_content_for_future_reload(sys)
+
def test_new_code_hook(self):
# workaround for running on top of old CPython 2.7 versions
def exec_(code, d):
More information about the pypy-commit
mailing list