mirror of
https://github.com/python/cpython.git
synced 2025-08-03 00:23:06 +00:00
Move importlib.abc.SourceLoader.source_to_code() to InspectLoader.
While the previous location was fine, it makes more sense to have the method higher up in the inheritance chain, especially at a point where get_source() is defined which is the earliest source_to_code() could programmatically be used in the inheritance tree in importlib.abc.
This commit is contained in:
parent
1256f1f438
commit
9ffe85e1e8
4 changed files with 66 additions and 15 deletions
|
@ -349,6 +349,17 @@ ABC hierarchy::
|
|||
.. versionchanged:: 3.4
|
||||
Raises :exc:`ImportError` instead of :exc:`NotImplementedError`.
|
||||
|
||||
.. method:: source_to_code(data, path='<string>')
|
||||
|
||||
Create a code object from Python source.
|
||||
|
||||
The *data* argument can be whatever the :func:`compile` function
|
||||
supports (i.e. string or bytes). The *path* argument should be
|
||||
the "path" to where the source code originated from, which can be an
|
||||
abstract concept (e.g. location in a zip file).
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
.. class:: ExecutionLoader
|
||||
|
||||
|
@ -466,17 +477,6 @@ ABC hierarchy::
|
|||
.. versionchanged:: 3.4
|
||||
No longer raises :exc:`NotImplementedError` when called.
|
||||
|
||||
.. method:: source_to_code(data, path)
|
||||
|
||||
Create a code object from Python source.
|
||||
|
||||
The *data* argument can be whatever the :func:`compile` function
|
||||
supports (i.e. string or bytes). The *path* argument should be
|
||||
the "path" to where the source code originated from, which can be an
|
||||
abstract concept (e.g. location in a zip file).
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
.. method:: get_code(fullname)
|
||||
|
||||
Concrete implementation of :meth:`InspectLoader.get_code`.
|
||||
|
|
|
@ -165,6 +165,13 @@ class InspectLoader(Loader):
|
|||
"""
|
||||
raise ImportError
|
||||
|
||||
def source_to_code(self, data, path='<string>'):
|
||||
"""Compile 'data' into a code object.
|
||||
|
||||
The 'data' argument can be anything that compile() can handle. The'path'
|
||||
argument should be where the data was retrieved (when applicable)."""
|
||||
return compile(data, path, 'exec', dont_inherit=True)
|
||||
|
||||
_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter,
|
||||
machinery.ExtensionFileLoader)
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import unittest
|
|||
|
||||
from . import util
|
||||
|
||||
##### Inheritance
|
||||
##### Inheritance ##############################################################
|
||||
class InheritanceTests:
|
||||
|
||||
"""Test that the specified class is a subclass/superclass of the expected
|
||||
|
@ -81,7 +81,7 @@ class SourceLoader(InheritanceTests, unittest.TestCase):
|
|||
subclasses = [machinery.SourceFileLoader]
|
||||
|
||||
|
||||
##### Default semantics
|
||||
##### Default return values ####################################################
|
||||
class MetaPathFinderSubclass(abc.MetaPathFinder):
|
||||
|
||||
def find_module(self, fullname, path):
|
||||
|
@ -205,7 +205,50 @@ class ExecutionLoaderDefaultsTests(unittest.TestCase):
|
|||
self.ins.get_filename('blah')
|
||||
|
||||
|
||||
##### SourceLoader
|
||||
##### InspectLoader concrete methods ###########################################
|
||||
class InspectLoaderConcreteMethodTests(unittest.TestCase):
|
||||
|
||||
def source_to_module(self, data, path=None):
|
||||
"""Help with source_to_code() tests."""
|
||||
module = imp.new_module('blah')
|
||||
loader = InspectLoaderSubclass()
|
||||
if path is None:
|
||||
code = loader.source_to_code(data)
|
||||
else:
|
||||
code = loader.source_to_code(data, path)
|
||||
exec(code, module.__dict__)
|
||||
return module
|
||||
|
||||
def test_source_to_code_source(self):
|
||||
# Since compile() can handle strings, so should source_to_code().
|
||||
source = 'attr = 42'
|
||||
module = self.source_to_module(source)
|
||||
self.assertTrue(hasattr(module, 'attr'))
|
||||
self.assertEqual(module.attr, 42)
|
||||
|
||||
def test_source_to_code_bytes(self):
|
||||
# Since compile() can handle bytes, so should source_to_code().
|
||||
source = b'attr = 42'
|
||||
module = self.source_to_module(source)
|
||||
self.assertTrue(hasattr(module, 'attr'))
|
||||
self.assertEqual(module.attr, 42)
|
||||
|
||||
def test_source_to_code_path(self):
|
||||
# Specifying a path should set it for the code object.
|
||||
path = 'path/to/somewhere'
|
||||
loader = InspectLoaderSubclass()
|
||||
code = loader.source_to_code('', path)
|
||||
self.assertEqual(code.co_filename, path)
|
||||
|
||||
def test_source_to_code_no_path(self):
|
||||
# Not setting a path should still work and be set to <string> since that
|
||||
# is a pre-existing practice as a default to compile().
|
||||
loader = InspectLoaderSubclass()
|
||||
code = loader.source_to_code('')
|
||||
self.assertEqual(code.co_filename, '<string>')
|
||||
|
||||
|
||||
##### SourceLoader concrete methods ############################################
|
||||
class SourceOnlyLoaderMock(abc.SourceLoader):
|
||||
|
||||
# Globals that should be defined for all modules.
|
||||
|
@ -498,5 +541,6 @@ class SourceLoaderGetSourceTests(unittest.TestCase):
|
|||
self.assertEqual(mock.get_source(name), expect)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -1111,7 +1111,7 @@ Library
|
|||
|
||||
- Issue #16522: added FAIL_FAST flag to doctest.
|
||||
|
||||
- Issue #15627: Add the importlib.abc.SourceLoader.source_to_code() method.
|
||||
- Issue #15627: Add the importlib.abc.InspectLoader.source_to_code() method.
|
||||
|
||||
- Issue #16408: Fix file descriptors not being closed in error conditions
|
||||
in the zipfile module. Patch by Serhiy Storchaka.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue