Issue #26667: Add path-like object support to importlib.util.

This commit is contained in:
Brett Cannon 2016-09-07 18:39:18 -07:00
parent d5f9223981
commit 035a100382
7 changed files with 2224 additions and 2172 deletions

View File

@ -1149,6 +1149,9 @@ an :term:`importer`.
The *optimization* parameter was added and the *debug_override* parameter
was deprecated.
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
.. function:: source_from_cache(path)
@ -1162,6 +1165,9 @@ an :term:`importer`.
.. versionadded:: 3.4
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
.. function:: decode_source(source_bytes)
Decode the given bytes representing source code and return it as a string
@ -1298,6 +1304,9 @@ an :term:`importer`.
.. versionadded:: 3.4
.. versionchanged:: 3.6
Accepts a :term:`path-like object`.
.. class:: LazyLoader(loader)
A class which postpones the execution of the loader of a module until the

View File

@ -68,8 +68,6 @@ New syntax features:
Standard library improvements:
* PEP 519: :ref:`Adding a file system path protocol <pep-519>`
Security improvements:
* On Linux, :func:`os.urandom` now blocks until the system urandom entropy pool
@ -513,6 +511,11 @@ restriction that :class:`importlib.machinery.BuiltinImporter` and
:class:`importlib.machinery.ExtensionFileLoader` couldn't be used with
:class:`importlib.util.LazyLoader`.
:func:`importlib.util.cache_from_source`,
:func:`importlib.util.source_from_cache`, and
:func:`importlib.util.spec_from_file_location` now accept a
:term:`path-like object`.
os
--
@ -528,6 +531,11 @@ The Linux ``getrandom()`` syscall (get random bytes) is now exposed as the new
:func:`os.getrandom` function.
(Contributed by Victor Stinner, part of the :pep:`524`)
See the summary for :ref:`PEP 519 <pep-519>` for details on how the
:mod:`os` and :mod:`os.path` modules now support
:term:`path-like objects <path-like object>`.
pickle
------

View File

@ -279,6 +279,7 @@ def cache_from_source(path, debug_override=None, *, optimization=None):
message = 'debug_override or optimization must be set to None'
raise TypeError(message)
optimization = '' if debug_override else 1
path = _os.fspath(path)
head, tail = _path_split(path)
base, sep, rest = tail.rpartition('.')
tag = sys.implementation.cache_tag
@ -309,6 +310,7 @@ def source_from_cache(path):
"""
if sys.implementation.cache_tag is None:
raise NotImplementedError('sys.implementation.cache_tag is None')
path = _os.fspath(path)
head, pycache_filename = _path_split(path)
head, pycache = _path_split(head)
if pycache != _PYCACHE:
@ -536,6 +538,8 @@ def spec_from_file_location(name, location=None, *, loader=None,
location = loader.get_filename(name)
except ImportError:
pass
else:
location = _os.fspath(location)
# If the location is on the filesystem, but doesn't actually exist,
# we could return None here, indicating that the location is not

View File

@ -5,6 +5,7 @@ machinery = test_util.import_importlib('importlib.machinery')
util = test_util.import_importlib('importlib.util')
import os.path
import pathlib
from test.support import CleanImport
import unittest
import sys
@ -659,6 +660,11 @@ class FactoryTests:
self.assertEqual(spec.cached, self.cached)
self.assertTrue(spec.has_location)
def test_spec_from_file_location_path_like_arg(self):
spec = self.util.spec_from_file_location(self.name,
pathlib.PurePath(self.path))
self.assertEqual(spec.origin, self.path)
def test_spec_from_file_location_default_without_location(self):
spec = self.util.spec_from_file_location(self.name)

View File

@ -5,6 +5,7 @@ machinery = util.import_importlib('importlib.machinery')
importlib_util = util.import_importlib('importlib.util')
import os
import pathlib
import string
import sys
from test import support
@ -676,6 +677,15 @@ class PEP3147Tests:
self.util.cache_from_source('\\foo\\bar\\baz/qux.py', optimization=''),
'\\foo\\bar\\baz\\__pycache__\\qux.{}.pyc'.format(self.tag))
@unittest.skipUnless(sys.implementation.cache_tag is not None,
'requires sys.implementation.cache_tag not be None')
def test_source_from_cache_path_like_arg(self):
path = pathlib.PurePath('foo', 'bar', 'baz', 'qux.py')
expect = os.path.join('foo', 'bar', 'baz', '__pycache__',
'qux.{}.pyc'.format(self.tag))
self.assertEqual(self.util.cache_from_source(path, optimization=''),
expect)
@unittest.skipUnless(sys.implementation.cache_tag is not None,
'requires sys.implementation.cache_tag to not be '
'None')
@ -738,6 +748,15 @@ class PEP3147Tests:
with self.assertRaises(ValueError):
self.util.source_from_cache(path)
@unittest.skipUnless(sys.implementation.cache_tag is not None,
'requires sys.implementation.cache_tag to not be '
'None')
def test_source_from_cache_path_like_arg(self):
path = pathlib.PurePath('foo', 'bar', 'baz', '__pycache__',
'qux.{}.pyc'.format(self.tag))
expect = os.path.join('foo', 'bar', 'baz', 'qux.py')
self.assertEqual(self.util.source_from_cache(path), expect)
(Frozen_PEP3147Tests,
Source_PEP3147Tests

View File

@ -108,6 +108,8 @@ Library
- Issue #28005: Allow ImportErrors in encoding implementation to propagate.
- Issue #26667: Support path-like objects in importlib.util.
- Issue #27570: Avoid zero-length memcpy() etc calls with null source
pointers in the "ctypes" and "array" modules.

File diff suppressed because it is too large Load Diff