machinery = util.import_importlib('importlib.machinery')
-from test.support import captured_stdout
+from test.support import captured_stdout, import_helper
+import contextlib
import types
import unittest
import warnings
+@contextlib.contextmanager
+def deprecated():
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ yield
+
+
+@contextlib.contextmanager
+def fresh(name, *, oldapi=False):
+ with util.uncache(name):
+ with import_helper.frozen_modules():
+ with captured_stdout() as stdout:
+ if oldapi:
+ with deprecated():
+ yield stdout
+ else:
+ yield stdout
+
+
class ExecModuleTests(abc.LoaderTests):
def exec_module(self, name):
- with util.uncache(name), captured_stdout() as stdout:
- spec = self.machinery.ModuleSpec(
- name, self.machinery.FrozenImporter, origin='frozen',
- is_package=self.machinery.FrozenImporter.is_package(name))
- module = types.ModuleType(name)
- module.__spec__ = spec
- assert not hasattr(module, 'initialized')
+ with import_helper.frozen_modules():
+ is_package = self.machinery.FrozenImporter.is_package(name)
+ spec = self.machinery.ModuleSpec(
+ name,
+ self.machinery.FrozenImporter,
+ origin='frozen',
+ is_package=is_package,
+ )
+ module = types.ModuleType(name)
+ module.__spec__ = spec
+ assert not hasattr(module, 'initialized')
+
+ with fresh(name) as stdout:
self.machinery.FrozenImporter.exec_module(module)
- self.assertTrue(module.initialized)
- self.assertTrue(hasattr(module, '__spec__'))
- self.assertEqual(module.__spec__.origin, 'frozen')
- return module, stdout.getvalue()
+
+ self.assertTrue(module.initialized)
+ self.assertTrue(hasattr(module, '__spec__'))
+ self.assertEqual(module.__spec__.origin, 'frozen')
+ return module, stdout.getvalue()
def test_module(self):
name = '__hello__'
name = '__phello__.spam'
with util.uncache('__phello__'):
module, output = self.exec_module(name)
- check = {'__name__': name}
- for attr, value in check.items():
- attr_value = getattr(module, attr)
- self.assertEqual(attr_value, value,
- 'for {name}.{attr}, {given} != {expected!r}'.format(
- name=name, attr=attr, given=attr_value,
- expected=value))
- self.assertEqual(output, 'Hello world!\n')
+ check = {'__name__': name}
+ for attr, value in check.items():
+ attr_value = getattr(module, attr)
+ self.assertEqual(attr_value, value,
+ 'for {name}.{attr}, {given} != {expected!r}'.format(
+ name=name, attr=attr, given=attr_value,
+ expected=value))
+ self.assertEqual(output, 'Hello world!\n')
def test_module_repr(self):
name = '__hello__'
module, output = self.exec_module(name)
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
+ with deprecated():
repr_str = self.machinery.FrozenImporter.module_repr(module)
self.assertEqual(repr_str,
"<module '__hello__' (frozen)>")
test_state_after_failure = None
def test_unloadable(self):
- assert self.machinery.FrozenImporter.find_spec('_not_real') is None
+ with import_helper.frozen_modules():
+ assert self.machinery.FrozenImporter.find_spec('_not_real') is None
with self.assertRaises(ImportError) as cm:
self.exec_module('_not_real')
self.assertEqual(cm.exception.name, '_not_real')
class LoaderTests(abc.LoaderTests):
+ def load_module(self, name):
+ with fresh(name, oldapi=True) as stdout:
+ module = self.machinery.FrozenImporter.load_module(name)
+ return module, stdout
+
def test_module(self):
- with util.uncache('__hello__'), captured_stdout() as stdout:
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = self.machinery.FrozenImporter.load_module('__hello__')
- check = {'__name__': '__hello__',
- '__package__': '',
- '__loader__': self.machinery.FrozenImporter,
- }
- for attr, value in check.items():
- self.assertEqual(getattr(module, attr), value)
- self.assertEqual(stdout.getvalue(), 'Hello world!\n')
- self.assertFalse(hasattr(module, '__file__'))
+ module, stdout = self.load_module('__hello__')
+ check = {'__name__': '__hello__',
+ '__package__': '',
+ '__loader__': self.machinery.FrozenImporter,
+ }
+ for attr, value in check.items():
+ self.assertEqual(getattr(module, attr), value)
+ self.assertEqual(stdout.getvalue(), 'Hello world!\n')
+ self.assertFalse(hasattr(module, '__file__'))
def test_package(self):
- with util.uncache('__phello__'), captured_stdout() as stdout:
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = self.machinery.FrozenImporter.load_module('__phello__')
- check = {'__name__': '__phello__',
- '__package__': '__phello__',
- '__path__': [],
- '__loader__': self.machinery.FrozenImporter,
- }
- for attr, value in check.items():
- attr_value = getattr(module, attr)
- self.assertEqual(attr_value, value,
- "for __phello__.%s, %r != %r" %
- (attr, attr_value, value))
- self.assertEqual(stdout.getvalue(), 'Hello world!\n')
- self.assertFalse(hasattr(module, '__file__'))
+ module, stdout = self.load_module('__phello__')
+ check = {'__name__': '__phello__',
+ '__package__': '__phello__',
+ '__path__': [],
+ '__loader__': self.machinery.FrozenImporter,
+ }
+ for attr, value in check.items():
+ attr_value = getattr(module, attr)
+ self.assertEqual(attr_value, value,
+ "for __phello__.%s, %r != %r" %
+ (attr, attr_value, value))
+ self.assertEqual(stdout.getvalue(), 'Hello world!\n')
+ self.assertFalse(hasattr(module, '__file__'))
def test_lacking_parent(self):
- with util.uncache('__phello__', '__phello__.spam'), \
- captured_stdout() as stdout:
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = self.machinery.FrozenImporter.load_module('__phello__.spam')
- check = {'__name__': '__phello__.spam',
- '__package__': '__phello__',
- '__loader__': self.machinery.FrozenImporter,
- }
- for attr, value in check.items():
- attr_value = getattr(module, attr)
- self.assertEqual(attr_value, value,
- "for __phello__.spam.%s, %r != %r" %
- (attr, attr_value, value))
- self.assertEqual(stdout.getvalue(), 'Hello world!\n')
- self.assertFalse(hasattr(module, '__file__'))
+ with util.uncache('__phello__'):
+ module, stdout = self.load_module('__phello__.spam')
+ check = {'__name__': '__phello__.spam',
+ '__package__': '__phello__',
+ '__loader__': self.machinery.FrozenImporter,
+ }
+ for attr, value in check.items():
+ attr_value = getattr(module, attr)
+ self.assertEqual(attr_value, value,
+ "for __phello__.spam.%s, %r != %r" %
+ (attr, attr_value, value))
+ self.assertEqual(stdout.getvalue(), 'Hello world!\n')
+ self.assertFalse(hasattr(module, '__file__'))
def test_module_reuse(self):
- with util.uncache('__hello__'), captured_stdout() as stdout:
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module1 = self.machinery.FrozenImporter.load_module('__hello__')
- module2 = self.machinery.FrozenImporter.load_module('__hello__')
- self.assertIs(module1, module2)
- self.assertEqual(stdout.getvalue(),
- 'Hello world!\nHello world!\n')
+ with fresh('__hello__', oldapi=True) as stdout:
+ module1 = self.machinery.FrozenImporter.load_module('__hello__')
+ module2 = self.machinery.FrozenImporter.load_module('__hello__')
+ self.assertIs(module1, module2)
+ self.assertEqual(stdout.getvalue(),
+ 'Hello world!\nHello world!\n')
def test_module_repr(self):
- with util.uncache('__hello__'), captured_stdout():
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = self.machinery.FrozenImporter.load_module('__hello__')
- repr_str = self.machinery.FrozenImporter.module_repr(module)
- self.assertEqual(repr_str,
- "<module '__hello__' (frozen)>")
+ with fresh('__hello__', oldapi=True) as stdout:
+ module = self.machinery.FrozenImporter.load_module('__hello__')
+ repr_str = self.machinery.FrozenImporter.module_repr(module)
+ self.assertEqual(repr_str,
+ "<module '__hello__' (frozen)>")
# No way to trigger an error in a frozen module.
test_state_after_failure = None
def test_unloadable(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- assert self.machinery.FrozenImporter.find_module('_not_real') is None
+ with import_helper.frozen_modules():
+ with deprecated():
+ assert self.machinery.FrozenImporter.find_module('_not_real') is None
with self.assertRaises(ImportError) as cm:
- self.machinery.FrozenImporter.load_module('_not_real')
+ self.load_module('_not_real')
self.assertEqual(cm.exception.name, '_not_real')
# Make sure that the code object is good.
name = '__hello__'
with captured_stdout() as stdout:
- code = self.machinery.FrozenImporter.get_code(name)
- mod = types.ModuleType(name)
- exec(code, mod.__dict__)
- self.assertTrue(hasattr(mod, 'initialized'))
- self.assertEqual(stdout.getvalue(), 'Hello world!\n')
+ with import_helper.frozen_modules():
+ code = self.machinery.FrozenImporter.get_code(name)
+ mod = types.ModuleType(name)
+ exec(code, mod.__dict__)
+ self.assertTrue(hasattr(mod, 'initialized'))
+ self.assertEqual(stdout.getvalue(), 'Hello world!\n')
def test_get_source(self):
# Should always return None.
- result = self.machinery.FrozenImporter.get_source('__hello__')
+ with import_helper.frozen_modules():
+ result = self.machinery.FrozenImporter.get_source('__hello__')
self.assertIsNone(result)
def test_is_package(self):
test_for = (('__hello__', False), ('__phello__', True),
('__phello__.spam', False))
for name, is_package in test_for:
- result = self.machinery.FrozenImporter.is_package(name)
+ with import_helper.frozen_modules():
+ result = self.machinery.FrozenImporter.is_package(name)
self.assertEqual(bool(result), is_package)
def test_failure(self):
for meth_name in ('get_code', 'get_source', 'is_package'):
method = getattr(self.machinery.FrozenImporter, meth_name)
with self.assertRaises(ImportError) as cm:
- method('importlib')
+ with import_helper.frozen_modules():
+ method('importlib')
self.assertEqual(cm.exception.name, 'importlib')
(Frozen_ILTests,
instruction in code objects. This is useful when smaller code objects and pyc \n\
files are desired as well as supressing the extra visual location indicators \n\
when the interpreter displays tracebacks.\n\
+ -X frozen_modules=[on|off]: whether or not frozen modules should be used.\n\
+ The default is \"on\" (or \"off\" if you are running a local build).\n\
\n\
--check-hash-based-pycs always|default|never:\n\
control how Python invalidates hash-based .pyc files\n\
COPY_ATTR(pathconfig_warnings);
COPY_ATTR(_init_main);
COPY_ATTR(_isolated_interpreter);
+ COPY_ATTR(use_frozen_modules);
COPY_WSTRLIST(orig_argv);
#undef COPY_ATTR
SET_ITEM_INT(_init_main);
SET_ITEM_INT(_isolated_interpreter);
SET_ITEM_WSTRLIST(orig_argv);
+ SET_ITEM_INT(use_frozen_modules);
return dict;
GET_UINT(_install_importlib);
GET_UINT(_init_main);
GET_UINT(_isolated_interpreter);
+ GET_UINT(use_frozen_modules);
#undef CHECK_VALUE
#undef GET_UINT
return _Py_get_xoption(&config->xoptions, name);
}
+static const wchar_t*
+config_get_xoption_value(const PyConfig *config, wchar_t *name)
+{
+ const wchar_t *xoption = config_get_xoption(config, name);
+ if (xoption == NULL) {
+ return NULL;
+ }
+ const wchar_t *sep = wcschr(xoption, L'=');
+ return sep ? sep + 1 : L"";
+}
+
static PyStatus
config_init_home(PyConfig *config)
}
+static PyStatus
+config_init_import(PyConfig *config, int compute_path_config)
+{
+ PyStatus status;
+
+ status = _PyConfig_InitPathConfig(config, compute_path_config);
+ if (_PyStatus_EXCEPTION(status)) {
+ return status;
+ }
+
+ /* -X frozen_modules=[on|off] */
+ const wchar_t *value = config_get_xoption_value(config, L"frozen_modules");
+ if (value == NULL) {
+ // For now we always default to "off".
+ // In the near future we will be factoring in PGO and in-development.
+ config->use_frozen_modules = 0;
+ }
+ else if (wcscmp(value, L"on") == 0) {
+ config->use_frozen_modules = 1;
+ }
+ else if (wcscmp(value, L"off") == 0) {
+ config->use_frozen_modules = 0;
+ }
+ else if (wcslen(value) == 0) {
+ // "-X frozen_modules" and "-X frozen_modules=" both imply "on".
+ config->use_frozen_modules = 1;
+ }
+ else {
+ return PyStatus_Error("bad value for option -X frozen_modules "
+ "(expected \"on\" or \"off\")");
+ }
+
+ return _PyStatus_OK();
+}
+
+PyStatus
+_PyConfig_InitImportConfig(PyConfig *config)
+{
+ return config_init_import(config, 1);
+}
+
+
static PyStatus
config_read(PyConfig *config, int compute_path_config)
{
}
if (config->_install_importlib) {
- status = _PyConfig_InitPathConfig(config, compute_path_config);
+ status = config_init_import(config, compute_path_config);
if (_PyStatus_EXCEPTION(status)) {
return status;
}