Issue #17907: touch up the code for imp.new_module().
This commit is contained in:
parent
15e489f7c5
commit
a3c96154d2
|
@ -205,6 +205,9 @@ file paths.
|
|||
If :attr:`sys.implementation.cache_tag` is ``None``, then
|
||||
:exc:`NotImplementedError` is raised.
|
||||
|
||||
.. deprecated:: 3.4
|
||||
Use :func:`importlib.util.cache_from_source` instead.
|
||||
|
||||
|
||||
.. function:: source_from_cache(path)
|
||||
|
||||
|
@ -220,6 +223,9 @@ file paths.
|
|||
Raise :exc:`NotImplementedError` when
|
||||
:attr:`sys.implementation.cache_tag` is not defined.
|
||||
|
||||
.. deprecated:: 3.4
|
||||
Use :func:`importlib.util.source_from_cache` instead.
|
||||
|
||||
|
||||
.. function:: get_tag()
|
||||
|
||||
|
|
|
@ -886,6 +886,36 @@ an :term:`importer`.
|
|||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. function:: cache_from_source(path, debug_override=None)
|
||||
|
||||
Return the :pep:`3147` path to the byte-compiled file associated with the
|
||||
source *path*. For example, if *path* is ``/foo/bar/baz.py`` the return
|
||||
value would be ``/foo/bar/__pycache__/baz.cpython-32.pyc`` for Python 3.2.
|
||||
The ``cpython-32`` string comes from the current magic tag (see
|
||||
:func:`get_tag`; if :attr:`sys.implementation.cache_tag` is not defined then
|
||||
:exc:`NotImplementedError` will be raised). The returned path will end in
|
||||
``.pyc`` when ``__debug__`` is True or ``.pyo`` for an optimized Python
|
||||
(i.e. ``__debug__`` is False). By passing in True or False for
|
||||
*debug_override* you can override the system's value for ``__debug__`` for
|
||||
extension selection.
|
||||
|
||||
*path* need not exist.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
.. function:: source_from_cache(path)
|
||||
|
||||
Given the *path* to a :pep:`3147` file name, return the associated source code
|
||||
file path. For example, if *path* is
|
||||
``/foo/bar/__pycache__/baz.cpython-32.pyc`` the returned path would be
|
||||
``/foo/bar/baz.py``. *path* need not exist, however if it does not conform
|
||||
to :pep:`3147` format, a ``ValueError`` is raised. If
|
||||
:attr:`sys.implementation.cache_tag` is not defined,
|
||||
:exc:`NotImplementedError` is raised.
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. function:: resolve_name(name, package)
|
||||
|
||||
Resolve a relative module name to an absolute one.
|
||||
|
|
13
Lib/imp.py
13
Lib/imp.py
|
@ -17,7 +17,6 @@ except ModuleNotFoundError:
|
|||
load_dynamic = None
|
||||
|
||||
# Directly exposed by this module
|
||||
from importlib._bootstrap import new_module
|
||||
from importlib._bootstrap import cache_from_source, source_from_cache
|
||||
|
||||
|
||||
|
@ -28,6 +27,7 @@ import importlib
|
|||
import os
|
||||
import sys
|
||||
import tokenize
|
||||
import types
|
||||
import warnings
|
||||
|
||||
|
||||
|
@ -44,6 +44,17 @@ PY_CODERESOURCE = 8
|
|||
IMP_HOOK = 9
|
||||
|
||||
|
||||
def new_module(name):
|
||||
"""**DEPRECATED**
|
||||
|
||||
Create a new module.
|
||||
|
||||
The module is not entered into sys.modules.
|
||||
|
||||
"""
|
||||
return types.ModuleType(name)
|
||||
|
||||
|
||||
def get_magic():
|
||||
"""**DEPRECATED**
|
||||
|
||||
|
|
|
@ -121,15 +121,6 @@ def _wrap(new, old):
|
|||
_code_type = type(_wrap.__code__)
|
||||
|
||||
|
||||
def new_module(name):
|
||||
"""Create a new module.
|
||||
|
||||
The module is not entered into sys.modules.
|
||||
|
||||
"""
|
||||
return type(_io)(name)
|
||||
|
||||
|
||||
# Module-level locking ########################################################
|
||||
|
||||
# A dict mapping module names to weakrefs of _ModuleLock instances
|
||||
|
@ -509,7 +500,7 @@ class _ModuleManager:
|
|||
# This must be done before open() is called as the 'io' module
|
||||
# implicitly imports 'locale' and would otherwise trigger an
|
||||
# infinite loop.
|
||||
self._module = new_module(self._name)
|
||||
self._module = type(_io)(self._name)
|
||||
# This must be done before putting the module in sys.modules
|
||||
# (otherwise an optimization shortcut in import.c becomes wrong)
|
||||
self._module.__initializing__ = True
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
"""Utility code for constructing importers, etc."""
|
||||
|
||||
from ._bootstrap import MAGIC_NUMBER
|
||||
from ._bootstrap import cache_from_source
|
||||
from ._bootstrap import module_to_load
|
||||
from ._bootstrap import set_loader
|
||||
from ._bootstrap import set_package
|
||||
from ._bootstrap import source_from_cache
|
||||
from ._bootstrap import _resolve_name
|
||||
|
||||
import functools
|
||||
|
|
|
@ -859,7 +859,6 @@ class ImportlibBootstrapTests(unittest.TestCase):
|
|||
from importlib import machinery
|
||||
mod = sys.modules['_frozen_importlib']
|
||||
self.assertIs(machinery.FileFinder, mod.FileFinder)
|
||||
self.assertIs(imp.new_module, mod.new_module)
|
||||
|
||||
|
||||
class ImportTracebackTests(unittest.TestCase):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from importlib import util
|
||||
from . import util as test_util
|
||||
import imp
|
||||
import os
|
||||
import sys
|
||||
from test import support
|
||||
import types
|
||||
|
@ -324,5 +325,120 @@ class MagicNumberTests(unittest.TestCase):
|
|||
self.assertTrue(util.MAGIC_NUMBER.endswith(b'\r\n'))
|
||||
|
||||
|
||||
class PEP3147Tests(unittest.TestCase):
|
||||
"""Tests of PEP 3147-related functions:
|
||||
cache_from_source and source_from_cache.
|
||||
|
||||
"""
|
||||
|
||||
tag = imp.get_tag()
|
||||
|
||||
@unittest.skipUnless(sys.implementation.cache_tag is not None,
|
||||
'requires sys.implementation.cache_tag not be None')
|
||||
def test_cache_from_source(self):
|
||||
# Given the path to a .py file, return the path to its PEP 3147
|
||||
# defined .pyc file (i.e. under __pycache__).
|
||||
path = os.path.join('foo', 'bar', 'baz', 'qux.py')
|
||||
expect = os.path.join('foo', 'bar', 'baz', '__pycache__',
|
||||
'qux.{}.pyc'.format(self.tag))
|
||||
self.assertEqual(util.cache_from_source(path, True), expect)
|
||||
|
||||
def test_cache_from_source_no_cache_tag(self):
|
||||
# No cache tag means NotImplementedError.
|
||||
with support.swap_attr(sys.implementation, 'cache_tag', None):
|
||||
with self.assertRaises(NotImplementedError):
|
||||
util.cache_from_source('whatever.py')
|
||||
|
||||
def test_cache_from_source_no_dot(self):
|
||||
# Directory with a dot, filename without dot.
|
||||
path = os.path.join('foo.bar', 'file')
|
||||
expect = os.path.join('foo.bar', '__pycache__',
|
||||
'file{}.pyc'.format(self.tag))
|
||||
self.assertEqual(util.cache_from_source(path, True), expect)
|
||||
|
||||
def test_cache_from_source_optimized(self):
|
||||
# Given the path to a .py file, return the path to its PEP 3147
|
||||
# defined .pyo file (i.e. under __pycache__).
|
||||
path = os.path.join('foo', 'bar', 'baz', 'qux.py')
|
||||
expect = os.path.join('foo', 'bar', 'baz', '__pycache__',
|
||||
'qux.{}.pyo'.format(self.tag))
|
||||
self.assertEqual(util.cache_from_source(path, False), expect)
|
||||
|
||||
def test_cache_from_source_cwd(self):
|
||||
path = 'foo.py'
|
||||
expect = os.path.join('__pycache__', 'foo.{}.pyc'.format(self.tag))
|
||||
self.assertEqual(util.cache_from_source(path, True), expect)
|
||||
|
||||
def test_cache_from_source_override(self):
|
||||
# When debug_override is not None, it can be any true-ish or false-ish
|
||||
# value.
|
||||
path = os.path.join('foo', 'bar', 'baz.py')
|
||||
partial_expect = os.path.join('foo', 'bar', '__pycache__',
|
||||
'baz.{}.py'.format(self.tag))
|
||||
self.assertEqual(util.cache_from_source(path, []), partial_expect + 'o')
|
||||
self.assertEqual(util.cache_from_source(path, [17]),
|
||||
partial_expect + 'c')
|
||||
# However if the bool-ishness can't be determined, the exception
|
||||
# propagates.
|
||||
class Bearish:
|
||||
def __bool__(self): raise RuntimeError
|
||||
with self.assertRaises(RuntimeError):
|
||||
util.cache_from_source('/foo/bar/baz.py', Bearish())
|
||||
|
||||
@unittest.skipUnless(os.sep == '\\' and os.altsep == '/',
|
||||
'test meaningful only where os.altsep is defined')
|
||||
def test_sep_altsep_and_sep_cache_from_source(self):
|
||||
# Windows path and PEP 3147 where sep is right of altsep.
|
||||
self.assertEqual(
|
||||
util.cache_from_source('\\foo\\bar\\baz/qux.py', True),
|
||||
'\\foo\\bar\\baz\\__pycache__\\qux.{}.pyc'.format(self.tag))
|
||||
|
||||
@unittest.skipUnless(sys.implementation.cache_tag is not None,
|
||||
'requires sys.implementation.cache_tag to not be '
|
||||
'None')
|
||||
def test_source_from_cache(self):
|
||||
# Given the path to a PEP 3147 defined .pyc file, return the path to
|
||||
# its source. This tests the good path.
|
||||
path = os.path.join('foo', 'bar', 'baz', '__pycache__',
|
||||
'qux.{}.pyc'.format(self.tag))
|
||||
expect = os.path.join('foo', 'bar', 'baz', 'qux.py')
|
||||
self.assertEqual(util.source_from_cache(path), expect)
|
||||
|
||||
def test_source_from_cache_no_cache_tag(self):
|
||||
# If sys.implementation.cache_tag is None, raise NotImplementedError.
|
||||
path = os.path.join('blah', '__pycache__', 'whatever.pyc')
|
||||
with support.swap_attr(sys.implementation, 'cache_tag', None):
|
||||
with self.assertRaises(NotImplementedError):
|
||||
util.source_from_cache(path)
|
||||
|
||||
def test_source_from_cache_bad_path(self):
|
||||
# When the path to a pyc file is not in PEP 3147 format, a ValueError
|
||||
# is raised.
|
||||
self.assertRaises(
|
||||
ValueError, util.source_from_cache, '/foo/bar/bazqux.pyc')
|
||||
|
||||
def test_source_from_cache_no_slash(self):
|
||||
# No slashes at all in path -> ValueError
|
||||
self.assertRaises(
|
||||
ValueError, util.source_from_cache, 'foo.cpython-32.pyc')
|
||||
|
||||
def test_source_from_cache_too_few_dots(self):
|
||||
# Too few dots in final path component -> ValueError
|
||||
self.assertRaises(
|
||||
ValueError, util.source_from_cache, '__pycache__/foo.pyc')
|
||||
|
||||
def test_source_from_cache_too_many_dots(self):
|
||||
# Too many dots in final path component -> ValueError
|
||||
self.assertRaises(
|
||||
ValueError, util.source_from_cache,
|
||||
'__pycache__/foo.cpython-32.foo.pyc')
|
||||
|
||||
def test_source_from_cache_no__pycache__(self):
|
||||
# Another problem with the path -> ValueError
|
||||
self.assertRaises(
|
||||
ValueError, util.source_from_cache,
|
||||
'/foo/bar/foo.cpython-32.foo.pyc')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
7079
Python/importlib.h
7079
Python/importlib.h
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue