mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-10-27 11:01:57 -06:00
Removed the Requirement to Install Python and NodeJS (Now Bundled with Borealis)
This commit is contained in:
5
Dependencies/Python/Lib/test/test_importlib/__init__.py
vendored
Normal file
5
Dependencies/Python/Lib/test/test_importlib/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
from test.support import load_package_tests
|
||||
|
||||
def load_tests(*args):
|
||||
return load_package_tests(os.path.dirname(__file__), *args)
|
||||
4
Dependencies/Python/Lib/test/test_importlib/__main__.py
vendored
Normal file
4
Dependencies/Python/Lib/test/test_importlib/__main__.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
from . import load_tests
|
||||
import unittest
|
||||
|
||||
unittest.main()
|
||||
93
Dependencies/Python/Lib/test/test_importlib/abc.py
vendored
Normal file
93
Dependencies/Python/Lib/test/test_importlib/abc.py
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import abc
|
||||
|
||||
|
||||
class FinderTests(metaclass=abc.ABCMeta):
|
||||
|
||||
"""Basic tests for a finder to pass."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_module(self):
|
||||
# Test importing a top-level module.
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_package(self):
|
||||
# Test importing a package.
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_module_in_package(self):
|
||||
# Test importing a module contained within a package.
|
||||
# A value for 'path' should be used if for a meta_path finder.
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_package_in_package(self):
|
||||
# Test importing a subpackage.
|
||||
# A value for 'path' should be used if for a meta_path finder.
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_package_over_module(self):
|
||||
# Test that packages are chosen over modules.
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_failure(self):
|
||||
# Test trying to find a module that cannot be handled.
|
||||
pass
|
||||
|
||||
|
||||
class LoaderTests(metaclass=abc.ABCMeta):
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_module(self):
|
||||
"""A module should load without issue.
|
||||
|
||||
After the loader returns the module should be in sys.modules.
|
||||
|
||||
Attributes to verify:
|
||||
|
||||
* __file__
|
||||
* __loader__
|
||||
* __name__
|
||||
* No __path__
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_package(self):
|
||||
"""Loading a package should work.
|
||||
|
||||
After the loader returns the module should be in sys.modules.
|
||||
|
||||
Attributes to verify:
|
||||
|
||||
* __name__
|
||||
* __file__
|
||||
* __package__
|
||||
* __path__
|
||||
* __loader__
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_lacking_parent(self):
|
||||
"""A loader should not be dependent on it's parent package being
|
||||
imported."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_state_after_failure(self):
|
||||
"""If a module is already in sys.modules and a reload fails
|
||||
(e.g. a SyntaxError), the module should be in the state it was before
|
||||
the reload began."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def test_unloadable(self):
|
||||
"""Test ImportError is raised when the loader is asked to load a module
|
||||
it can't."""
|
||||
pass
|
||||
5
Dependencies/Python/Lib/test/test_importlib/builtin/__init__.py
vendored
Normal file
5
Dependencies/Python/Lib/test/test_importlib/builtin/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
from test.support import load_package_tests
|
||||
|
||||
def load_tests(*args):
|
||||
return load_package_tests(os.path.dirname(__file__), *args)
|
||||
4
Dependencies/Python/Lib/test/test_importlib/builtin/__main__.py
vendored
Normal file
4
Dependencies/Python/Lib/test/test_importlib/builtin/__main__.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
from . import load_tests
|
||||
import unittest
|
||||
|
||||
unittest.main()
|
||||
46
Dependencies/Python/Lib/test/test_importlib/builtin/test_finder.py
vendored
Normal file
46
Dependencies/Python/Lib/test/test_importlib/builtin/test_finder.py
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
from test.test_importlib import abc, util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
|
||||
@unittest.skipIf(util.BUILTINS.good_name is None, 'no reasonable builtin module')
|
||||
class FindSpecTests(abc.FinderTests):
|
||||
|
||||
"""Test find_spec() for built-in modules."""
|
||||
|
||||
def test_module(self):
|
||||
# Common case.
|
||||
with util.uncache(util.BUILTINS.good_name):
|
||||
found = self.machinery.BuiltinImporter.find_spec(util.BUILTINS.good_name)
|
||||
self.assertTrue(found)
|
||||
self.assertEqual(found.origin, 'built-in')
|
||||
|
||||
# Built-in modules cannot be a package.
|
||||
test_package = None
|
||||
|
||||
# Built-in modules cannot be in a package.
|
||||
test_module_in_package = None
|
||||
|
||||
# Built-in modules cannot be a package.
|
||||
test_package_in_package = None
|
||||
|
||||
# Built-in modules cannot be a package.
|
||||
test_package_over_module = None
|
||||
|
||||
def test_failure(self):
|
||||
name = 'importlib'
|
||||
assert name not in sys.builtin_module_names
|
||||
spec = self.machinery.BuiltinImporter.find_spec(name)
|
||||
self.assertIsNone(spec)
|
||||
|
||||
|
||||
(Frozen_FindSpecTests,
|
||||
Source_FindSpecTests
|
||||
) = util.test_both(FindSpecTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
110
Dependencies/Python/Lib/test/test_importlib/builtin/test_loader.py
vendored
Normal file
110
Dependencies/Python/Lib/test/test_importlib/builtin/test_loader.py
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
from test.test_importlib import abc, util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
@unittest.skipIf(util.BUILTINS.good_name is None, 'no reasonable builtin module')
|
||||
class LoaderTests(abc.LoaderTests):
|
||||
|
||||
"""Test load_module() for built-in modules."""
|
||||
|
||||
def setUp(self):
|
||||
self.verification = {'__name__': 'errno', '__package__': '',
|
||||
'__loader__': self.machinery.BuiltinImporter}
|
||||
|
||||
def verify(self, module):
|
||||
"""Verify that the module matches against what it should have."""
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
for attr, value in self.verification.items():
|
||||
self.assertEqual(getattr(module, attr), value)
|
||||
self.assertIn(module.__name__, sys.modules)
|
||||
|
||||
def load_module(self, name):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
return self.machinery.BuiltinImporter.load_module(name)
|
||||
|
||||
def test_module(self):
|
||||
# Common case.
|
||||
with util.uncache(util.BUILTINS.good_name):
|
||||
module = self.load_module(util.BUILTINS.good_name)
|
||||
self.verify(module)
|
||||
|
||||
# Built-in modules cannot be a package.
|
||||
test_package = test_lacking_parent = None
|
||||
|
||||
# No way to force an import failure.
|
||||
test_state_after_failure = None
|
||||
|
||||
def test_module_reuse(self):
|
||||
# Test that the same module is used in a reload.
|
||||
with util.uncache(util.BUILTINS.good_name):
|
||||
module1 = self.load_module(util.BUILTINS.good_name)
|
||||
module2 = self.load_module(util.BUILTINS.good_name)
|
||||
self.assertIs(module1, module2)
|
||||
|
||||
def test_unloadable(self):
|
||||
name = 'dssdsdfff'
|
||||
assert name not in sys.builtin_module_names
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.load_module(name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
|
||||
def test_already_imported(self):
|
||||
# Using the name of a module already imported but not a built-in should
|
||||
# still fail.
|
||||
module_name = 'builtin_reload_test'
|
||||
assert module_name not in sys.builtin_module_names
|
||||
with util.uncache(module_name):
|
||||
module = types.ModuleType(module_name)
|
||||
sys.modules[module_name] = module
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.load_module(module_name)
|
||||
self.assertEqual(cm.exception.name, module_name)
|
||||
|
||||
|
||||
(Frozen_LoaderTests,
|
||||
Source_LoaderTests
|
||||
) = util.test_both(LoaderTests, machinery=machinery)
|
||||
|
||||
|
||||
@unittest.skipIf(util.BUILTINS.good_name is None, 'no reasonable builtin module')
|
||||
class InspectLoaderTests:
|
||||
|
||||
"""Tests for InspectLoader methods for BuiltinImporter."""
|
||||
|
||||
def test_get_code(self):
|
||||
# There is no code object.
|
||||
result = self.machinery.BuiltinImporter.get_code(util.BUILTINS.good_name)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_get_source(self):
|
||||
# There is no source.
|
||||
result = self.machinery.BuiltinImporter.get_source(util.BUILTINS.good_name)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_is_package(self):
|
||||
# Cannot be a package.
|
||||
result = self.machinery.BuiltinImporter.is_package(util.BUILTINS.good_name)
|
||||
self.assertFalse(result)
|
||||
|
||||
@unittest.skipIf(util.BUILTINS.bad_name is None, 'all modules are built in')
|
||||
def test_not_builtin(self):
|
||||
# Modules not built-in should raise ImportError.
|
||||
for meth_name in ('get_code', 'get_source', 'is_package'):
|
||||
method = getattr(self.machinery.BuiltinImporter, meth_name)
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
method(util.BUILTINS.bad_name)
|
||||
|
||||
|
||||
(Frozen_InspectLoaderTests,
|
||||
Source_InspectLoaderTests
|
||||
) = util.test_both(InspectLoaderTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
5
Dependencies/Python/Lib/test/test_importlib/extension/__init__.py
vendored
Normal file
5
Dependencies/Python/Lib/test/test_importlib/extension/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
from test.support import load_package_tests
|
||||
|
||||
def load_tests(*args):
|
||||
return load_package_tests(os.path.dirname(__file__), *args)
|
||||
4
Dependencies/Python/Lib/test/test_importlib/extension/__main__.py
vendored
Normal file
4
Dependencies/Python/Lib/test/test_importlib/extension/__main__.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
from . import load_tests
|
||||
import unittest
|
||||
|
||||
unittest.main()
|
||||
44
Dependencies/Python/Lib/test/test_importlib/extension/_test_nonmodule_cases.py
vendored
Normal file
44
Dependencies/Python/Lib/test/test_importlib/extension/_test_nonmodule_cases.py
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
import types
|
||||
import unittest
|
||||
from test.test_importlib import util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
from test.test_importlib.extension.test_loader import MultiPhaseExtensionModuleTests
|
||||
|
||||
|
||||
class NonModuleExtensionTests:
|
||||
setUp = MultiPhaseExtensionModuleTests.setUp
|
||||
load_module_by_name = MultiPhaseExtensionModuleTests.load_module_by_name
|
||||
|
||||
def _test_nonmodule(self):
|
||||
# Test returning a non-module object from create works.
|
||||
name = self.name + '_nonmodule'
|
||||
mod = self.load_module_by_name(name)
|
||||
self.assertNotEqual(type(mod), type(unittest))
|
||||
self.assertEqual(mod.three, 3)
|
||||
|
||||
# issue 27782
|
||||
def test_nonmodule_with_methods(self):
|
||||
# Test creating a non-module object with methods defined.
|
||||
name = self.name + '_nonmodule_with_methods'
|
||||
mod = self.load_module_by_name(name)
|
||||
self.assertNotEqual(type(mod), type(unittest))
|
||||
self.assertEqual(mod.three, 3)
|
||||
self.assertEqual(mod.bar(10, 1), 9)
|
||||
|
||||
def test_null_slots(self):
|
||||
# Test that NULL slots aren't a problem.
|
||||
name = self.name + '_null_slots'
|
||||
module = self.load_module_by_name(name)
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
self.assertEqual(module.__name__, name)
|
||||
|
||||
|
||||
(Frozen_NonModuleExtensionTests,
|
||||
Source_NonModuleExtensionTests
|
||||
) = util.test_both(NonModuleExtensionTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
49
Dependencies/Python/Lib/test/test_importlib/extension/test_case_sensitivity.py
vendored
Normal file
49
Dependencies/Python/Lib/test/test_importlib/extension/test_case_sensitivity.py
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
from importlib import _bootstrap_external
|
||||
from test.support import os_helper
|
||||
import unittest
|
||||
import sys
|
||||
from test.test_importlib import util
|
||||
|
||||
importlib = util.import_importlib('importlib')
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
|
||||
@unittest.skipIf(util.EXTENSIONS is None or util.EXTENSIONS.filename is None,
|
||||
'dynamic loading not supported or test module not available')
|
||||
@util.case_insensitive_tests
|
||||
class ExtensionModuleCaseSensitivityTest(util.CASEOKTestBase):
|
||||
|
||||
def find_spec(self):
|
||||
good_name = util.EXTENSIONS.name
|
||||
bad_name = good_name.upper()
|
||||
assert good_name != bad_name
|
||||
finder = self.machinery.FileFinder(util.EXTENSIONS.path,
|
||||
(self.machinery.ExtensionFileLoader,
|
||||
self.machinery.EXTENSION_SUFFIXES))
|
||||
return finder.find_spec(bad_name)
|
||||
|
||||
@unittest.skipIf(sys.flags.ignore_environment, 'ignore_environment flag was set')
|
||||
def test_case_sensitive(self):
|
||||
with os_helper.EnvironmentVarGuard() as env:
|
||||
env.unset('PYTHONCASEOK')
|
||||
self.caseok_env_changed(should_exist=False)
|
||||
spec = self.find_spec()
|
||||
self.assertIsNone(spec)
|
||||
|
||||
@unittest.skipIf(sys.flags.ignore_environment, 'ignore_environment flag was set')
|
||||
def test_case_insensitivity(self):
|
||||
with os_helper.EnvironmentVarGuard() as env:
|
||||
env.set('PYTHONCASEOK', '1')
|
||||
self.caseok_env_changed(should_exist=True)
|
||||
spec = self.find_spec()
|
||||
self.assertTrue(spec)
|
||||
|
||||
|
||||
(Frozen_ExtensionCaseSensitivity,
|
||||
Source_ExtensionCaseSensitivity
|
||||
) = util.test_both(ExtensionModuleCaseSensitivityTest, importlib=importlib,
|
||||
machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
69
Dependencies/Python/Lib/test/test_importlib/extension/test_finder.py
vendored
Normal file
69
Dependencies/Python/Lib/test/test_importlib/extension/test_finder.py
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
from test.support import is_apple_mobile
|
||||
from test.test_importlib import abc, util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
|
||||
class FinderTests(abc.FinderTests):
|
||||
|
||||
"""Test the finder for extension modules."""
|
||||
|
||||
def setUp(self):
|
||||
if not self.machinery.EXTENSION_SUFFIXES or not util.EXTENSIONS:
|
||||
raise unittest.SkipTest("Requires dynamic loading support.")
|
||||
if util.EXTENSIONS.name in sys.builtin_module_names:
|
||||
raise unittest.SkipTest(
|
||||
f"{util.EXTENSIONS.name} is a builtin module"
|
||||
)
|
||||
|
||||
def find_spec(self, fullname):
|
||||
if is_apple_mobile:
|
||||
# Apple mobile platforms require a specialist loader that uses
|
||||
# .fwork files as placeholders for the true `.so` files.
|
||||
loaders = [
|
||||
(
|
||||
self.machinery.AppleFrameworkLoader,
|
||||
[
|
||||
ext.replace(".so", ".fwork")
|
||||
for ext in self.machinery.EXTENSION_SUFFIXES
|
||||
]
|
||||
)
|
||||
]
|
||||
else:
|
||||
loaders = [
|
||||
(
|
||||
self.machinery.ExtensionFileLoader,
|
||||
self.machinery.EXTENSION_SUFFIXES
|
||||
)
|
||||
]
|
||||
|
||||
importer = self.machinery.FileFinder(util.EXTENSIONS.path, *loaders)
|
||||
|
||||
return importer.find_spec(fullname)
|
||||
|
||||
def test_module(self):
|
||||
self.assertTrue(self.find_spec(util.EXTENSIONS.name))
|
||||
|
||||
# No extension module as an __init__ available for testing.
|
||||
test_package = test_package_in_package = None
|
||||
|
||||
# No extension module in a package available for testing.
|
||||
test_module_in_package = None
|
||||
|
||||
# Extension modules cannot be an __init__ for a package.
|
||||
test_package_over_module = None
|
||||
|
||||
def test_failure(self):
|
||||
self.assertIsNone(self.find_spec('asdfjkl;'))
|
||||
|
||||
|
||||
(Frozen_FinderTests,
|
||||
Source_FinderTests
|
||||
) = util.test_both(FinderTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
392
Dependencies/Python/Lib/test/test_importlib/extension/test_loader.py
vendored
Normal file
392
Dependencies/Python/Lib/test/test_importlib/extension/test_loader.py
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
from test.support import is_apple_mobile
|
||||
from test.test_importlib import abc, util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
import warnings
|
||||
import importlib.util
|
||||
import importlib
|
||||
from test import support
|
||||
from test.support import MISSING_C_DOCSTRINGS, script_helper
|
||||
|
||||
|
||||
class LoaderTests:
|
||||
|
||||
"""Test ExtensionFileLoader."""
|
||||
|
||||
def setUp(self):
|
||||
if not self.machinery.EXTENSION_SUFFIXES or not util.EXTENSIONS:
|
||||
raise unittest.SkipTest("Requires dynamic loading support.")
|
||||
if util.EXTENSIONS.name in sys.builtin_module_names:
|
||||
raise unittest.SkipTest(
|
||||
f"{util.EXTENSIONS.name} is a builtin module"
|
||||
)
|
||||
|
||||
# Apple extensions must be distributed as frameworks. This requires
|
||||
# a specialist loader.
|
||||
if is_apple_mobile:
|
||||
self.LoaderClass = self.machinery.AppleFrameworkLoader
|
||||
else:
|
||||
self.LoaderClass = self.machinery.ExtensionFileLoader
|
||||
|
||||
self.loader = self.LoaderClass(util.EXTENSIONS.name, util.EXTENSIONS.file_path)
|
||||
|
||||
def load_module(self, fullname):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
return self.loader.load_module(fullname)
|
||||
|
||||
def test_equality(self):
|
||||
other = self.LoaderClass(util.EXTENSIONS.name, util.EXTENSIONS.file_path)
|
||||
self.assertEqual(self.loader, other)
|
||||
|
||||
def test_inequality(self):
|
||||
other = self.LoaderClass('_' + util.EXTENSIONS.name, util.EXTENSIONS.file_path)
|
||||
self.assertNotEqual(self.loader, other)
|
||||
|
||||
def test_load_module_API(self):
|
||||
# Test the default argument for load_module().
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
self.loader.load_module()
|
||||
self.loader.load_module(None)
|
||||
with self.assertRaises(ImportError):
|
||||
self.load_module('XXX')
|
||||
|
||||
def test_module(self):
|
||||
with util.uncache(util.EXTENSIONS.name):
|
||||
module = self.load_module(util.EXTENSIONS.name)
|
||||
for attr, value in [('__name__', util.EXTENSIONS.name),
|
||||
('__file__', util.EXTENSIONS.file_path),
|
||||
('__package__', '')]:
|
||||
self.assertEqual(getattr(module, attr), value)
|
||||
self.assertIn(util.EXTENSIONS.name, sys.modules)
|
||||
self.assertIsInstance(module.__loader__, self.LoaderClass)
|
||||
|
||||
# No extension module as __init__ available for testing.
|
||||
test_package = None
|
||||
|
||||
# No extension module in a package available for testing.
|
||||
test_lacking_parent = None
|
||||
|
||||
# No easy way to trigger a failure after a successful import.
|
||||
test_state_after_failure = None
|
||||
|
||||
def test_unloadable(self):
|
||||
name = 'asdfjkl;'
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.load_module(name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
|
||||
def test_module_reuse(self):
|
||||
with util.uncache(util.EXTENSIONS.name):
|
||||
module1 = self.load_module(util.EXTENSIONS.name)
|
||||
module2 = self.load_module(util.EXTENSIONS.name)
|
||||
self.assertIs(module1, module2)
|
||||
|
||||
def test_is_package(self):
|
||||
self.assertFalse(self.loader.is_package(util.EXTENSIONS.name))
|
||||
for suffix in self.machinery.EXTENSION_SUFFIXES:
|
||||
path = os.path.join('some', 'path', 'pkg', '__init__' + suffix)
|
||||
loader = self.LoaderClass('pkg', path)
|
||||
self.assertTrue(loader.is_package('pkg'))
|
||||
|
||||
|
||||
(Frozen_LoaderTests,
|
||||
Source_LoaderTests
|
||||
) = util.test_both(LoaderTests, machinery=machinery)
|
||||
|
||||
|
||||
class SinglePhaseExtensionModuleTests(abc.LoaderTests):
|
||||
# Test loading extension modules without multi-phase initialization.
|
||||
|
||||
def setUp(self):
|
||||
if not self.machinery.EXTENSION_SUFFIXES or not util.EXTENSIONS:
|
||||
raise unittest.SkipTest("Requires dynamic loading support.")
|
||||
|
||||
# Apple extensions must be distributed as frameworks. This requires
|
||||
# a specialist loader.
|
||||
if is_apple_mobile:
|
||||
self.LoaderClass = self.machinery.AppleFrameworkLoader
|
||||
else:
|
||||
self.LoaderClass = self.machinery.ExtensionFileLoader
|
||||
|
||||
self.name = '_testsinglephase'
|
||||
if self.name in sys.builtin_module_names:
|
||||
raise unittest.SkipTest(
|
||||
f"{self.name} is a builtin module"
|
||||
)
|
||||
finder = self.machinery.FileFinder(None)
|
||||
self.spec = importlib.util.find_spec(self.name)
|
||||
assert self.spec
|
||||
|
||||
self.loader = self.LoaderClass(self.name, self.spec.origin)
|
||||
|
||||
def load_module(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
return self.loader.load_module(self.name)
|
||||
|
||||
def load_module_by_name(self, fullname):
|
||||
# Load a module from the test extension by name.
|
||||
origin = self.spec.origin
|
||||
loader = self.LoaderClass(fullname, origin)
|
||||
spec = importlib.util.spec_from_loader(fullname, loader)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
loader.exec_module(module)
|
||||
return module
|
||||
|
||||
def test_module(self):
|
||||
# Test loading an extension module.
|
||||
with util.uncache(self.name):
|
||||
module = self.load_module()
|
||||
for attr, value in [('__name__', self.name),
|
||||
('__file__', self.spec.origin),
|
||||
('__package__', '')]:
|
||||
self.assertEqual(getattr(module, attr), value)
|
||||
with self.assertRaises(AttributeError):
|
||||
module.__path__
|
||||
self.assertIs(module, sys.modules[self.name])
|
||||
self.assertIsInstance(module.__loader__, self.LoaderClass)
|
||||
|
||||
# No extension module as __init__ available for testing.
|
||||
test_package = None
|
||||
|
||||
# No extension module in a package available for testing.
|
||||
test_lacking_parent = None
|
||||
|
||||
# No easy way to trigger a failure after a successful import.
|
||||
test_state_after_failure = None
|
||||
|
||||
def test_unloadable(self):
|
||||
name = 'asdfjkl;'
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.load_module_by_name(name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
|
||||
def test_unloadable_nonascii(self):
|
||||
# Test behavior with nonexistent module with non-ASCII name.
|
||||
name = 'fo\xf3'
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.load_module_by_name(name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
|
||||
# It may make sense to add the equivalent to
|
||||
# the following MultiPhaseExtensionModuleTests tests:
|
||||
#
|
||||
# * test_nonmodule
|
||||
# * test_nonmodule_with_methods
|
||||
# * test_bad_modules
|
||||
# * test_nonascii
|
||||
|
||||
|
||||
(Frozen_SinglePhaseExtensionModuleTests,
|
||||
Source_SinglePhaseExtensionModuleTests
|
||||
) = util.test_both(SinglePhaseExtensionModuleTests, machinery=machinery)
|
||||
|
||||
|
||||
class MultiPhaseExtensionModuleTests(abc.LoaderTests):
|
||||
# Test loading extension modules with multi-phase initialization (PEP 489).
|
||||
|
||||
def setUp(self):
|
||||
if not self.machinery.EXTENSION_SUFFIXES or not util.EXTENSIONS:
|
||||
raise unittest.SkipTest("Requires dynamic loading support.")
|
||||
|
||||
# Apple extensions must be distributed as frameworks. This requires
|
||||
# a specialist loader.
|
||||
if is_apple_mobile:
|
||||
self.LoaderClass = self.machinery.AppleFrameworkLoader
|
||||
else:
|
||||
self.LoaderClass = self.machinery.ExtensionFileLoader
|
||||
|
||||
self.name = '_testmultiphase'
|
||||
if self.name in sys.builtin_module_names:
|
||||
raise unittest.SkipTest(
|
||||
f"{self.name} is a builtin module"
|
||||
)
|
||||
finder = self.machinery.FileFinder(None)
|
||||
self.spec = importlib.util.find_spec(self.name)
|
||||
assert self.spec
|
||||
self.loader = self.LoaderClass(self.name, self.spec.origin)
|
||||
|
||||
def load_module(self):
|
||||
# Load the module from the test extension.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
return self.loader.load_module(self.name)
|
||||
|
||||
def load_module_by_name(self, fullname):
|
||||
# Load a module from the test extension by name.
|
||||
origin = self.spec.origin
|
||||
loader = self.LoaderClass(fullname, origin)
|
||||
spec = importlib.util.spec_from_loader(fullname, loader)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
loader.exec_module(module)
|
||||
return module
|
||||
|
||||
# No extension module as __init__ available for testing.
|
||||
test_package = None
|
||||
|
||||
# No extension module in a package available for testing.
|
||||
test_lacking_parent = None
|
||||
|
||||
# Handling failure on reload is the up to the module.
|
||||
test_state_after_failure = None
|
||||
|
||||
def test_module(self):
|
||||
# Test loading an extension module.
|
||||
with util.uncache(self.name):
|
||||
module = self.load_module()
|
||||
for attr, value in [('__name__', self.name),
|
||||
('__file__', self.spec.origin),
|
||||
('__package__', '')]:
|
||||
self.assertEqual(getattr(module, attr), value)
|
||||
with self.assertRaises(AttributeError):
|
||||
module.__path__
|
||||
self.assertIs(module, sys.modules[self.name])
|
||||
self.assertIsInstance(module.__loader__, self.LoaderClass)
|
||||
|
||||
def test_functionality(self):
|
||||
# Test basic functionality of stuff defined in an extension module.
|
||||
with util.uncache(self.name):
|
||||
module = self.load_module()
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
ex = module.Example()
|
||||
self.assertEqual(ex.demo('abcd'), 'abcd')
|
||||
self.assertEqual(ex.demo(), None)
|
||||
with self.assertRaises(AttributeError):
|
||||
ex.abc
|
||||
ex.abc = 0
|
||||
self.assertEqual(ex.abc, 0)
|
||||
self.assertEqual(module.foo(9, 9), 18)
|
||||
self.assertIsInstance(module.Str(), str)
|
||||
self.assertEqual(module.Str(1) + '23', '123')
|
||||
with self.assertRaises(module.error):
|
||||
raise module.error()
|
||||
self.assertEqual(module.int_const, 1969)
|
||||
self.assertEqual(module.str_const, 'something different')
|
||||
|
||||
def test_reload(self):
|
||||
# Test that reload didn't re-set the module's attributes.
|
||||
with util.uncache(self.name):
|
||||
module = self.load_module()
|
||||
ex_class = module.Example
|
||||
importlib.reload(module)
|
||||
self.assertIs(ex_class, module.Example)
|
||||
|
||||
def test_try_registration(self):
|
||||
# Assert that the PyState_{Find,Add,Remove}Module C API doesn't work.
|
||||
with util.uncache(self.name):
|
||||
module = self.load_module()
|
||||
with self.subTest('PyState_FindModule'):
|
||||
self.assertEqual(module.call_state_registration_func(0), None)
|
||||
with self.subTest('PyState_AddModule'):
|
||||
with self.assertRaises(SystemError):
|
||||
module.call_state_registration_func(1)
|
||||
with self.subTest('PyState_RemoveModule'):
|
||||
with self.assertRaises(SystemError):
|
||||
module.call_state_registration_func(2)
|
||||
|
||||
def test_load_submodule(self):
|
||||
# Test loading a simulated submodule.
|
||||
module = self.load_module_by_name('pkg.' + self.name)
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
self.assertEqual(module.__name__, 'pkg.' + self.name)
|
||||
self.assertEqual(module.str_const, 'something different')
|
||||
|
||||
def test_load_short_name(self):
|
||||
# Test loading module with a one-character name.
|
||||
module = self.load_module_by_name('x')
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
self.assertEqual(module.__name__, 'x')
|
||||
self.assertEqual(module.str_const, 'something different')
|
||||
self.assertNotIn('x', sys.modules)
|
||||
|
||||
def test_load_twice(self):
|
||||
# Test that 2 loads result in 2 module objects.
|
||||
module1 = self.load_module_by_name(self.name)
|
||||
module2 = self.load_module_by_name(self.name)
|
||||
self.assertIsNot(module1, module2)
|
||||
|
||||
def test_unloadable(self):
|
||||
# Test nonexistent module.
|
||||
name = 'asdfjkl;'
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.load_module_by_name(name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
|
||||
def test_unloadable_nonascii(self):
|
||||
# Test behavior with nonexistent module with non-ASCII name.
|
||||
name = 'fo\xf3'
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.load_module_by_name(name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
|
||||
def test_bad_modules(self):
|
||||
# Test SystemError is raised for misbehaving extensions.
|
||||
for name_base in [
|
||||
'bad_slot_large',
|
||||
'bad_slot_negative',
|
||||
'create_int_with_state',
|
||||
'negative_size',
|
||||
'export_null',
|
||||
'export_uninitialized',
|
||||
'export_raise',
|
||||
'export_unreported_exception',
|
||||
'create_null',
|
||||
'create_raise',
|
||||
'create_unreported_exception',
|
||||
'nonmodule_with_exec_slots',
|
||||
'exec_err',
|
||||
'exec_raise',
|
||||
'exec_unreported_exception',
|
||||
'multiple_create_slots',
|
||||
'multiple_multiple_interpreters_slots',
|
||||
]:
|
||||
with self.subTest(name_base):
|
||||
name = self.name + '_' + name_base
|
||||
with self.assertRaises(SystemError) as cm:
|
||||
self.load_module_by_name(name)
|
||||
|
||||
# If there is an unreported exception, it should be chained
|
||||
# with the `SystemError`.
|
||||
if "unreported_exception" in name_base:
|
||||
self.assertIsNotNone(cm.exception.__cause__)
|
||||
|
||||
def test_nonascii(self):
|
||||
# Test that modules with non-ASCII names can be loaded.
|
||||
# punycode behaves slightly differently in some-ASCII and no-ASCII
|
||||
# cases, so test both.
|
||||
cases = [
|
||||
(self.name + '_zkou\u0161ka_na\u010dten\xed', 'Czech'),
|
||||
('\uff3f\u30a4\u30f3\u30dd\u30fc\u30c8\u30c6\u30b9\u30c8',
|
||||
'Japanese'),
|
||||
]
|
||||
for name, lang in cases:
|
||||
with self.subTest(name):
|
||||
module = self.load_module_by_name(name)
|
||||
self.assertEqual(module.__name__, name)
|
||||
if not MISSING_C_DOCSTRINGS:
|
||||
self.assertEqual(module.__doc__, "Module named in %s" % lang)
|
||||
|
||||
|
||||
(Frozen_MultiPhaseExtensionModuleTests,
|
||||
Source_MultiPhaseExtensionModuleTests
|
||||
) = util.test_both(MultiPhaseExtensionModuleTests, machinery=machinery)
|
||||
|
||||
|
||||
class NonModuleExtensionTests(unittest.TestCase):
|
||||
def test_nonmodule_cases(self):
|
||||
# The test cases in this file cause the GIL to be enabled permanently
|
||||
# in free-threaded builds, so they are run in a subprocess to isolate
|
||||
# this effect.
|
||||
script = support.findfile("test_importlib/extension/_test_nonmodule_cases.py")
|
||||
script_helper.run_test_script(script)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
33
Dependencies/Python/Lib/test/test_importlib/extension/test_path_hook.py
vendored
Normal file
33
Dependencies/Python/Lib/test/test_importlib/extension/test_path_hook.py
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
from test.test_importlib import util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
@unittest.skipIf(util.EXTENSIONS is None or util.EXTENSIONS.filename is None,
|
||||
'dynamic loading not supported or test module not available')
|
||||
class PathHookTests:
|
||||
|
||||
"""Test the path hook for extension modules."""
|
||||
# XXX Should it only succeed for pre-existing directories?
|
||||
# XXX Should it only work for directories containing an extension module?
|
||||
|
||||
def hook(self, entry):
|
||||
return self.machinery.FileFinder.path_hook(
|
||||
(self.machinery.ExtensionFileLoader,
|
||||
self.machinery.EXTENSION_SUFFIXES))(entry)
|
||||
|
||||
def test_success(self):
|
||||
# Path hook should handle a directory where a known extension module
|
||||
# exists.
|
||||
self.assertHasAttr(self.hook(util.EXTENSIONS.path), 'find_spec')
|
||||
|
||||
|
||||
(Frozen_PathHooksTests,
|
||||
Source_PathHooksTests
|
||||
) = util.test_both(PathHookTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
5
Dependencies/Python/Lib/test/test_importlib/frozen/__init__.py
vendored
Normal file
5
Dependencies/Python/Lib/test/test_importlib/frozen/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
from test.support import load_package_tests
|
||||
|
||||
def load_tests(*args):
|
||||
return load_package_tests(os.path.dirname(__file__), *args)
|
||||
4
Dependencies/Python/Lib/test/test_importlib/frozen/__main__.py
vendored
Normal file
4
Dependencies/Python/Lib/test/test_importlib/frozen/__main__.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
from . import load_tests
|
||||
import unittest
|
||||
|
||||
unittest.main()
|
||||
183
Dependencies/Python/Lib/test/test_importlib/frozen/test_finder.py
vendored
Normal file
183
Dependencies/Python/Lib/test/test_importlib/frozen/test_finder.py
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
from test.test_importlib import abc, util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import os.path
|
||||
import unittest
|
||||
|
||||
from test.support import import_helper, REPO_ROOT, STDLIB_DIR
|
||||
|
||||
|
||||
def resolve_stdlib_file(name, ispkg=False):
|
||||
assert name
|
||||
if ispkg:
|
||||
return os.path.join(STDLIB_DIR, *name.split('.'), '__init__.py')
|
||||
else:
|
||||
return os.path.join(STDLIB_DIR, *name.split('.')) + '.py'
|
||||
|
||||
|
||||
class FindSpecTests(abc.FinderTests):
|
||||
|
||||
"""Test finding frozen modules."""
|
||||
|
||||
def find(self, name, **kwargs):
|
||||
finder = self.machinery.FrozenImporter
|
||||
with import_helper.frozen_modules():
|
||||
return finder.find_spec(name, **kwargs)
|
||||
|
||||
def check_basic(self, spec, name, ispkg=False):
|
||||
self.assertEqual(spec.name, name)
|
||||
self.assertIs(spec.loader, self.machinery.FrozenImporter)
|
||||
self.assertEqual(spec.origin, 'frozen')
|
||||
self.assertFalse(spec.has_location)
|
||||
if ispkg:
|
||||
self.assertIsNotNone(spec.submodule_search_locations)
|
||||
else:
|
||||
self.assertIsNone(spec.submodule_search_locations)
|
||||
self.assertIsNotNone(spec.loader_state)
|
||||
|
||||
def check_loader_state(self, spec, origname=None, filename=None):
|
||||
if not filename:
|
||||
if not origname:
|
||||
origname = spec.name
|
||||
filename = resolve_stdlib_file(origname)
|
||||
|
||||
actual = dict(vars(spec.loader_state))
|
||||
|
||||
# Check the rest of spec.loader_state.
|
||||
expected = dict(
|
||||
origname=origname,
|
||||
filename=filename if origname else None,
|
||||
)
|
||||
self.assertDictEqual(actual, expected)
|
||||
|
||||
def check_search_locations(self, spec):
|
||||
"""This is only called when testing packages."""
|
||||
missing = object()
|
||||
filename = getattr(spec.loader_state, 'filename', missing)
|
||||
origname = getattr(spec.loader_state, 'origname', None)
|
||||
if not origname or filename is missing:
|
||||
# We deal with this in check_loader_state().
|
||||
return
|
||||
if not filename:
|
||||
expected = []
|
||||
elif origname != spec.name and not origname.startswith('<'):
|
||||
expected = []
|
||||
else:
|
||||
expected = [os.path.dirname(filename)]
|
||||
self.assertListEqual(spec.submodule_search_locations, expected)
|
||||
|
||||
def test_module(self):
|
||||
modules = [
|
||||
'__hello__',
|
||||
'__phello__.spam',
|
||||
'__phello__.ham.eggs',
|
||||
]
|
||||
for name in modules:
|
||||
with self.subTest(f'{name} -> {name}'):
|
||||
spec = self.find(name)
|
||||
self.check_basic(spec, name)
|
||||
self.check_loader_state(spec)
|
||||
modules = {
|
||||
'__hello_alias__': '__hello__',
|
||||
'_frozen_importlib': 'importlib._bootstrap',
|
||||
}
|
||||
for name, origname in modules.items():
|
||||
with self.subTest(f'{name} -> {origname}'):
|
||||
spec = self.find(name)
|
||||
self.check_basic(spec, name)
|
||||
self.check_loader_state(spec, origname)
|
||||
modules = [
|
||||
'__phello__.__init__',
|
||||
'__phello__.ham.__init__',
|
||||
]
|
||||
for name in modules:
|
||||
origname = '<' + name.rpartition('.')[0]
|
||||
filename = resolve_stdlib_file(name)
|
||||
with self.subTest(f'{name} -> {origname}'):
|
||||
spec = self.find(name)
|
||||
self.check_basic(spec, name)
|
||||
self.check_loader_state(spec, origname, filename)
|
||||
modules = {
|
||||
'__hello_only__': ('Tools', 'freeze', 'flag.py'),
|
||||
}
|
||||
for name, path in modules.items():
|
||||
origname = None
|
||||
filename = os.path.join(REPO_ROOT, *path)
|
||||
with self.subTest(f'{name} -> {filename}'):
|
||||
spec = self.find(name)
|
||||
self.check_basic(spec, name)
|
||||
self.check_loader_state(spec, origname, filename)
|
||||
|
||||
def test_package(self):
|
||||
packages = [
|
||||
'__phello__',
|
||||
'__phello__.ham',
|
||||
]
|
||||
for name in packages:
|
||||
filename = resolve_stdlib_file(name, ispkg=True)
|
||||
with self.subTest(f'{name} -> {name}'):
|
||||
spec = self.find(name)
|
||||
self.check_basic(spec, name, ispkg=True)
|
||||
self.check_loader_state(spec, name, filename)
|
||||
self.check_search_locations(spec)
|
||||
packages = {
|
||||
'__phello_alias__': '__hello__',
|
||||
}
|
||||
for name, origname in packages.items():
|
||||
filename = resolve_stdlib_file(origname, ispkg=False)
|
||||
with self.subTest(f'{name} -> {origname}'):
|
||||
spec = self.find(name)
|
||||
self.check_basic(spec, name, ispkg=True)
|
||||
self.check_loader_state(spec, origname, filename)
|
||||
self.check_search_locations(spec)
|
||||
|
||||
# These are covered by test_module() and test_package().
|
||||
test_module_in_package = None
|
||||
test_package_in_package = None
|
||||
|
||||
# No easy way to test.
|
||||
test_package_over_module = None
|
||||
|
||||
def test_path_ignored(self):
|
||||
for name in ('__hello__', '__phello__', '__phello__.spam'):
|
||||
actual = self.find(name)
|
||||
for path in (None, object(), '', 'eggs', [], [''], ['eggs']):
|
||||
with self.subTest((name, path)):
|
||||
spec = self.find(name, path=path)
|
||||
self.assertEqual(spec, actual)
|
||||
|
||||
def test_target_ignored(self):
|
||||
imported = ('__hello__', '__phello__')
|
||||
with import_helper.CleanImport(*imported, usefrozen=True):
|
||||
import __hello__ as match
|
||||
import __phello__ as nonmatch
|
||||
name = '__hello__'
|
||||
actual = self.find(name)
|
||||
for target in (None, match, nonmatch, object(), 'not-a-module-object'):
|
||||
with self.subTest(target):
|
||||
spec = self.find(name, target=target)
|
||||
self.assertEqual(spec, actual)
|
||||
|
||||
def test_failure(self):
|
||||
spec = self.find('<not real>')
|
||||
self.assertIsNone(spec)
|
||||
|
||||
def test_not_using_frozen(self):
|
||||
finder = self.machinery.FrozenImporter
|
||||
with import_helper.frozen_modules(enabled=False):
|
||||
# both frozen and not frozen
|
||||
spec1 = finder.find_spec('__hello__')
|
||||
# only frozen
|
||||
spec2 = finder.find_spec('__hello_only__')
|
||||
self.assertIsNone(spec1)
|
||||
self.assertIsNone(spec2)
|
||||
|
||||
|
||||
(Frozen_FindSpecTests,
|
||||
Source_FindSpecTests
|
||||
) = util.test_both(FindSpecTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
172
Dependencies/Python/Lib/test/test_importlib/frozen/test_loader.py
vendored
Normal file
172
Dependencies/Python/Lib/test/test_importlib/frozen/test_loader.py
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
from test.test_importlib import abc, util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
from test.support import captured_stdout, import_helper, STDLIB_DIR
|
||||
import contextlib
|
||||
import os.path
|
||||
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():
|
||||
if oldapi:
|
||||
with deprecated():
|
||||
yield
|
||||
else:
|
||||
yield
|
||||
|
||||
|
||||
def resolve_stdlib_file(name, ispkg=False):
|
||||
assert name
|
||||
if ispkg:
|
||||
return os.path.join(STDLIB_DIR, *name.split('.'), '__init__.py')
|
||||
else:
|
||||
return os.path.join(STDLIB_DIR, *name.split('.')) + '.py'
|
||||
|
||||
|
||||
class ExecModuleTests(abc.LoaderTests):
|
||||
|
||||
def exec_module(self, name, origname=None):
|
||||
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,
|
||||
loader_state=types.SimpleNamespace(
|
||||
origname=origname or name,
|
||||
filename=resolve_stdlib_file(origname or name, is_package),
|
||||
),
|
||||
)
|
||||
module = types.ModuleType(name)
|
||||
module.__spec__ = spec
|
||||
assert not hasattr(module, 'initialized')
|
||||
|
||||
with fresh(name):
|
||||
self.machinery.FrozenImporter.exec_module(module)
|
||||
with captured_stdout() as stdout:
|
||||
module.main()
|
||||
|
||||
self.assertTrue(module.initialized)
|
||||
self.assertHasAttr(module, '__spec__')
|
||||
self.assertEqual(module.__spec__.origin, 'frozen')
|
||||
return module, stdout.getvalue()
|
||||
|
||||
def test_module(self):
|
||||
name = '__hello__'
|
||||
module, output = self.exec_module(name)
|
||||
check = {'__name__': name}
|
||||
for attr, value in check.items():
|
||||
self.assertEqual(getattr(module, attr), value)
|
||||
self.assertEqual(output, 'Hello world!\n')
|
||||
self.assertHasAttr(module, '__spec__')
|
||||
self.assertEqual(module.__spec__.loader_state.origname, name)
|
||||
|
||||
def test_package(self):
|
||||
name = '__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!r} != {expected!r}'.format(
|
||||
name=name, attr=attr, given=attr_value,
|
||||
expected=value))
|
||||
self.assertEqual(output, 'Hello world!\n')
|
||||
self.assertEqual(module.__spec__.loader_state.origname, name)
|
||||
|
||||
def test_lacking_parent(self):
|
||||
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')
|
||||
|
||||
def test_module_repr_indirect_through_spec(self):
|
||||
name = '__hello__'
|
||||
module, output = self.exec_module(name)
|
||||
self.assertEqual(repr(module),
|
||||
"<module '__hello__' (frozen)>")
|
||||
|
||||
# No way to trigger an error in a frozen module.
|
||||
test_state_after_failure = None
|
||||
|
||||
def test_unloadable(self):
|
||||
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')
|
||||
|
||||
|
||||
(Frozen_ExecModuleTests,
|
||||
Source_ExecModuleTests
|
||||
) = util.test_both(ExecModuleTests, machinery=machinery)
|
||||
|
||||
|
||||
class InspectLoaderTests:
|
||||
|
||||
"""Tests for the InspectLoader methods for FrozenImporter."""
|
||||
|
||||
def test_get_code(self):
|
||||
# Make sure that the code object is good.
|
||||
name = '__hello__'
|
||||
with import_helper.frozen_modules():
|
||||
code = self.machinery.FrozenImporter.get_code(name)
|
||||
mod = types.ModuleType(name)
|
||||
exec(code, mod.__dict__)
|
||||
with captured_stdout() as stdout:
|
||||
mod.main()
|
||||
self.assertHasAttr(mod, 'initialized')
|
||||
self.assertEqual(stdout.getvalue(), 'Hello world!\n')
|
||||
|
||||
def test_get_source(self):
|
||||
# Should always return None.
|
||||
with import_helper.frozen_modules():
|
||||
result = self.machinery.FrozenImporter.get_source('__hello__')
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_is_package(self):
|
||||
# Should be able to tell what is a package.
|
||||
test_for = (('__hello__', False), ('__phello__', True),
|
||||
('__phello__.spam', False))
|
||||
for name, is_package in test_for:
|
||||
with import_helper.frozen_modules():
|
||||
result = self.machinery.FrozenImporter.is_package(name)
|
||||
self.assertEqual(bool(result), is_package)
|
||||
|
||||
def test_failure(self):
|
||||
# Raise ImportError for modules that are not frozen.
|
||||
for meth_name in ('get_code', 'get_source', 'is_package'):
|
||||
method = getattr(self.machinery.FrozenImporter, meth_name)
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
with import_helper.frozen_modules():
|
||||
method('importlib')
|
||||
self.assertEqual(cm.exception.name, 'importlib')
|
||||
|
||||
(Frozen_ILTests,
|
||||
Source_ILTests
|
||||
) = util.test_both(InspectLoaderTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
5
Dependencies/Python/Lib/test/test_importlib/import_/__init__.py
vendored
Normal file
5
Dependencies/Python/Lib/test/test_importlib/import_/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
from test.support import load_package_tests
|
||||
|
||||
def load_tests(*args):
|
||||
return load_package_tests(os.path.dirname(__file__), *args)
|
||||
4
Dependencies/Python/Lib/test/test_importlib/import_/__main__.py
vendored
Normal file
4
Dependencies/Python/Lib/test/test_importlib/import_/__main__.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
from . import load_tests
|
||||
import unittest
|
||||
|
||||
unittest.main()
|
||||
34
Dependencies/Python/Lib/test/test_importlib/import_/test___loader__.py
vendored
Normal file
34
Dependencies/Python/Lib/test/test_importlib/import_/test___loader__.py
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
from importlib import machinery
|
||||
import unittest
|
||||
|
||||
from test.test_importlib import util
|
||||
|
||||
|
||||
class SpecLoaderMock:
|
||||
|
||||
def find_spec(self, fullname, path=None, target=None):
|
||||
return machinery.ModuleSpec(fullname, self)
|
||||
|
||||
def create_module(self, spec):
|
||||
return None
|
||||
|
||||
def exec_module(self, module):
|
||||
pass
|
||||
|
||||
|
||||
class SpecLoaderAttributeTests:
|
||||
|
||||
def test___loader__(self):
|
||||
loader = SpecLoaderMock()
|
||||
with util.uncache('blah'), util.import_state(meta_path=[loader]):
|
||||
module = self.__import__('blah')
|
||||
self.assertEqual(loader, module.__loader__)
|
||||
|
||||
|
||||
(Frozen_SpecTests,
|
||||
Source_SpecTests
|
||||
) = util.test_both(SpecLoaderAttributeTests, __import__=util.__import__)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
152
Dependencies/Python/Lib/test/test_importlib/import_/test___package__.py
vendored
Normal file
152
Dependencies/Python/Lib/test/test_importlib/import_/test___package__.py
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
"""PEP 366 ("Main module explicit relative imports") specifies the
|
||||
semantics for the __package__ attribute on modules. This attribute is
|
||||
used, when available, to detect which package a module belongs to (instead
|
||||
of using the typical __path__/__name__ test).
|
||||
|
||||
"""
|
||||
import unittest
|
||||
import warnings
|
||||
from test.test_importlib import util
|
||||
|
||||
|
||||
class Using__package__:
|
||||
|
||||
"""Use of __package__ supersedes the use of __name__/__path__ to calculate
|
||||
what package a module belongs to. The basic algorithm is [__package__]::
|
||||
|
||||
def resolve_name(name, package, level):
|
||||
level -= 1
|
||||
base = package.rsplit('.', level)[0]
|
||||
return '{0}.{1}'.format(base, name)
|
||||
|
||||
But since there is no guarantee that __package__ has been set (or not been
|
||||
set to None [None]), there has to be a way to calculate the attribute's value
|
||||
[__name__]::
|
||||
|
||||
def calc_package(caller_name, has___path__):
|
||||
if has__path__:
|
||||
return caller_name
|
||||
else:
|
||||
return caller_name.rsplit('.', 1)[0]
|
||||
|
||||
Then the normal algorithm for relative name imports can proceed as if
|
||||
__package__ had been set.
|
||||
|
||||
"""
|
||||
|
||||
def import_module(self, globals_):
|
||||
with self.mock_modules('pkg.__init__', 'pkg.fake') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
self.__import__('pkg.fake')
|
||||
module = self.__import__('',
|
||||
globals=globals_,
|
||||
fromlist=['attr'], level=2)
|
||||
return module
|
||||
|
||||
def test_using___package__(self):
|
||||
# [__package__]
|
||||
module = self.import_module({'__package__': 'pkg.fake'})
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
|
||||
def test_using___name__(self):
|
||||
# [__name__]
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
module = self.import_module({'__name__': 'pkg.fake',
|
||||
'__path__': []})
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
|
||||
def test_warn_when_using___name__(self):
|
||||
with self.assertWarns(ImportWarning):
|
||||
self.import_module({'__name__': 'pkg.fake', '__path__': []})
|
||||
|
||||
def test_None_as___package__(self):
|
||||
# [None]
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
module = self.import_module({
|
||||
'__name__': 'pkg.fake', '__path__': [], '__package__': None })
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
|
||||
def test_spec_fallback(self):
|
||||
# If __package__ isn't defined, fall back on __spec__.parent.
|
||||
module = self.import_module({'__spec__': FakeSpec('pkg.fake')})
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
|
||||
def test_warn_when_package_and_spec_disagree(self):
|
||||
# Raise a DeprecationWarning if __package__ != __spec__.parent.
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.import_module({'__package__': 'pkg.fake',
|
||||
'__spec__': FakeSpec('pkg.fakefake')})
|
||||
|
||||
def test_bad__package__(self):
|
||||
globals = {'__package__': '<not real>'}
|
||||
with self.assertRaises(ModuleNotFoundError):
|
||||
self.__import__('', globals, {}, ['relimport'], 1)
|
||||
|
||||
def test_bunk__package__(self):
|
||||
globals = {'__package__': 42}
|
||||
with self.assertRaises(TypeError):
|
||||
self.__import__('', globals, {}, ['relimport'], 1)
|
||||
|
||||
|
||||
class FakeSpec:
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
|
||||
|
||||
class Using__package__PEP451(Using__package__):
|
||||
mock_modules = util.mock_spec
|
||||
|
||||
|
||||
(Frozen_UsingPackagePEP451,
|
||||
Source_UsingPackagePEP451
|
||||
) = util.test_both(Using__package__PEP451, __import__=util.__import__)
|
||||
|
||||
|
||||
class Setting__package__:
|
||||
|
||||
"""Because __package__ is a new feature, it is not always set by a loader.
|
||||
Import will set it as needed to help with the transition to relying on
|
||||
__package__.
|
||||
|
||||
For a top-level module, __package__ is set to None [top-level]. For a
|
||||
package __name__ is used for __package__ [package]. For submodules the
|
||||
value is __name__.rsplit('.', 1)[0] [submodule].
|
||||
|
||||
"""
|
||||
|
||||
__import__ = util.__import__['Source']
|
||||
|
||||
# [top-level]
|
||||
def test_top_level(self):
|
||||
with self.mock_modules('top_level') as mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
del mock['top_level'].__package__
|
||||
module = self.__import__('top_level')
|
||||
self.assertEqual(module.__package__, '')
|
||||
|
||||
# [package]
|
||||
def test_package(self):
|
||||
with self.mock_modules('pkg.__init__') as mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
del mock['pkg'].__package__
|
||||
module = self.__import__('pkg')
|
||||
self.assertEqual(module.__package__, 'pkg')
|
||||
|
||||
# [submodule]
|
||||
def test_submodule(self):
|
||||
with self.mock_modules('pkg.__init__', 'pkg.mod') as mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
del mock['pkg.mod'].__package__
|
||||
pkg = self.__import__('pkg.mod')
|
||||
module = getattr(pkg, 'mod')
|
||||
self.assertEqual(module.__package__, 'pkg')
|
||||
|
||||
|
||||
class Setting__package__PEP451(Setting__package__, unittest.TestCase):
|
||||
mock_modules = util.mock_spec
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
145
Dependencies/Python/Lib/test/test_importlib/import_/test_api.py
vendored
Normal file
145
Dependencies/Python/Lib/test/test_importlib/import_/test_api.py
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
from test.test_importlib import util
|
||||
|
||||
from importlib import machinery
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
PKG_NAME = 'fine'
|
||||
SUBMOD_NAME = 'fine.bogus'
|
||||
|
||||
|
||||
class BadSpecFinderLoader:
|
||||
@classmethod
|
||||
def find_spec(cls, fullname, path=None, target=None):
|
||||
if fullname == SUBMOD_NAME:
|
||||
spec = machinery.ModuleSpec(fullname, cls)
|
||||
return spec
|
||||
|
||||
@staticmethod
|
||||
def create_module(spec):
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def exec_module(module):
|
||||
if module.__name__ == SUBMOD_NAME:
|
||||
raise ImportError('I cannot be loaded!')
|
||||
|
||||
|
||||
class BadLoaderFinder:
|
||||
@classmethod
|
||||
def load_module(cls, fullname):
|
||||
if fullname == SUBMOD_NAME:
|
||||
raise ImportError('I cannot be loaded!')
|
||||
|
||||
|
||||
class APITest:
|
||||
|
||||
"""Test API-specific details for __import__ (e.g. raising the right
|
||||
exception when passing in an int for the module name)."""
|
||||
|
||||
def test_raises_ModuleNotFoundError(self):
|
||||
with self.assertRaises(ModuleNotFoundError):
|
||||
util.import_importlib('some module that does not exist')
|
||||
|
||||
def test_name_requires_rparition(self):
|
||||
# Raise TypeError if a non-string is passed in for the module name.
|
||||
with self.assertRaises(TypeError):
|
||||
self.__import__(42)
|
||||
|
||||
def test_negative_level(self):
|
||||
# Raise ValueError when a negative level is specified.
|
||||
# PEP 328 did away with sys.module None entries and the ambiguity of
|
||||
# absolute/relative imports.
|
||||
with self.assertRaises(ValueError):
|
||||
self.__import__('os', globals(), level=-1)
|
||||
|
||||
def test_nonexistent_fromlist_entry(self):
|
||||
# If something in fromlist doesn't exist, that's okay.
|
||||
# issue15715
|
||||
mod = types.ModuleType(PKG_NAME)
|
||||
mod.__path__ = ['XXX']
|
||||
with util.import_state(meta_path=[self.bad_finder_loader]):
|
||||
with util.uncache(PKG_NAME):
|
||||
sys.modules[PKG_NAME] = mod
|
||||
self.__import__(PKG_NAME, fromlist=['not here'])
|
||||
|
||||
def test_fromlist_load_error_propagates(self):
|
||||
# If something in fromlist triggers an exception not related to not
|
||||
# existing, let that exception propagate.
|
||||
# issue15316
|
||||
mod = types.ModuleType(PKG_NAME)
|
||||
mod.__path__ = ['XXX']
|
||||
with util.import_state(meta_path=[self.bad_finder_loader]):
|
||||
with util.uncache(PKG_NAME):
|
||||
sys.modules[PKG_NAME] = mod
|
||||
with self.assertRaises(ImportError):
|
||||
self.__import__(PKG_NAME,
|
||||
fromlist=[SUBMOD_NAME.rpartition('.')[-1]])
|
||||
|
||||
def test_blocked_fromlist(self):
|
||||
# If fromlist entry is None, let a ModuleNotFoundError propagate.
|
||||
# issue31642
|
||||
mod = types.ModuleType(PKG_NAME)
|
||||
mod.__path__ = []
|
||||
with util.import_state(meta_path=[self.bad_finder_loader]):
|
||||
with util.uncache(PKG_NAME, SUBMOD_NAME):
|
||||
sys.modules[PKG_NAME] = mod
|
||||
sys.modules[SUBMOD_NAME] = None
|
||||
with self.assertRaises(ModuleNotFoundError) as cm:
|
||||
self.__import__(PKG_NAME,
|
||||
fromlist=[SUBMOD_NAME.rpartition('.')[-1]])
|
||||
self.assertEqual(cm.exception.name, SUBMOD_NAME)
|
||||
|
||||
|
||||
class OldAPITests(APITest):
|
||||
bad_finder_loader = BadLoaderFinder
|
||||
|
||||
def test_raises_ModuleNotFoundError(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
super().test_raises_ModuleNotFoundError()
|
||||
|
||||
def test_name_requires_rparition(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
super().test_name_requires_rparition()
|
||||
|
||||
def test_negative_level(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
super().test_negative_level()
|
||||
|
||||
def test_nonexistent_fromlist_entry(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
super().test_nonexistent_fromlist_entry()
|
||||
|
||||
def test_fromlist_load_error_propagates(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
super().test_fromlist_load_error_propagates
|
||||
|
||||
def test_blocked_fromlist(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
super().test_blocked_fromlist()
|
||||
|
||||
|
||||
(Frozen_OldAPITests,
|
||||
Source_OldAPITests
|
||||
) = util.test_both(OldAPITests, __import__=util.__import__)
|
||||
|
||||
|
||||
class SpecAPITests(APITest):
|
||||
bad_finder_loader = BadSpecFinderLoader
|
||||
|
||||
|
||||
(Frozen_SpecAPITests,
|
||||
Source_SpecAPITests
|
||||
) = util.test_both(SpecAPITests, __import__=util.__import__)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
98
Dependencies/Python/Lib/test/test_importlib/import_/test_caching.py
vendored
Normal file
98
Dependencies/Python/Lib/test/test_importlib/import_/test_caching.py
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
"""Test that sys.modules is used properly by import."""
|
||||
from test.test_importlib import util
|
||||
from test.support.testcase import ExtraAssertions
|
||||
import sys
|
||||
from types import MethodType
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
|
||||
class UseCache:
|
||||
|
||||
"""When it comes to sys.modules, import prefers it over anything else.
|
||||
|
||||
Once a name has been resolved, sys.modules is checked to see if it contains
|
||||
the module desired. If so, then it is returned [use cache]. If it is not
|
||||
found, then the proper steps are taken to perform the import, but
|
||||
sys.modules is still used to return the imported module (e.g., not what a
|
||||
loader returns) [from cache on return]. This also applies to imports of
|
||||
things contained within a package and thus get assigned as an attribute
|
||||
[from cache to attribute] or pulled in thanks to a fromlist import
|
||||
[from cache for fromlist]. But if sys.modules contains None then
|
||||
ImportError is raised [None in cache].
|
||||
|
||||
"""
|
||||
|
||||
def test_using_cache(self):
|
||||
# [use cache]
|
||||
module_to_use = "some module found!"
|
||||
with util.uncache('some_module'):
|
||||
sys.modules['some_module'] = module_to_use
|
||||
module = self.__import__('some_module')
|
||||
self.assertEqual(id(module_to_use), id(module))
|
||||
|
||||
def test_None_in_cache(self):
|
||||
#[None in cache]
|
||||
name = 'using_None'
|
||||
with util.uncache(name):
|
||||
sys.modules[name] = None
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.__import__(name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
|
||||
|
||||
(Frozen_UseCache,
|
||||
Source_UseCache
|
||||
) = util.test_both(UseCache, __import__=util.__import__)
|
||||
|
||||
|
||||
class ImportlibUseCache(UseCache, unittest.TestCase, ExtraAssertions):
|
||||
|
||||
# Pertinent only to PEP 302; exec_module() doesn't return a module.
|
||||
|
||||
__import__ = util.__import__['Source']
|
||||
|
||||
def create_mock(self, *names, return_=None):
|
||||
mock = util.mock_spec(*names)
|
||||
original_spec = mock.find_spec
|
||||
def find_spec(self, fullname, path, target=None):
|
||||
return original_spec(fullname)
|
||||
mock.find_spec = MethodType(find_spec, mock)
|
||||
return mock
|
||||
|
||||
# __import__ inconsistent between loaders and built-in import when it comes
|
||||
# to when to use the module in sys.modules and when not to.
|
||||
def test_using_cache_after_loader(self):
|
||||
# [from cache on return]
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
with self.create_mock('module') as mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
module = self.__import__('module')
|
||||
self.assertEqual(id(module), id(sys.modules['module']))
|
||||
|
||||
# See test_using_cache_after_loader() for reasoning.
|
||||
def test_using_cache_for_assigning_to_attribute(self):
|
||||
# [from cache to attribute]
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
with self.create_mock('pkg.__init__', 'pkg.module') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
module = self.__import__('pkg.module')
|
||||
self.assertHasAttr(module, 'module')
|
||||
self.assertEqual(id(module.module),
|
||||
id(sys.modules['pkg.module']))
|
||||
|
||||
# See test_using_cache_after_loader() for reasoning.
|
||||
def test_using_cache_for_fromlist(self):
|
||||
# [from cache for fromlist]
|
||||
with self.create_mock('pkg.__init__', 'pkg.module') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
module = self.__import__('pkg', fromlist=['module'])
|
||||
self.assertHasAttr(module, 'module')
|
||||
self.assertEqual(id(module.module),
|
||||
id(sys.modules['pkg.module']))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
175
Dependencies/Python/Lib/test/test_importlib/import_/test_fromlist.py
vendored
Normal file
175
Dependencies/Python/Lib/test/test_importlib/import_/test_fromlist.py
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
"""Test that the semantics relating to the 'fromlist' argument are correct."""
|
||||
from test.test_importlib import util
|
||||
import warnings
|
||||
import unittest
|
||||
|
||||
|
||||
class ReturnValue:
|
||||
|
||||
"""The use of fromlist influences what import returns.
|
||||
|
||||
If direct ``import ...`` statement is used, the root module or package is
|
||||
returned [import return]. But if fromlist is set, then the specified module
|
||||
is actually returned (whether it is a relative import or not)
|
||||
[from return].
|
||||
|
||||
"""
|
||||
|
||||
def test_return_from_import(self):
|
||||
# [import return]
|
||||
with util.mock_spec('pkg.__init__', 'pkg.module') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
module = self.__import__('pkg.module')
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
|
||||
def test_return_from_from_import(self):
|
||||
# [from return]
|
||||
with util.mock_spec('pkg.__init__', 'pkg.module')as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
module = self.__import__('pkg.module', fromlist=['attr'])
|
||||
self.assertEqual(module.__name__, 'pkg.module')
|
||||
|
||||
|
||||
(Frozen_ReturnValue,
|
||||
Source_ReturnValue
|
||||
) = util.test_both(ReturnValue, __import__=util.__import__)
|
||||
|
||||
|
||||
class HandlingFromlist:
|
||||
|
||||
"""Using fromlist triggers different actions based on what is being asked
|
||||
of it.
|
||||
|
||||
If fromlist specifies an object on a module, nothing special happens
|
||||
[object case]. This is even true if the object does not exist [bad object].
|
||||
|
||||
If a package is being imported, then what is listed in fromlist may be
|
||||
treated as a module to be imported [module]. And this extends to what is
|
||||
contained in __all__ when '*' is imported [using *]. And '*' does not need
|
||||
to be the only name in the fromlist [using * with others].
|
||||
|
||||
"""
|
||||
|
||||
def test_object(self):
|
||||
# [object case]
|
||||
with util.mock_spec('module') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
module = self.__import__('module', fromlist=['attr'])
|
||||
self.assertEqual(module.__name__, 'module')
|
||||
|
||||
def test_nonexistent_object(self):
|
||||
# [bad object]
|
||||
with util.mock_spec('module') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
module = self.__import__('module', fromlist=['non_existent'])
|
||||
self.assertEqual(module.__name__, 'module')
|
||||
self.assertNotHasAttr(module, 'non_existent')
|
||||
|
||||
def test_module_from_package(self):
|
||||
# [module]
|
||||
with util.mock_spec('pkg.__init__', 'pkg.module') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
module = self.__import__('pkg', fromlist=['module'])
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.assertHasAttr(module, 'module')
|
||||
self.assertEqual(module.module.__name__, 'pkg.module')
|
||||
|
||||
def test_nonexistent_from_package(self):
|
||||
with util.mock_spec('pkg.__init__') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
module = self.__import__('pkg', fromlist=['non_existent'])
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.assertNotHasAttr(module, 'non_existent')
|
||||
|
||||
def test_module_from_package_triggers_ModuleNotFoundError(self):
|
||||
# If a submodule causes an ModuleNotFoundError because it tries
|
||||
# to import a module which doesn't exist, that should let the
|
||||
# ModuleNotFoundError propagate.
|
||||
def module_code():
|
||||
import i_do_not_exist
|
||||
with util.mock_spec('pkg.__init__', 'pkg.mod',
|
||||
module_code={'pkg.mod': module_code}) as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
with self.assertRaises(ModuleNotFoundError) as exc:
|
||||
self.__import__('pkg', fromlist=['mod'])
|
||||
self.assertEqual('i_do_not_exist', exc.exception.name)
|
||||
|
||||
def test_empty_string(self):
|
||||
with util.mock_spec('pkg.__init__', 'pkg.mod') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
module = self.__import__('pkg.mod', fromlist=[''])
|
||||
self.assertEqual(module.__name__, 'pkg.mod')
|
||||
|
||||
def basic_star_test(self, fromlist=['*']):
|
||||
# [using *]
|
||||
with util.mock_spec('pkg.__init__', 'pkg.module') as mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
mock['pkg'].__all__ = ['module']
|
||||
module = self.__import__('pkg', fromlist=fromlist)
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.assertHasAttr(module, 'module')
|
||||
self.assertEqual(module.module.__name__, 'pkg.module')
|
||||
|
||||
def test_using_star(self):
|
||||
# [using *]
|
||||
self.basic_star_test()
|
||||
|
||||
def test_fromlist_as_tuple(self):
|
||||
self.basic_star_test(('*',))
|
||||
|
||||
def test_star_with_others(self):
|
||||
# [using * with others]
|
||||
context = util.mock_spec('pkg.__init__', 'pkg.module1', 'pkg.module2')
|
||||
with context as mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
mock['pkg'].__all__ = ['module1']
|
||||
module = self.__import__('pkg', fromlist=['module2', '*'])
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.assertHasAttr(module, 'module1')
|
||||
self.assertHasAttr(module, 'module2')
|
||||
self.assertEqual(module.module1.__name__, 'pkg.module1')
|
||||
self.assertEqual(module.module2.__name__, 'pkg.module2')
|
||||
|
||||
def test_nonexistent_in_all(self):
|
||||
with util.mock_spec('pkg.__init__') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
importer['pkg'].__all__ = ['non_existent']
|
||||
module = self.__import__('pkg', fromlist=['*'])
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.assertNotHasAttr(module, 'non_existent')
|
||||
|
||||
def test_star_in_all(self):
|
||||
with util.mock_spec('pkg.__init__') as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
importer['pkg'].__all__ = ['*']
|
||||
module = self.__import__('pkg', fromlist=['*'])
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.assertNotHasAttr(module, '*')
|
||||
|
||||
def test_invalid_type(self):
|
||||
with util.mock_spec('pkg.__init__') as importer:
|
||||
with util.import_state(meta_path=[importer]), \
|
||||
warnings.catch_warnings():
|
||||
warnings.simplefilter('error', BytesWarning)
|
||||
with self.assertRaisesRegex(TypeError, r'\bfrom\b'):
|
||||
self.__import__('pkg', fromlist=[b'attr'])
|
||||
with self.assertRaisesRegex(TypeError, r'\bfrom\b'):
|
||||
self.__import__('pkg', fromlist=iter([b'attr']))
|
||||
|
||||
def test_invalid_type_in_all(self):
|
||||
with util.mock_spec('pkg.__init__') as importer:
|
||||
with util.import_state(meta_path=[importer]), \
|
||||
warnings.catch_warnings():
|
||||
warnings.simplefilter('error', BytesWarning)
|
||||
importer['pkg'].__all__ = [b'attr']
|
||||
with self.assertRaisesRegex(TypeError, r'\bpkg\.__all__\b'):
|
||||
self.__import__('pkg', fromlist=['*'])
|
||||
|
||||
|
||||
(Frozen_FromList,
|
||||
Source_FromList
|
||||
) = util.test_both(HandlingFromlist, __import__=util.__import__)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
184
Dependencies/Python/Lib/test/test_importlib/import_/test_helpers.py
vendored
Normal file
184
Dependencies/Python/Lib/test/test_importlib/import_/test_helpers.py
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
"""Tests for helper functions used by import.c ."""
|
||||
|
||||
from importlib import _bootstrap_external, machinery
|
||||
import os.path
|
||||
from types import ModuleType, SimpleNamespace
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from .. import util
|
||||
|
||||
|
||||
class FixUpModuleTests:
|
||||
|
||||
def test_no_loader_but_spec(self):
|
||||
loader = object()
|
||||
name = "hello"
|
||||
path = "hello.py"
|
||||
spec = machinery.ModuleSpec(name, loader)
|
||||
ns = {"__spec__": spec}
|
||||
_bootstrap_external._fix_up_module(ns, name, path)
|
||||
|
||||
expected = {"__spec__": spec, "__loader__": loader, "__file__": path,
|
||||
"__cached__": None}
|
||||
self.assertEqual(ns, expected)
|
||||
|
||||
def test_no_loader_no_spec_but_sourceless(self):
|
||||
name = "hello"
|
||||
path = "hello.py"
|
||||
ns = {}
|
||||
_bootstrap_external._fix_up_module(ns, name, path, path)
|
||||
|
||||
expected = {"__file__": path, "__cached__": path}
|
||||
|
||||
for key, val in expected.items():
|
||||
with self.subTest(f"{key}: {val}"):
|
||||
self.assertEqual(ns[key], val)
|
||||
|
||||
spec = ns["__spec__"]
|
||||
self.assertIsInstance(spec, machinery.ModuleSpec)
|
||||
self.assertEqual(spec.name, name)
|
||||
self.assertEqual(spec.origin, os.path.abspath(path))
|
||||
self.assertEqual(spec.cached, os.path.abspath(path))
|
||||
self.assertIsInstance(spec.loader, machinery.SourcelessFileLoader)
|
||||
self.assertEqual(spec.loader.name, name)
|
||||
self.assertEqual(spec.loader.path, path)
|
||||
self.assertEqual(spec.loader, ns["__loader__"])
|
||||
|
||||
def test_no_loader_no_spec_but_source(self):
|
||||
name = "hello"
|
||||
path = "hello.py"
|
||||
ns = {}
|
||||
_bootstrap_external._fix_up_module(ns, name, path)
|
||||
|
||||
expected = {"__file__": path, "__cached__": None}
|
||||
|
||||
for key, val in expected.items():
|
||||
with self.subTest(f"{key}: {val}"):
|
||||
self.assertEqual(ns[key], val)
|
||||
|
||||
spec = ns["__spec__"]
|
||||
self.assertIsInstance(spec, machinery.ModuleSpec)
|
||||
self.assertEqual(spec.name, name)
|
||||
self.assertEqual(spec.origin, os.path.abspath(path))
|
||||
self.assertIsInstance(spec.loader, machinery.SourceFileLoader)
|
||||
self.assertEqual(spec.loader.name, name)
|
||||
self.assertEqual(spec.loader.path, path)
|
||||
self.assertEqual(spec.loader, ns["__loader__"])
|
||||
|
||||
|
||||
FrozenFixUpModuleTests, SourceFixUpModuleTests = util.test_both(FixUpModuleTests)
|
||||
|
||||
|
||||
class TestBlessMyLoader(unittest.TestCase):
|
||||
# GH#86298 is part of the migration away from module attributes and toward
|
||||
# __spec__ attributes. There are several cases to test here. This will
|
||||
# have to change in Python 3.14 when we actually remove/ignore __loader__
|
||||
# in favor of requiring __spec__.loader.
|
||||
|
||||
def test_gh86298_no_loader_and_no_spec(self):
|
||||
bar = ModuleType('bar')
|
||||
del bar.__loader__
|
||||
del bar.__spec__
|
||||
# 2022-10-06(warsaw): For backward compatibility with the
|
||||
# implementation in _warnings.c, this can't raise an
|
||||
# AttributeError. See _bless_my_loader() in _bootstrap_external.py
|
||||
# If working with a module:
|
||||
## self.assertRaises(
|
||||
## AttributeError, _bootstrap_external._bless_my_loader,
|
||||
## bar.__dict__)
|
||||
self.assertIsNone(_bootstrap_external._bless_my_loader(bar.__dict__))
|
||||
|
||||
def test_gh86298_loader_is_none_and_no_spec(self):
|
||||
bar = ModuleType('bar')
|
||||
bar.__loader__ = None
|
||||
del bar.__spec__
|
||||
# 2022-10-06(warsaw): For backward compatibility with the
|
||||
# implementation in _warnings.c, this can't raise an
|
||||
# AttributeError. See _bless_my_loader() in _bootstrap_external.py
|
||||
# If working with a module:
|
||||
## self.assertRaises(
|
||||
## AttributeError, _bootstrap_external._bless_my_loader,
|
||||
## bar.__dict__)
|
||||
self.assertIsNone(_bootstrap_external._bless_my_loader(bar.__dict__))
|
||||
|
||||
def test_gh86298_no_loader_and_spec_is_none(self):
|
||||
bar = ModuleType('bar')
|
||||
del bar.__loader__
|
||||
bar.__spec__ = None
|
||||
self.assertRaises(
|
||||
ValueError,
|
||||
_bootstrap_external._bless_my_loader, bar.__dict__)
|
||||
|
||||
def test_gh86298_loader_is_none_and_spec_is_none(self):
|
||||
bar = ModuleType('bar')
|
||||
bar.__loader__ = None
|
||||
bar.__spec__ = None
|
||||
self.assertRaises(
|
||||
ValueError,
|
||||
_bootstrap_external._bless_my_loader, bar.__dict__)
|
||||
|
||||
def test_gh86298_loader_is_none_and_spec_loader_is_none(self):
|
||||
bar = ModuleType('bar')
|
||||
bar.__loader__ = None
|
||||
bar.__spec__ = SimpleNamespace(loader=None)
|
||||
self.assertRaises(
|
||||
ValueError,
|
||||
_bootstrap_external._bless_my_loader, bar.__dict__)
|
||||
|
||||
def test_gh86298_no_spec(self):
|
||||
bar = ModuleType('bar')
|
||||
bar.__loader__ = object()
|
||||
del bar.__spec__
|
||||
with warnings.catch_warnings():
|
||||
self.assertWarns(
|
||||
DeprecationWarning,
|
||||
_bootstrap_external._bless_my_loader, bar.__dict__)
|
||||
|
||||
def test_gh86298_spec_is_none(self):
|
||||
bar = ModuleType('bar')
|
||||
bar.__loader__ = object()
|
||||
bar.__spec__ = None
|
||||
with warnings.catch_warnings():
|
||||
self.assertWarns(
|
||||
DeprecationWarning,
|
||||
_bootstrap_external._bless_my_loader, bar.__dict__)
|
||||
|
||||
def test_gh86298_no_spec_loader(self):
|
||||
bar = ModuleType('bar')
|
||||
bar.__loader__ = object()
|
||||
bar.__spec__ = SimpleNamespace()
|
||||
with warnings.catch_warnings():
|
||||
self.assertWarns(
|
||||
DeprecationWarning,
|
||||
_bootstrap_external._bless_my_loader, bar.__dict__)
|
||||
|
||||
def test_gh86298_loader_and_spec_loader_disagree(self):
|
||||
bar = ModuleType('bar')
|
||||
bar.__loader__ = object()
|
||||
bar.__spec__ = SimpleNamespace(loader=object())
|
||||
with warnings.catch_warnings():
|
||||
self.assertWarns(
|
||||
DeprecationWarning,
|
||||
_bootstrap_external._bless_my_loader, bar.__dict__)
|
||||
|
||||
def test_gh86298_no_loader_and_no_spec_loader(self):
|
||||
bar = ModuleType('bar')
|
||||
del bar.__loader__
|
||||
bar.__spec__ = SimpleNamespace()
|
||||
self.assertRaises(
|
||||
AttributeError,
|
||||
_bootstrap_external._bless_my_loader, bar.__dict__)
|
||||
|
||||
def test_gh86298_no_loader_with_spec_loader_okay(self):
|
||||
bar = ModuleType('bar')
|
||||
del bar.__loader__
|
||||
loader = object()
|
||||
bar.__spec__ = SimpleNamespace(loader=loader)
|
||||
self.assertEqual(
|
||||
_bootstrap_external._bless_my_loader(bar.__dict__),
|
||||
loader)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
127
Dependencies/Python/Lib/test/test_importlib/import_/test_meta_path.py
vendored
Normal file
127
Dependencies/Python/Lib/test/test_importlib/import_/test_meta_path.py
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
from test.test_importlib import util
|
||||
import importlib._bootstrap
|
||||
import sys
|
||||
from types import MethodType
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
|
||||
class CallingOrder:
|
||||
|
||||
"""Calls to the importers on sys.meta_path happen in order that they are
|
||||
specified in the sequence, starting with the first importer
|
||||
[first called], and then continuing on down until one is found that doesn't
|
||||
return None [continuing]."""
|
||||
|
||||
|
||||
def test_first_called(self):
|
||||
# [first called]
|
||||
mod = 'top_level'
|
||||
with util.mock_spec(mod) as first, util.mock_spec(mod) as second:
|
||||
with util.import_state(meta_path=[first, second]):
|
||||
self.assertIs(self.__import__(mod), first.modules[mod])
|
||||
|
||||
def test_continuing(self):
|
||||
# [continuing]
|
||||
mod_name = 'for_real'
|
||||
with util.mock_spec('nonexistent') as first, \
|
||||
util.mock_spec(mod_name) as second:
|
||||
first.find_spec = lambda self, fullname, path=None, parent=None: None
|
||||
with util.import_state(meta_path=[first, second]):
|
||||
self.assertIs(self.__import__(mod_name), second.modules[mod_name])
|
||||
|
||||
def test_empty(self):
|
||||
# Raise an ImportWarning if sys.meta_path is empty.
|
||||
module_name = 'nothing'
|
||||
try:
|
||||
del sys.modules[module_name]
|
||||
except KeyError:
|
||||
pass
|
||||
with util.import_state(meta_path=[]):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always')
|
||||
self.assertIsNone(importlib._bootstrap._find_spec('nothing',
|
||||
None))
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertIsSubclass(w[-1].category, ImportWarning)
|
||||
|
||||
|
||||
(Frozen_CallingOrder,
|
||||
Source_CallingOrder
|
||||
) = util.test_both(CallingOrder, __import__=util.__import__)
|
||||
|
||||
|
||||
class CallSignature:
|
||||
|
||||
"""If there is no __path__ entry on the parent module, then 'path' is None
|
||||
[no path]. Otherwise, the value for __path__ is passed in for the 'path'
|
||||
argument [path set]."""
|
||||
|
||||
def log_finder(self, importer):
|
||||
fxn = getattr(importer, self.finder_name)
|
||||
log = []
|
||||
def wrapper(self, *args, **kwargs):
|
||||
log.append([args, kwargs])
|
||||
return fxn(*args, **kwargs)
|
||||
return log, wrapper
|
||||
|
||||
def test_no_path(self):
|
||||
# [no path]
|
||||
mod_name = 'top_level'
|
||||
assert '.' not in mod_name
|
||||
with self.mock_modules(mod_name) as importer:
|
||||
log, wrapped_call = self.log_finder(importer)
|
||||
setattr(importer, self.finder_name, MethodType(wrapped_call, importer))
|
||||
with util.import_state(meta_path=[importer]):
|
||||
self.__import__(mod_name)
|
||||
assert len(log) == 1
|
||||
args = log[0][0]
|
||||
# Assuming all arguments are positional.
|
||||
self.assertEqual(args[0], mod_name)
|
||||
self.assertIsNone(args[1])
|
||||
|
||||
def test_with_path(self):
|
||||
# [path set]
|
||||
pkg_name = 'pkg'
|
||||
mod_name = pkg_name + '.module'
|
||||
path = [42]
|
||||
assert '.' in mod_name
|
||||
with self.mock_modules(pkg_name+'.__init__', mod_name) as importer:
|
||||
importer.modules[pkg_name].__path__ = path
|
||||
log, wrapped_call = self.log_finder(importer)
|
||||
setattr(importer, self.finder_name, MethodType(wrapped_call, importer))
|
||||
with util.import_state(meta_path=[importer]):
|
||||
self.__import__(mod_name)
|
||||
assert len(log) == 2
|
||||
args = log[1][0]
|
||||
kwargs = log[1][1]
|
||||
# Assuming all arguments are positional.
|
||||
self.assertFalse(kwargs)
|
||||
self.assertEqual(args[0], mod_name)
|
||||
self.assertIs(args[1], path)
|
||||
|
||||
class CallSignoreSuppressImportWarning(CallSignature):
|
||||
|
||||
def test_no_path(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
super().test_no_path()
|
||||
|
||||
def test_with_path(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
super().test_no_path()
|
||||
|
||||
|
||||
class CallSignaturePEP451(CallSignature):
|
||||
mock_modules = util.mock_spec
|
||||
finder_name = 'find_spec'
|
||||
|
||||
|
||||
(Frozen_CallSignaturePEP451,
|
||||
Source_CallSignaturePEP451
|
||||
) = util.test_both(CallSignaturePEP451, __import__=util.__import__)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
110
Dependencies/Python/Lib/test/test_importlib/import_/test_packages.py
vendored
Normal file
110
Dependencies/Python/Lib/test/test_importlib/import_/test_packages.py
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
from test.test_importlib import util
|
||||
import sys
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
|
||||
|
||||
class ParentModuleTests:
|
||||
|
||||
"""Importing a submodule should import the parent modules."""
|
||||
|
||||
def test_import_parent(self):
|
||||
with util.mock_spec('pkg.__init__', 'pkg.module') as mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
module = self.__import__('pkg.module')
|
||||
self.assertIn('pkg', sys.modules)
|
||||
|
||||
def test_bad_parent(self):
|
||||
with util.mock_spec('pkg.module') as mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.__import__('pkg.module')
|
||||
self.assertEqual(cm.exception.name, 'pkg')
|
||||
|
||||
def test_raising_parent_after_importing_child(self):
|
||||
def __init__():
|
||||
import pkg.module
|
||||
1/0
|
||||
mock = util.mock_spec('pkg.__init__', 'pkg.module',
|
||||
module_code={'pkg': __init__})
|
||||
with mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
self.__import__('pkg')
|
||||
self.assertNotIn('pkg', sys.modules)
|
||||
self.assertIn('pkg.module', sys.modules)
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
self.__import__('pkg.module')
|
||||
self.assertNotIn('pkg', sys.modules)
|
||||
self.assertIn('pkg.module', sys.modules)
|
||||
|
||||
def test_raising_parent_after_relative_importing_child(self):
|
||||
def __init__():
|
||||
from . import module
|
||||
1/0
|
||||
mock = util.mock_spec('pkg.__init__', 'pkg.module',
|
||||
module_code={'pkg': __init__})
|
||||
with mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
with self.assertRaises((ZeroDivisionError, ImportError)):
|
||||
# This raises ImportError on the "from . import module"
|
||||
# line, not sure why.
|
||||
self.__import__('pkg')
|
||||
self.assertNotIn('pkg', sys.modules)
|
||||
with self.assertRaises((ZeroDivisionError, ImportError)):
|
||||
self.__import__('pkg.module')
|
||||
self.assertNotIn('pkg', sys.modules)
|
||||
# XXX False
|
||||
#self.assertIn('pkg.module', sys.modules)
|
||||
|
||||
def test_raising_parent_after_double_relative_importing_child(self):
|
||||
def __init__():
|
||||
from ..subpkg import module
|
||||
1/0
|
||||
mock = util.mock_spec('pkg.__init__', 'pkg.subpkg.__init__',
|
||||
'pkg.subpkg.module',
|
||||
module_code={'pkg.subpkg': __init__})
|
||||
with mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
with self.assertRaises((ZeroDivisionError, ImportError)):
|
||||
# This raises ImportError on the "from ..subpkg import module"
|
||||
# line, not sure why.
|
||||
self.__import__('pkg.subpkg')
|
||||
self.assertNotIn('pkg.subpkg', sys.modules)
|
||||
with self.assertRaises((ZeroDivisionError, ImportError)):
|
||||
self.__import__('pkg.subpkg.module')
|
||||
self.assertNotIn('pkg.subpkg', sys.modules)
|
||||
# XXX False
|
||||
#self.assertIn('pkg.subpkg.module', sys.modules)
|
||||
|
||||
def test_module_not_package(self):
|
||||
# Try to import a submodule from a non-package should raise ImportError.
|
||||
assert not hasattr(sys, '__path__')
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.__import__('sys.no_submodules_here')
|
||||
self.assertEqual(cm.exception.name, 'sys.no_submodules_here')
|
||||
|
||||
def test_module_not_package_but_side_effects(self):
|
||||
# If a module injects something into sys.modules as a side-effect, then
|
||||
# pick up on that fact.
|
||||
name = 'mod'
|
||||
subname = name + '.b'
|
||||
def module_injection():
|
||||
sys.modules[subname] = 'total bunk'
|
||||
mock_spec = util.mock_spec('mod',
|
||||
module_code={'mod': module_injection})
|
||||
with mock_spec as mock:
|
||||
with util.import_state(meta_path=[mock]):
|
||||
try:
|
||||
submodule = self.__import__(subname)
|
||||
finally:
|
||||
import_helper.unload(subname)
|
||||
|
||||
|
||||
(Frozen_ParentTests,
|
||||
Source_ParentTests
|
||||
) = util.test_both(ParentModuleTests, __import__=util.__import__)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
242
Dependencies/Python/Lib/test/test_importlib/import_/test_path.py
vendored
Normal file
242
Dependencies/Python/Lib/test/test_importlib/import_/test_path.py
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
from test.test_importlib import util
|
||||
|
||||
importlib = util.import_importlib('importlib')
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
from types import ModuleType
|
||||
import unittest
|
||||
import warnings
|
||||
import zipimport
|
||||
|
||||
|
||||
class FinderTests:
|
||||
|
||||
"""Tests for PathFinder."""
|
||||
|
||||
find = None
|
||||
check_found = None
|
||||
|
||||
def test_failure(self):
|
||||
# Test None returned upon not finding a suitable loader.
|
||||
module = '<test module>'
|
||||
with util.import_state():
|
||||
self.assertIsNone(self.find(module))
|
||||
|
||||
def test_sys_path(self):
|
||||
# Test that sys.path is used when 'path' is None.
|
||||
# Implicitly tests that sys.path_importer_cache is used.
|
||||
module = '<test module>'
|
||||
path = '<test path>'
|
||||
importer = util.mock_spec(module)
|
||||
with util.import_state(path_importer_cache={path: importer},
|
||||
path=[path]):
|
||||
found = self.find(module)
|
||||
self.check_found(found, importer)
|
||||
|
||||
def test_path(self):
|
||||
# Test that 'path' is used when set.
|
||||
# Implicitly tests that sys.path_importer_cache is used.
|
||||
module = '<test module>'
|
||||
path = '<test path>'
|
||||
importer = util.mock_spec(module)
|
||||
with util.import_state(path_importer_cache={path: importer}):
|
||||
found = self.find(module, [path])
|
||||
self.check_found(found, importer)
|
||||
|
||||
def test_empty_list(self):
|
||||
# An empty list should not count as asking for sys.path.
|
||||
module = 'module'
|
||||
path = '<test path>'
|
||||
importer = util.mock_spec(module)
|
||||
with util.import_state(path_importer_cache={path: importer},
|
||||
path=[path]):
|
||||
self.assertIsNone(self.find('module', []))
|
||||
|
||||
def test_path_hooks(self):
|
||||
# Test that sys.path_hooks is used.
|
||||
# Test that sys.path_importer_cache is set.
|
||||
module = '<test module>'
|
||||
path = '<test path>'
|
||||
importer = util.mock_spec(module)
|
||||
hook = util.mock_path_hook(path, importer=importer)
|
||||
with util.import_state(path_hooks=[hook]):
|
||||
found = self.find(module, [path])
|
||||
self.check_found(found, importer)
|
||||
self.assertIn(path, sys.path_importer_cache)
|
||||
self.assertIs(sys.path_importer_cache[path], importer)
|
||||
|
||||
def test_empty_path_hooks(self):
|
||||
# Test that if sys.path_hooks is empty a warning is raised,
|
||||
# sys.path_importer_cache gets None set, and PathFinder returns None.
|
||||
path_entry = 'bogus_path'
|
||||
with util.import_state(path_importer_cache={}, path_hooks=[],
|
||||
path=[path_entry]):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter('always', ImportWarning)
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
self.assertIsNone(self.find('os'))
|
||||
self.assertIsNone(sys.path_importer_cache[path_entry])
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertIsSubclass(w[-1].category, ImportWarning)
|
||||
|
||||
def test_path_importer_cache_empty_string(self):
|
||||
# The empty string should create a finder using the cwd.
|
||||
path = ''
|
||||
module = '<test module>'
|
||||
importer = util.mock_spec(module)
|
||||
hook = util.mock_path_hook(os.getcwd(), importer=importer)
|
||||
with util.import_state(path=[path], path_hooks=[hook]):
|
||||
found = self.find(module)
|
||||
self.check_found(found, importer)
|
||||
self.assertIn(os.getcwd(), sys.path_importer_cache)
|
||||
|
||||
def test_None_on_sys_path(self):
|
||||
# Putting None in sys.path[0] caused an import regression from Python
|
||||
# 3.2: http://bugs.python.org/issue16514
|
||||
new_path = sys.path[:]
|
||||
new_path.insert(0, None)
|
||||
new_path_importer_cache = sys.path_importer_cache.copy()
|
||||
new_path_importer_cache.pop(None, None)
|
||||
new_path_hooks = [zipimport.zipimporter,
|
||||
self.machinery.FileFinder.path_hook(
|
||||
*self.importlib._bootstrap_external._get_supported_file_loaders())]
|
||||
missing = object()
|
||||
email = sys.modules.pop('email', missing)
|
||||
try:
|
||||
with util.import_state(meta_path=sys.meta_path[:],
|
||||
path=new_path,
|
||||
path_importer_cache=new_path_importer_cache,
|
||||
path_hooks=new_path_hooks):
|
||||
module = self.importlib.import_module('email')
|
||||
self.assertIsInstance(module, ModuleType)
|
||||
finally:
|
||||
if email is not missing:
|
||||
sys.modules['email'] = email
|
||||
|
||||
def test_finder_with_find_spec(self):
|
||||
class TestFinder:
|
||||
spec = None
|
||||
def find_spec(self, fullname, target=None):
|
||||
return self.spec
|
||||
path = 'testing path'
|
||||
with util.import_state(path_importer_cache={path: TestFinder()}):
|
||||
self.assertIsNone(
|
||||
self.machinery.PathFinder.find_spec('whatever', [path]))
|
||||
success_finder = TestFinder()
|
||||
success_finder.spec = self.machinery.ModuleSpec('whatever', __loader__)
|
||||
with util.import_state(path_importer_cache={path: success_finder}):
|
||||
got = self.machinery.PathFinder.find_spec('whatever', [path])
|
||||
self.assertEqual(got, success_finder.spec)
|
||||
|
||||
def test_deleted_cwd(self):
|
||||
# Issue #22834
|
||||
old_dir = os.getcwd()
|
||||
self.addCleanup(os.chdir, old_dir)
|
||||
new_dir = tempfile.mkdtemp()
|
||||
try:
|
||||
os.chdir(new_dir)
|
||||
try:
|
||||
os.rmdir(new_dir)
|
||||
except OSError:
|
||||
# EINVAL on Solaris, EBUSY on AIX, ENOTEMPTY on Windows
|
||||
self.skipTest("platform does not allow "
|
||||
"the deletion of the cwd")
|
||||
except:
|
||||
os.chdir(old_dir)
|
||||
os.rmdir(new_dir)
|
||||
raise
|
||||
|
||||
with util.import_state(path=['']):
|
||||
# Do not want FileNotFoundError raised.
|
||||
self.assertIsNone(self.machinery.PathFinder.find_spec('whatever'))
|
||||
|
||||
def test_invalidate_caches_finders(self):
|
||||
# Finders with an invalidate_caches() method have it called.
|
||||
class FakeFinder:
|
||||
def __init__(self):
|
||||
self.called = False
|
||||
|
||||
def invalidate_caches(self):
|
||||
self.called = True
|
||||
|
||||
key = os.path.abspath('finder_to_invalidate')
|
||||
cache = {'leave_alone': object(), key: FakeFinder()}
|
||||
with util.import_state(path_importer_cache=cache):
|
||||
self.machinery.PathFinder.invalidate_caches()
|
||||
self.assertTrue(cache[key].called)
|
||||
|
||||
def test_invalidate_caches_clear_out_None(self):
|
||||
# Clear out None in sys.path_importer_cache() when invalidating caches.
|
||||
cache = {'clear_out': None}
|
||||
with util.import_state(path_importer_cache=cache):
|
||||
self.machinery.PathFinder.invalidate_caches()
|
||||
self.assertEqual(len(cache), 0)
|
||||
|
||||
def test_invalidate_caches_clear_out_relative_path(self):
|
||||
class FakeFinder:
|
||||
def invalidate_caches(self):
|
||||
pass
|
||||
|
||||
cache = {'relative_path': FakeFinder()}
|
||||
with util.import_state(path_importer_cache=cache):
|
||||
self.machinery.PathFinder.invalidate_caches()
|
||||
self.assertEqual(cache, {})
|
||||
|
||||
|
||||
class FindModuleTests(FinderTests):
|
||||
def find(self, *args, **kwargs):
|
||||
spec = self.machinery.PathFinder.find_spec(*args, **kwargs)
|
||||
return None if spec is None else spec.loader
|
||||
|
||||
def check_found(self, found, importer):
|
||||
self.assertIs(found, importer)
|
||||
|
||||
|
||||
(Frozen_FindModuleTests,
|
||||
Source_FindModuleTests
|
||||
) = util.test_both(FindModuleTests, importlib=importlib, machinery=machinery)
|
||||
|
||||
|
||||
class FindSpecTests(FinderTests):
|
||||
def find(self, *args, **kwargs):
|
||||
return self.machinery.PathFinder.find_spec(*args, **kwargs)
|
||||
def check_found(self, found, importer):
|
||||
self.assertIs(found.loader, importer)
|
||||
|
||||
|
||||
(Frozen_FindSpecTests,
|
||||
Source_FindSpecTests
|
||||
) = util.test_both(FindSpecTests, importlib=importlib, machinery=machinery)
|
||||
|
||||
|
||||
class PathEntryFinderTests:
|
||||
|
||||
def test_finder_with_failing_find_spec(self):
|
||||
class Finder:
|
||||
path_location = 'test_finder_with_find_spec'
|
||||
def __init__(self, path):
|
||||
if path != self.path_location:
|
||||
raise ImportError
|
||||
|
||||
@staticmethod
|
||||
def find_spec(fullname, target=None):
|
||||
return None
|
||||
|
||||
|
||||
with util.import_state(path=[Finder.path_location]+sys.path[:],
|
||||
path_hooks=[Finder]):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
self.machinery.PathFinder.find_spec('importlib')
|
||||
|
||||
|
||||
(Frozen_PEFTests,
|
||||
Source_PEFTests
|
||||
) = util.test_both(PathEntryFinderTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
233
Dependencies/Python/Lib/test/test_importlib/import_/test_relative_imports.py
vendored
Normal file
233
Dependencies/Python/Lib/test/test_importlib/import_/test_relative_imports.py
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
"""Test relative imports (PEP 328)."""
|
||||
from test.test_importlib import util
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
|
||||
class RelativeImports:
|
||||
|
||||
"""PEP 328 introduced relative imports. This allows for imports to occur
|
||||
from within a package without having to specify the actual package name.
|
||||
|
||||
A simple example is to import another module within the same package
|
||||
[module from module]::
|
||||
|
||||
# From pkg.mod1 with pkg.mod2 being a module.
|
||||
from . import mod2
|
||||
|
||||
This also works for getting an attribute from a module that is specified
|
||||
in a relative fashion [attr from module]::
|
||||
|
||||
# From pkg.mod1.
|
||||
from .mod2 import attr
|
||||
|
||||
But this is in no way restricted to working between modules; it works
|
||||
from [package to module],::
|
||||
|
||||
# From pkg, importing pkg.module which is a module.
|
||||
from . import module
|
||||
|
||||
[module to package],::
|
||||
|
||||
# Pull attr from pkg, called from pkg.module which is a module.
|
||||
from . import attr
|
||||
|
||||
and [package to package]::
|
||||
|
||||
# From pkg.subpkg1 (both pkg.subpkg[1,2] are packages).
|
||||
from .. import subpkg2
|
||||
|
||||
The number of dots used is in no way restricted [deep import]::
|
||||
|
||||
# Import pkg.attr from pkg.pkg1.pkg2.pkg3.pkg4.pkg5.
|
||||
from ...... import attr
|
||||
|
||||
To prevent someone from accessing code that is outside of a package, one
|
||||
cannot reach the location containing the root package itself::
|
||||
|
||||
# From pkg.__init__ [too high from package]
|
||||
from .. import top_level
|
||||
|
||||
# From pkg.module [too high from module]
|
||||
from .. import top_level
|
||||
|
||||
Relative imports are the only type of import that allow for an empty
|
||||
module name for an import [empty name].
|
||||
|
||||
"""
|
||||
|
||||
def relative_import_test(self, create, globals_, callback):
|
||||
"""Abstract out boilerplace for setting up for an import test."""
|
||||
uncache_names = []
|
||||
for name in create:
|
||||
if not name.endswith('.__init__'):
|
||||
uncache_names.append(name)
|
||||
else:
|
||||
uncache_names.append(name[:-len('.__init__')])
|
||||
with util.mock_spec(*create) as importer:
|
||||
with util.import_state(meta_path=[importer]):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
for global_ in globals_:
|
||||
with util.uncache(*uncache_names):
|
||||
callback(global_)
|
||||
|
||||
|
||||
def test_module_from_module(self):
|
||||
# [module from module]
|
||||
create = 'pkg.__init__', 'pkg.mod2'
|
||||
globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.mod1'}
|
||||
def callback(global_):
|
||||
self.__import__('pkg') # For __import__().
|
||||
module = self.__import__('', global_, fromlist=['mod2'], level=1)
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.assertHasAttr(module, 'mod2')
|
||||
self.assertEqual(module.mod2.attr, 'pkg.mod2')
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_attr_from_module(self):
|
||||
# [attr from module]
|
||||
create = 'pkg.__init__', 'pkg.mod2'
|
||||
globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.mod1'}
|
||||
def callback(global_):
|
||||
self.__import__('pkg') # For __import__().
|
||||
module = self.__import__('mod2', global_, fromlist=['attr'],
|
||||
level=1)
|
||||
self.assertEqual(module.__name__, 'pkg.mod2')
|
||||
self.assertEqual(module.attr, 'pkg.mod2')
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_package_to_module(self):
|
||||
# [package to module]
|
||||
create = 'pkg.__init__', 'pkg.module'
|
||||
globals_ = ({'__package__': 'pkg'},
|
||||
{'__name__': 'pkg', '__path__': ['blah']})
|
||||
def callback(global_):
|
||||
self.__import__('pkg') # For __import__().
|
||||
module = self.__import__('', global_, fromlist=['module'],
|
||||
level=1)
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.assertHasAttr(module, 'module')
|
||||
self.assertEqual(module.module.attr, 'pkg.module')
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_module_to_package(self):
|
||||
# [module to package]
|
||||
create = 'pkg.__init__', 'pkg.module'
|
||||
globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.module'}
|
||||
def callback(global_):
|
||||
self.__import__('pkg') # For __import__().
|
||||
module = self.__import__('', global_, fromlist=['attr'], level=1)
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_package_to_package(self):
|
||||
# [package to package]
|
||||
create = ('pkg.__init__', 'pkg.subpkg1.__init__',
|
||||
'pkg.subpkg2.__init__')
|
||||
globals_ = ({'__package__': 'pkg.subpkg1'},
|
||||
{'__name__': 'pkg.subpkg1', '__path__': ['blah']})
|
||||
def callback(global_):
|
||||
module = self.__import__('', global_, fromlist=['subpkg2'],
|
||||
level=2)
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.assertHasAttr(module, 'subpkg2')
|
||||
self.assertEqual(module.subpkg2.attr, 'pkg.subpkg2.__init__')
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_deep_import(self):
|
||||
# [deep import]
|
||||
create = ['pkg.__init__']
|
||||
for count in range(1,6):
|
||||
create.append('{0}.pkg{1}.__init__'.format(
|
||||
create[-1][:-len('.__init__')], count))
|
||||
globals_ = ({'__package__': 'pkg.pkg1.pkg2.pkg3.pkg4.pkg5'},
|
||||
{'__name__': 'pkg.pkg1.pkg2.pkg3.pkg4.pkg5',
|
||||
'__path__': ['blah']})
|
||||
def callback(global_):
|
||||
self.__import__(globals_[0]['__package__'])
|
||||
module = self.__import__('', global_, fromlist=['attr'], level=6)
|
||||
self.assertEqual(module.__name__, 'pkg')
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_too_high_from_package(self):
|
||||
# [too high from package]
|
||||
create = ['top_level', 'pkg.__init__']
|
||||
globals_ = ({'__package__': 'pkg'},
|
||||
{'__name__': 'pkg', '__path__': ['blah']})
|
||||
def callback(global_):
|
||||
self.__import__('pkg')
|
||||
with self.assertRaises(ImportError):
|
||||
self.__import__('', global_, fromlist=['top_level'],
|
||||
level=2)
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_too_high_from_module(self):
|
||||
# [too high from module]
|
||||
create = ['top_level', 'pkg.__init__', 'pkg.module']
|
||||
globals_ = {'__package__': 'pkg'}, {'__name__': 'pkg.module'}
|
||||
def callback(global_):
|
||||
self.__import__('pkg')
|
||||
with self.assertRaises(ImportError):
|
||||
self.__import__('', global_, fromlist=['top_level'],
|
||||
level=2)
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_empty_name_w_level_0(self):
|
||||
# [empty name]
|
||||
with self.assertRaises(ValueError):
|
||||
self.__import__('')
|
||||
|
||||
def test_import_from_different_package(self):
|
||||
# Test importing from a different package than the caller.
|
||||
# in pkg.subpkg1.mod
|
||||
# from ..subpkg2 import mod
|
||||
create = ['__runpy_pkg__.__init__',
|
||||
'__runpy_pkg__.__runpy_pkg__.__init__',
|
||||
'__runpy_pkg__.uncle.__init__',
|
||||
'__runpy_pkg__.uncle.cousin.__init__',
|
||||
'__runpy_pkg__.uncle.cousin.nephew']
|
||||
globals_ = {'__package__': '__runpy_pkg__.__runpy_pkg__'}
|
||||
def callback(global_):
|
||||
self.__import__('__runpy_pkg__.__runpy_pkg__')
|
||||
module = self.__import__('uncle.cousin', globals_, {},
|
||||
fromlist=['nephew'],
|
||||
level=2)
|
||||
self.assertEqual(module.__name__, '__runpy_pkg__.uncle.cousin')
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_import_relative_import_no_fromlist(self):
|
||||
# Import a relative module w/ no fromlist.
|
||||
create = ['crash.__init__', 'crash.mod']
|
||||
globals_ = [{'__package__': 'crash', '__name__': 'crash'}]
|
||||
def callback(global_):
|
||||
self.__import__('crash')
|
||||
mod = self.__import__('mod', global_, {}, [], 1)
|
||||
self.assertEqual(mod.__name__, 'crash.mod')
|
||||
self.relative_import_test(create, globals_, callback)
|
||||
|
||||
def test_relative_import_no_globals(self):
|
||||
# No globals for a relative import is an error.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
with self.assertRaises(KeyError):
|
||||
self.__import__('sys', level=1)
|
||||
|
||||
def test_relative_import_no_package(self):
|
||||
with self.assertRaises(ImportError):
|
||||
self.__import__('a', {'__package__': '', '__spec__': None},
|
||||
level=1)
|
||||
|
||||
def test_relative_import_no_package_exists_absolute(self):
|
||||
with self.assertRaises(ImportError):
|
||||
self.__import__('sys', {'__package__': '', '__spec__': None},
|
||||
level=1)
|
||||
|
||||
|
||||
(Frozen_RelativeImports,
|
||||
Source_RelativeImports
|
||||
) = util.test_both(RelativeImports, __import__=util.__import__)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
0
Dependencies/Python/Lib/test/test_importlib/metadata/__init__.py
vendored
Normal file
0
Dependencies/Python/Lib/test/test_importlib/metadata/__init__.py
vendored
Normal file
13
Dependencies/Python/Lib/test/test_importlib/metadata/_context.py
vendored
Normal file
13
Dependencies/Python/Lib/test/test_importlib/metadata/_context.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import contextlib
|
||||
|
||||
|
||||
# from jaraco.context 4.3
|
||||
class suppress(contextlib.suppress, contextlib.ContextDecorator):
|
||||
"""
|
||||
A version of contextlib.suppress with decorator support.
|
||||
|
||||
>>> @suppress(KeyError)
|
||||
... def key_error():
|
||||
... {}['']
|
||||
>>> key_error()
|
||||
"""
|
||||
115
Dependencies/Python/Lib/test/test_importlib/metadata/_path.py
vendored
Normal file
115
Dependencies/Python/Lib/test/test_importlib/metadata/_path.py
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
# from jaraco.path 3.7
|
||||
|
||||
import functools
|
||||
import pathlib
|
||||
from typing import Dict, Protocol, Union
|
||||
from typing import runtime_checkable
|
||||
|
||||
|
||||
class Symlink(str):
|
||||
"""
|
||||
A string indicating the target of a symlink.
|
||||
"""
|
||||
|
||||
|
||||
FilesSpec = Dict[str, Union[str, bytes, Symlink, 'FilesSpec']] # type: ignore
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class TreeMaker(Protocol):
|
||||
def __truediv__(self, *args, **kwargs): ... # pragma: no cover
|
||||
|
||||
def mkdir(self, **kwargs): ... # pragma: no cover
|
||||
|
||||
def write_text(self, content, **kwargs): ... # pragma: no cover
|
||||
|
||||
def write_bytes(self, content): ... # pragma: no cover
|
||||
|
||||
def symlink_to(self, target): ... # pragma: no cover
|
||||
|
||||
|
||||
def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker:
|
||||
return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type: ignore
|
||||
|
||||
|
||||
def build(
|
||||
spec: FilesSpec,
|
||||
prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore
|
||||
):
|
||||
"""
|
||||
Build a set of files/directories, as described by the spec.
|
||||
|
||||
Each key represents a pathname, and the value represents
|
||||
the content. Content may be a nested directory.
|
||||
|
||||
>>> spec = {
|
||||
... 'README.txt': "A README file",
|
||||
... "foo": {
|
||||
... "__init__.py": "",
|
||||
... "bar": {
|
||||
... "__init__.py": "",
|
||||
... },
|
||||
... "baz.py": "# Some code",
|
||||
... "bar.py": Symlink("baz.py"),
|
||||
... },
|
||||
... "bing": Symlink("foo"),
|
||||
... }
|
||||
>>> target = getfixture('tmp_path')
|
||||
>>> build(spec, target)
|
||||
>>> target.joinpath('foo/baz.py').read_text(encoding='utf-8')
|
||||
'# Some code'
|
||||
>>> target.joinpath('bing/bar.py').read_text(encoding='utf-8')
|
||||
'# Some code'
|
||||
"""
|
||||
for name, contents in spec.items():
|
||||
create(contents, _ensure_tree_maker(prefix) / name)
|
||||
|
||||
|
||||
@functools.singledispatch
|
||||
def create(content: Union[str, bytes, FilesSpec], path):
|
||||
path.mkdir(exist_ok=True)
|
||||
build(content, prefix=path) # type: ignore
|
||||
|
||||
|
||||
@create.register
|
||||
def _(content: bytes, path):
|
||||
path.write_bytes(content)
|
||||
|
||||
|
||||
@create.register
|
||||
def _(content: str, path):
|
||||
path.write_text(content, encoding='utf-8')
|
||||
|
||||
|
||||
@create.register
|
||||
def _(content: Symlink, path):
|
||||
path.symlink_to(content)
|
||||
|
||||
|
||||
class Recording:
|
||||
"""
|
||||
A TreeMaker object that records everything that would be written.
|
||||
|
||||
>>> r = Recording()
|
||||
>>> build({'foo': {'foo1.txt': 'yes'}, 'bar.txt': 'abc'}, r)
|
||||
>>> r.record
|
||||
['foo/foo1.txt', 'bar.txt']
|
||||
"""
|
||||
|
||||
def __init__(self, loc=pathlib.PurePosixPath(), record=None):
|
||||
self.loc = loc
|
||||
self.record = record if record is not None else []
|
||||
|
||||
def __truediv__(self, other):
|
||||
return Recording(self.loc / other, self.record)
|
||||
|
||||
def write_text(self, content, **kwargs):
|
||||
self.record.append(str(self.loc))
|
||||
|
||||
write_bytes = write_text
|
||||
|
||||
def mkdir(self, **kwargs):
|
||||
return
|
||||
|
||||
def symlink_to(self, target):
|
||||
pass
|
||||
0
Dependencies/Python/Lib/test/test_importlib/metadata/data/__init__.py
vendored
Normal file
0
Dependencies/Python/Lib/test/test_importlib/metadata/data/__init__.py
vendored
Normal file
BIN
Dependencies/Python/Lib/test/test_importlib/metadata/data/example-21.12-py3-none-any.whl
vendored
Normal file
BIN
Dependencies/Python/Lib/test/test_importlib/metadata/data/example-21.12-py3-none-any.whl
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/test/test_importlib/metadata/data/example-21.12-py3.6.egg
vendored
Normal file
BIN
Dependencies/Python/Lib/test/test_importlib/metadata/data/example-21.12-py3.6.egg
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/test/test_importlib/metadata/data/example2-1.0.0-py3-none-any.whl
vendored
Normal file
BIN
Dependencies/Python/Lib/test/test_importlib/metadata/data/example2-1.0.0-py3-none-any.whl
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
def main():
|
||||
return 'example'
|
||||
11
Dependencies/Python/Lib/test/test_importlib/metadata/data/sources/example/setup.py
vendored
Normal file
11
Dependencies/Python/Lib/test/test_importlib/metadata/data/sources/example/setup.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='example',
|
||||
version='21.12',
|
||||
license='Apache Software License',
|
||||
packages=['example'],
|
||||
entry_points={
|
||||
'console_scripts': ['example = example:main', 'Example=example:main'],
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
def main():
|
||||
return "example"
|
||||
10
Dependencies/Python/Lib/test/test_importlib/metadata/data/sources/example2/pyproject.toml
vendored
Normal file
10
Dependencies/Python/Lib/test/test_importlib/metadata/data/sources/example2/pyproject.toml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
[build-system]
|
||||
build-backend = 'trampolim'
|
||||
requires = ['trampolim']
|
||||
|
||||
[project]
|
||||
name = 'example2'
|
||||
version = '1.0.0'
|
||||
|
||||
[project.scripts]
|
||||
example = 'example2:main'
|
||||
414
Dependencies/Python/Lib/test/test_importlib/metadata/fixtures.py
vendored
Normal file
414
Dependencies/Python/Lib/test/test_importlib/metadata/fixtures.py
vendored
Normal file
@@ -0,0 +1,414 @@
|
||||
import os
|
||||
import sys
|
||||
import copy
|
||||
import json
|
||||
import shutil
|
||||
import pathlib
|
||||
import tempfile
|
||||
import textwrap
|
||||
import functools
|
||||
import contextlib
|
||||
|
||||
from test.support import import_helper
|
||||
from test.support import os_helper
|
||||
from test.support import requires_zlib
|
||||
|
||||
from . import _path
|
||||
from ._path import FilesSpec
|
||||
|
||||
|
||||
try:
|
||||
from importlib import resources # type: ignore
|
||||
|
||||
getattr(resources, 'files')
|
||||
getattr(resources, 'as_file')
|
||||
except (ImportError, AttributeError):
|
||||
import importlib_resources as resources # type: ignore
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def tempdir():
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
try:
|
||||
yield pathlib.Path(tmpdir)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def save_cwd():
|
||||
orig = os.getcwd()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.chdir(orig)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def tempdir_as_cwd():
|
||||
with tempdir() as tmp:
|
||||
with save_cwd():
|
||||
os.chdir(str(tmp))
|
||||
yield tmp
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def install_finder(finder):
|
||||
sys.meta_path.append(finder)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
sys.meta_path.remove(finder)
|
||||
|
||||
|
||||
class Fixtures:
|
||||
def setUp(self):
|
||||
self.fixtures = contextlib.ExitStack()
|
||||
self.addCleanup(self.fixtures.close)
|
||||
|
||||
|
||||
class SiteDir(Fixtures):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.site_dir = self.fixtures.enter_context(tempdir())
|
||||
|
||||
|
||||
class OnSysPath(Fixtures):
|
||||
@staticmethod
|
||||
@contextlib.contextmanager
|
||||
def add_sys_path(dir):
|
||||
sys.path[:0] = [str(dir)]
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
sys.path.remove(str(dir))
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.fixtures.enter_context(self.add_sys_path(self.site_dir))
|
||||
self.fixtures.enter_context(import_helper.isolated_modules())
|
||||
|
||||
|
||||
class SiteBuilder(SiteDir):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
for cls in self.__class__.mro():
|
||||
with contextlib.suppress(AttributeError):
|
||||
build_files(cls.files, prefix=self.site_dir)
|
||||
|
||||
|
||||
class DistInfoPkg(OnSysPath, SiteBuilder):
|
||||
files: FilesSpec = {
|
||||
"distinfo_pkg-1.0.0.dist-info": {
|
||||
"METADATA": """
|
||||
Name: distinfo-pkg
|
||||
Author: Steven Ma
|
||||
Version: 1.0.0
|
||||
Requires-Dist: wheel >= 1.0
|
||||
Requires-Dist: pytest; extra == 'test'
|
||||
Keywords: sample package
|
||||
|
||||
Once upon a time
|
||||
There was a distinfo pkg
|
||||
""",
|
||||
"RECORD": "mod.py,sha256=abc,20\n",
|
||||
"entry_points.txt": """
|
||||
[entries]
|
||||
main = mod:main
|
||||
ns:sub = mod:main
|
||||
""",
|
||||
},
|
||||
"mod.py": """
|
||||
def main():
|
||||
print("hello world")
|
||||
""",
|
||||
}
|
||||
|
||||
def make_uppercase(self):
|
||||
"""
|
||||
Rewrite metadata with everything uppercase.
|
||||
"""
|
||||
shutil.rmtree(self.site_dir / "distinfo_pkg-1.0.0.dist-info")
|
||||
files = copy.deepcopy(DistInfoPkg.files)
|
||||
info = files["distinfo_pkg-1.0.0.dist-info"]
|
||||
info["METADATA"] = info["METADATA"].upper()
|
||||
build_files(files, self.site_dir)
|
||||
|
||||
|
||||
class DistInfoPkgEditable(DistInfoPkg):
|
||||
"""
|
||||
Package with a PEP 660 direct_url.json.
|
||||
"""
|
||||
|
||||
some_hash = '524127ce937f7cb65665130c695abd18ca386f60bb29687efb976faa1596fdcc'
|
||||
files: FilesSpec = {
|
||||
'distinfo_pkg-1.0.0.dist-info': {
|
||||
'direct_url.json': json.dumps({
|
||||
"archive_info": {
|
||||
"hash": f"sha256={some_hash}",
|
||||
"hashes": {"sha256": f"{some_hash}"},
|
||||
},
|
||||
"url": "file:///path/to/distinfo_pkg-1.0.0.editable-py3-none-any.whl",
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class DistInfoPkgWithDot(OnSysPath, SiteBuilder):
|
||||
files: FilesSpec = {
|
||||
"pkg_dot-1.0.0.dist-info": {
|
||||
"METADATA": """
|
||||
Name: pkg.dot
|
||||
Version: 1.0.0
|
||||
""",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class DistInfoPkgWithDotLegacy(OnSysPath, SiteBuilder):
|
||||
files: FilesSpec = {
|
||||
"pkg.dot-1.0.0.dist-info": {
|
||||
"METADATA": """
|
||||
Name: pkg.dot
|
||||
Version: 1.0.0
|
||||
""",
|
||||
},
|
||||
"pkg.lot.egg-info": {
|
||||
"METADATA": """
|
||||
Name: pkg.lot
|
||||
Version: 1.0.0
|
||||
""",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class DistInfoPkgOffPath(SiteBuilder):
|
||||
files = DistInfoPkg.files
|
||||
|
||||
|
||||
class EggInfoPkg(OnSysPath, SiteBuilder):
|
||||
files: FilesSpec = {
|
||||
"egginfo_pkg.egg-info": {
|
||||
"PKG-INFO": """
|
||||
Name: egginfo-pkg
|
||||
Author: Steven Ma
|
||||
License: Unknown
|
||||
Version: 1.0.0
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
Keywords: sample package
|
||||
Description: Once upon a time
|
||||
There was an egginfo package
|
||||
""",
|
||||
"SOURCES.txt": """
|
||||
mod.py
|
||||
egginfo_pkg.egg-info/top_level.txt
|
||||
""",
|
||||
"entry_points.txt": """
|
||||
[entries]
|
||||
main = mod:main
|
||||
""",
|
||||
"requires.txt": """
|
||||
wheel >= 1.0; python_version >= "2.7"
|
||||
[test]
|
||||
pytest
|
||||
""",
|
||||
"top_level.txt": "mod\n",
|
||||
},
|
||||
"mod.py": """
|
||||
def main():
|
||||
print("hello world")
|
||||
""",
|
||||
}
|
||||
|
||||
|
||||
class EggInfoPkgPipInstalledNoToplevel(OnSysPath, SiteBuilder):
|
||||
files: FilesSpec = {
|
||||
"egg_with_module_pkg.egg-info": {
|
||||
"PKG-INFO": "Name: egg_with_module-pkg",
|
||||
# SOURCES.txt is made from the source archive, and contains files
|
||||
# (setup.py) that are not present after installation.
|
||||
"SOURCES.txt": """
|
||||
egg_with_module.py
|
||||
setup.py
|
||||
egg_with_module_pkg.egg-info/PKG-INFO
|
||||
egg_with_module_pkg.egg-info/SOURCES.txt
|
||||
egg_with_module_pkg.egg-info/top_level.txt
|
||||
""",
|
||||
# installed-files.txt is written by pip, and is a strictly more
|
||||
# accurate source than SOURCES.txt as to the installed contents of
|
||||
# the package.
|
||||
"installed-files.txt": """
|
||||
../egg_with_module.py
|
||||
PKG-INFO
|
||||
SOURCES.txt
|
||||
top_level.txt
|
||||
""",
|
||||
# missing top_level.txt (to trigger fallback to installed-files.txt)
|
||||
},
|
||||
"egg_with_module.py": """
|
||||
def main():
|
||||
print("hello world")
|
||||
""",
|
||||
}
|
||||
|
||||
|
||||
class EggInfoPkgPipInstalledExternalDataFiles(OnSysPath, SiteBuilder):
|
||||
files: FilesSpec = {
|
||||
"egg_with_module_pkg.egg-info": {
|
||||
"PKG-INFO": "Name: egg_with_module-pkg",
|
||||
# SOURCES.txt is made from the source archive, and contains files
|
||||
# (setup.py) that are not present after installation.
|
||||
"SOURCES.txt": """
|
||||
egg_with_module.py
|
||||
setup.py
|
||||
egg_with_module.json
|
||||
egg_with_module_pkg.egg-info/PKG-INFO
|
||||
egg_with_module_pkg.egg-info/SOURCES.txt
|
||||
egg_with_module_pkg.egg-info/top_level.txt
|
||||
""",
|
||||
# installed-files.txt is written by pip, and is a strictly more
|
||||
# accurate source than SOURCES.txt as to the installed contents of
|
||||
# the package.
|
||||
"installed-files.txt": """
|
||||
../../../etc/jupyter/jupyter_notebook_config.d/relative.json
|
||||
/etc/jupyter/jupyter_notebook_config.d/absolute.json
|
||||
../egg_with_module.py
|
||||
PKG-INFO
|
||||
SOURCES.txt
|
||||
top_level.txt
|
||||
""",
|
||||
# missing top_level.txt (to trigger fallback to installed-files.txt)
|
||||
},
|
||||
"egg_with_module.py": """
|
||||
def main():
|
||||
print("hello world")
|
||||
""",
|
||||
}
|
||||
|
||||
|
||||
class EggInfoPkgPipInstalledNoModules(OnSysPath, SiteBuilder):
|
||||
files: FilesSpec = {
|
||||
"egg_with_no_modules_pkg.egg-info": {
|
||||
"PKG-INFO": "Name: egg_with_no_modules-pkg",
|
||||
# SOURCES.txt is made from the source archive, and contains files
|
||||
# (setup.py) that are not present after installation.
|
||||
"SOURCES.txt": """
|
||||
setup.py
|
||||
egg_with_no_modules_pkg.egg-info/PKG-INFO
|
||||
egg_with_no_modules_pkg.egg-info/SOURCES.txt
|
||||
egg_with_no_modules_pkg.egg-info/top_level.txt
|
||||
""",
|
||||
# installed-files.txt is written by pip, and is a strictly more
|
||||
# accurate source than SOURCES.txt as to the installed contents of
|
||||
# the package.
|
||||
"installed-files.txt": """
|
||||
PKG-INFO
|
||||
SOURCES.txt
|
||||
top_level.txt
|
||||
""",
|
||||
# top_level.txt correctly reflects that no modules are installed
|
||||
"top_level.txt": b"\n",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class EggInfoPkgSourcesFallback(OnSysPath, SiteBuilder):
|
||||
files: FilesSpec = {
|
||||
"sources_fallback_pkg.egg-info": {
|
||||
"PKG-INFO": "Name: sources_fallback-pkg",
|
||||
# SOURCES.txt is made from the source archive, and contains files
|
||||
# (setup.py) that are not present after installation.
|
||||
"SOURCES.txt": """
|
||||
sources_fallback.py
|
||||
setup.py
|
||||
sources_fallback_pkg.egg-info/PKG-INFO
|
||||
sources_fallback_pkg.egg-info/SOURCES.txt
|
||||
""",
|
||||
# missing installed-files.txt (i.e. not installed by pip) and
|
||||
# missing top_level.txt (to trigger fallback to SOURCES.txt)
|
||||
},
|
||||
"sources_fallback.py": """
|
||||
def main():
|
||||
print("hello world")
|
||||
""",
|
||||
}
|
||||
|
||||
|
||||
class EggInfoFile(OnSysPath, SiteBuilder):
|
||||
files: FilesSpec = {
|
||||
"egginfo_file.egg-info": """
|
||||
Metadata-Version: 1.0
|
||||
Name: egginfo_file
|
||||
Version: 0.1
|
||||
Summary: An example package
|
||||
Home-page: www.example.com
|
||||
Author: Eric Haffa-Vee
|
||||
Author-email: eric@example.coms
|
||||
License: UNKNOWN
|
||||
Description: UNKNOWN
|
||||
Platform: UNKNOWN
|
||||
""",
|
||||
}
|
||||
|
||||
|
||||
# dedent all text strings before writing
|
||||
orig = _path.create.registry[str]
|
||||
_path.create.register(str, lambda content, path: orig(DALS(content), path))
|
||||
|
||||
|
||||
build_files = _path.build
|
||||
|
||||
|
||||
def build_record(file_defs):
|
||||
return ''.join(f'{name},,\n' for name in record_names(file_defs))
|
||||
|
||||
|
||||
def record_names(file_defs):
|
||||
recording = _path.Recording()
|
||||
_path.build(file_defs, recording)
|
||||
return recording.record
|
||||
|
||||
|
||||
class FileBuilder:
|
||||
def unicode_filename(self):
|
||||
return os_helper.FS_NONASCII or self.skip(
|
||||
"File system does not support non-ascii."
|
||||
)
|
||||
|
||||
|
||||
def DALS(str):
|
||||
"Dedent and left-strip"
|
||||
return textwrap.dedent(str).lstrip()
|
||||
|
||||
|
||||
@requires_zlib()
|
||||
class ZipFixtures:
|
||||
root = 'test.test_importlib.metadata.data'
|
||||
|
||||
def _fixture_on_path(self, filename):
|
||||
pkg_file = resources.files(self.root).joinpath(filename)
|
||||
file = self.resources.enter_context(resources.as_file(pkg_file))
|
||||
assert file.name.startswith('example'), file.name
|
||||
sys.path.insert(0, str(file))
|
||||
self.resources.callback(sys.path.pop, 0)
|
||||
|
||||
def setUp(self):
|
||||
# Add self.zip_name to the front of sys.path.
|
||||
self.resources = contextlib.ExitStack()
|
||||
self.addCleanup(self.resources.close)
|
||||
|
||||
|
||||
def parameterize(*args_set):
|
||||
"""Run test method with a series of parameters."""
|
||||
|
||||
def wrapper(func):
|
||||
@functools.wraps(func)
|
||||
def _inner(self):
|
||||
for args in args_set:
|
||||
with self.subTest(**args):
|
||||
func(self, **args)
|
||||
|
||||
return _inner
|
||||
|
||||
return wrapper
|
||||
10
Dependencies/Python/Lib/test/test_importlib/metadata/stubs.py
vendored
Normal file
10
Dependencies/Python/Lib/test/test_importlib/metadata/stubs.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import unittest
|
||||
|
||||
|
||||
class fake_filesystem_unittest:
|
||||
"""
|
||||
Stubbed version of the pyfakefs module
|
||||
"""
|
||||
class TestCase(unittest.TestCase):
|
||||
def setUpPyfakefs(self):
|
||||
self.skipTest("pyfakefs not available")
|
||||
323
Dependencies/Python/Lib/test/test_importlib/metadata/test_api.py
vendored
Normal file
323
Dependencies/Python/Lib/test/test_importlib/metadata/test_api.py
vendored
Normal file
@@ -0,0 +1,323 @@
|
||||
import re
|
||||
import textwrap
|
||||
import unittest
|
||||
import warnings
|
||||
import importlib
|
||||
import contextlib
|
||||
|
||||
from . import fixtures
|
||||
from importlib.metadata import (
|
||||
Distribution,
|
||||
PackageNotFoundError,
|
||||
distribution,
|
||||
entry_points,
|
||||
files,
|
||||
metadata,
|
||||
requires,
|
||||
version,
|
||||
)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def suppress_known_deprecation():
|
||||
with warnings.catch_warnings(record=True) as ctx:
|
||||
warnings.simplefilter('default', category=DeprecationWarning)
|
||||
yield ctx
|
||||
|
||||
|
||||
class APITests(
|
||||
fixtures.EggInfoPkg,
|
||||
fixtures.EggInfoPkgPipInstalledNoToplevel,
|
||||
fixtures.EggInfoPkgPipInstalledNoModules,
|
||||
fixtures.EggInfoPkgPipInstalledExternalDataFiles,
|
||||
fixtures.EggInfoPkgSourcesFallback,
|
||||
fixtures.DistInfoPkg,
|
||||
fixtures.DistInfoPkgWithDot,
|
||||
fixtures.EggInfoFile,
|
||||
unittest.TestCase,
|
||||
):
|
||||
version_pattern = r'\d+\.\d+(\.\d)?'
|
||||
|
||||
def test_retrieves_version_of_self(self):
|
||||
pkg_version = version('egginfo-pkg')
|
||||
assert isinstance(pkg_version, str)
|
||||
assert re.match(self.version_pattern, pkg_version)
|
||||
|
||||
def test_retrieves_version_of_distinfo_pkg(self):
|
||||
pkg_version = version('distinfo-pkg')
|
||||
assert isinstance(pkg_version, str)
|
||||
assert re.match(self.version_pattern, pkg_version)
|
||||
|
||||
def test_for_name_does_not_exist(self):
|
||||
with self.assertRaises(PackageNotFoundError):
|
||||
distribution('does-not-exist')
|
||||
|
||||
def test_name_normalization(self):
|
||||
names = 'pkg.dot', 'pkg_dot', 'pkg-dot', 'pkg..dot', 'Pkg.Dot'
|
||||
for name in names:
|
||||
with self.subTest(name):
|
||||
assert distribution(name).metadata['Name'] == 'pkg.dot'
|
||||
|
||||
def test_prefix_not_matched(self):
|
||||
prefixes = 'p', 'pkg', 'pkg.'
|
||||
for prefix in prefixes:
|
||||
with self.subTest(prefix):
|
||||
with self.assertRaises(PackageNotFoundError):
|
||||
distribution(prefix)
|
||||
|
||||
def test_for_top_level(self):
|
||||
tests = [
|
||||
('egginfo-pkg', 'mod'),
|
||||
('egg_with_no_modules-pkg', ''),
|
||||
]
|
||||
for pkg_name, expect_content in tests:
|
||||
with self.subTest(pkg_name):
|
||||
self.assertEqual(
|
||||
distribution(pkg_name).read_text('top_level.txt').strip(),
|
||||
expect_content,
|
||||
)
|
||||
|
||||
def test_read_text(self):
|
||||
tests = [
|
||||
('egginfo-pkg', 'mod\n'),
|
||||
('egg_with_no_modules-pkg', '\n'),
|
||||
]
|
||||
for pkg_name, expect_content in tests:
|
||||
with self.subTest(pkg_name):
|
||||
top_level = [
|
||||
path for path in files(pkg_name) if path.name == 'top_level.txt'
|
||||
][0]
|
||||
self.assertEqual(top_level.read_text(), expect_content)
|
||||
|
||||
def test_entry_points(self):
|
||||
eps = entry_points()
|
||||
assert 'entries' in eps.groups
|
||||
entries = eps.select(group='entries')
|
||||
assert 'main' in entries.names
|
||||
ep = entries['main']
|
||||
self.assertEqual(ep.value, 'mod:main')
|
||||
self.assertEqual(ep.extras, [])
|
||||
|
||||
def test_entry_points_distribution(self):
|
||||
entries = entry_points(group='entries')
|
||||
for entry in ("main", "ns:sub"):
|
||||
ep = entries[entry]
|
||||
self.assertIn(ep.dist.name, ('distinfo-pkg', 'egginfo-pkg'))
|
||||
self.assertEqual(ep.dist.version, "1.0.0")
|
||||
|
||||
def test_entry_points_unique_packages_normalized(self):
|
||||
"""
|
||||
Entry points should only be exposed for the first package
|
||||
on sys.path with a given name (even when normalized).
|
||||
"""
|
||||
alt_site_dir = self.fixtures.enter_context(fixtures.tempdir())
|
||||
self.fixtures.enter_context(self.add_sys_path(alt_site_dir))
|
||||
alt_pkg = {
|
||||
"DistInfo_pkg-1.1.0.dist-info": {
|
||||
"METADATA": """
|
||||
Name: distinfo-pkg
|
||||
Version: 1.1.0
|
||||
""",
|
||||
"entry_points.txt": """
|
||||
[entries]
|
||||
main = mod:altmain
|
||||
""",
|
||||
},
|
||||
}
|
||||
fixtures.build_files(alt_pkg, alt_site_dir)
|
||||
entries = entry_points(group='entries')
|
||||
assert not any(
|
||||
ep.dist.name == 'distinfo-pkg' and ep.dist.version == '1.0.0'
|
||||
for ep in entries
|
||||
)
|
||||
# ns:sub doesn't exist in alt_pkg
|
||||
assert 'ns:sub' not in entries.names
|
||||
|
||||
def test_entry_points_missing_name(self):
|
||||
with self.assertRaises(KeyError):
|
||||
entry_points(group='entries')['missing']
|
||||
|
||||
def test_entry_points_missing_group(self):
|
||||
assert entry_points(group='missing') == ()
|
||||
|
||||
def test_entry_points_allows_no_attributes(self):
|
||||
ep = entry_points().select(group='entries', name='main')
|
||||
with self.assertRaises(AttributeError):
|
||||
ep.foo = 4
|
||||
|
||||
def test_metadata_for_this_package(self):
|
||||
md = metadata('egginfo-pkg')
|
||||
assert md['author'] == 'Steven Ma'
|
||||
assert md['LICENSE'] == 'Unknown'
|
||||
assert md['Name'] == 'egginfo-pkg'
|
||||
classifiers = md.get_all('Classifier')
|
||||
assert 'Topic :: Software Development :: Libraries' in classifiers
|
||||
|
||||
def test_missing_key_legacy(self):
|
||||
"""
|
||||
Requesting a missing key will still return None, but warn.
|
||||
"""
|
||||
md = metadata('distinfo-pkg')
|
||||
with suppress_known_deprecation():
|
||||
assert md['does-not-exist'] is None
|
||||
|
||||
def test_get_key(self):
|
||||
"""
|
||||
Getting a key gets the key.
|
||||
"""
|
||||
md = metadata('egginfo-pkg')
|
||||
assert md.get('Name') == 'egginfo-pkg'
|
||||
|
||||
def test_get_missing_key(self):
|
||||
"""
|
||||
Requesting a missing key will return None.
|
||||
"""
|
||||
md = metadata('distinfo-pkg')
|
||||
assert md.get('does-not-exist') is None
|
||||
|
||||
@staticmethod
|
||||
def _test_files(files):
|
||||
root = files[0].root
|
||||
for file in files:
|
||||
assert file.root == root
|
||||
assert not file.hash or file.hash.value
|
||||
assert not file.hash or file.hash.mode == 'sha256'
|
||||
assert not file.size or file.size >= 0
|
||||
assert file.locate().exists()
|
||||
assert isinstance(file.read_binary(), bytes)
|
||||
if file.name.endswith('.py'):
|
||||
file.read_text()
|
||||
|
||||
def test_file_hash_repr(self):
|
||||
util = [p for p in files('distinfo-pkg') if p.name == 'mod.py'][0]
|
||||
self.assertRegex(repr(util.hash), '<FileHash mode: sha256 value: .*>')
|
||||
|
||||
def test_files_dist_info(self):
|
||||
self._test_files(files('distinfo-pkg'))
|
||||
|
||||
def test_files_egg_info(self):
|
||||
self._test_files(files('egginfo-pkg'))
|
||||
self._test_files(files('egg_with_module-pkg'))
|
||||
self._test_files(files('egg_with_no_modules-pkg'))
|
||||
self._test_files(files('sources_fallback-pkg'))
|
||||
|
||||
def test_version_egg_info_file(self):
|
||||
self.assertEqual(version('egginfo-file'), '0.1')
|
||||
|
||||
def test_requires_egg_info_file(self):
|
||||
requirements = requires('egginfo-file')
|
||||
self.assertIsNone(requirements)
|
||||
|
||||
def test_requires_egg_info(self):
|
||||
deps = requires('egginfo-pkg')
|
||||
assert len(deps) == 2
|
||||
assert any(dep == 'wheel >= 1.0; python_version >= "2.7"' for dep in deps)
|
||||
|
||||
def test_requires_egg_info_empty(self):
|
||||
fixtures.build_files(
|
||||
{
|
||||
'requires.txt': '',
|
||||
},
|
||||
self.site_dir.joinpath('egginfo_pkg.egg-info'),
|
||||
)
|
||||
deps = requires('egginfo-pkg')
|
||||
assert deps == []
|
||||
|
||||
def test_requires_dist_info(self):
|
||||
deps = requires('distinfo-pkg')
|
||||
assert len(deps) == 2
|
||||
assert all(deps)
|
||||
assert 'wheel >= 1.0' in deps
|
||||
assert "pytest; extra == 'test'" in deps
|
||||
|
||||
def test_more_complex_deps_requires_text(self):
|
||||
requires = textwrap.dedent(
|
||||
"""
|
||||
dep1
|
||||
dep2
|
||||
|
||||
[:python_version < "3"]
|
||||
dep3
|
||||
|
||||
[extra1]
|
||||
dep4
|
||||
dep6@ git+https://example.com/python/dep.git@v1.0.0
|
||||
|
||||
[extra2:python_version < "3"]
|
||||
dep5
|
||||
"""
|
||||
)
|
||||
deps = sorted(Distribution._deps_from_requires_text(requires))
|
||||
expected = [
|
||||
'dep1',
|
||||
'dep2',
|
||||
'dep3; python_version < "3"',
|
||||
'dep4; extra == "extra1"',
|
||||
'dep5; (python_version < "3") and extra == "extra2"',
|
||||
'dep6@ git+https://example.com/python/dep.git@v1.0.0 ; extra == "extra1"',
|
||||
]
|
||||
# It's important that the environment marker expression be
|
||||
# wrapped in parentheses to avoid the following 'and' binding more
|
||||
# tightly than some other part of the environment expression.
|
||||
|
||||
assert deps == expected
|
||||
|
||||
def test_as_json(self):
|
||||
md = metadata('distinfo-pkg').json
|
||||
assert 'name' in md
|
||||
assert md['keywords'] == ['sample', 'package']
|
||||
desc = md['description']
|
||||
assert desc.startswith('Once upon a time\nThere was')
|
||||
assert len(md['requires_dist']) == 2
|
||||
|
||||
def test_as_json_egg_info(self):
|
||||
md = metadata('egginfo-pkg').json
|
||||
assert 'name' in md
|
||||
assert md['keywords'] == ['sample', 'package']
|
||||
desc = md['description']
|
||||
assert desc.startswith('Once upon a time\nThere was')
|
||||
assert len(md['classifier']) == 2
|
||||
|
||||
def test_as_json_odd_case(self):
|
||||
self.make_uppercase()
|
||||
md = metadata('distinfo-pkg').json
|
||||
assert 'name' in md
|
||||
assert len(md['requires_dist']) == 2
|
||||
assert md['keywords'] == ['SAMPLE', 'PACKAGE']
|
||||
|
||||
|
||||
class LegacyDots(fixtures.DistInfoPkgWithDotLegacy, unittest.TestCase):
|
||||
def test_name_normalization(self):
|
||||
names = 'pkg.dot', 'pkg_dot', 'pkg-dot', 'pkg..dot', 'Pkg.Dot'
|
||||
for name in names:
|
||||
with self.subTest(name):
|
||||
assert distribution(name).metadata['Name'] == 'pkg.dot'
|
||||
|
||||
def test_name_normalization_versionless_egg_info(self):
|
||||
names = 'pkg.lot', 'pkg_lot', 'pkg-lot', 'pkg..lot', 'Pkg.Lot'
|
||||
for name in names:
|
||||
with self.subTest(name):
|
||||
assert distribution(name).metadata['Name'] == 'pkg.lot'
|
||||
|
||||
|
||||
class OffSysPathTests(fixtures.DistInfoPkgOffPath, unittest.TestCase):
|
||||
def test_find_distributions_specified_path(self):
|
||||
dists = Distribution.discover(path=[str(self.site_dir)])
|
||||
assert any(dist.metadata['Name'] == 'distinfo-pkg' for dist in dists)
|
||||
|
||||
def test_distribution_at_pathlib(self):
|
||||
"""Demonstrate how to load metadata direct from a directory."""
|
||||
dist_info_path = self.site_dir / 'distinfo_pkg-1.0.0.dist-info'
|
||||
dist = Distribution.at(dist_info_path)
|
||||
assert dist.version == '1.0.0'
|
||||
|
||||
def test_distribution_at_str(self):
|
||||
dist_info_path = self.site_dir / 'distinfo_pkg-1.0.0.dist-info'
|
||||
dist = Distribution.at(str(dist_info_path))
|
||||
assert dist.version == '1.0.0'
|
||||
|
||||
|
||||
class InvalidateCache(unittest.TestCase):
|
||||
def test_invalidate_cache(self):
|
||||
# No externally observable behavior, but ensures test coverage...
|
||||
importlib.invalidate_caches()
|
||||
468
Dependencies/Python/Lib/test/test_importlib/metadata/test_main.py
vendored
Normal file
468
Dependencies/Python/Lib/test/test_importlib/metadata/test_main.py
vendored
Normal file
@@ -0,0 +1,468 @@
|
||||
import re
|
||||
import pickle
|
||||
import unittest
|
||||
import warnings
|
||||
import importlib
|
||||
import importlib.metadata
|
||||
import contextlib
|
||||
from test.support import os_helper
|
||||
|
||||
try:
|
||||
import pyfakefs.fake_filesystem_unittest as ffs
|
||||
except ImportError:
|
||||
from .stubs import fake_filesystem_unittest as ffs
|
||||
|
||||
from . import fixtures
|
||||
from ._context import suppress
|
||||
from ._path import Symlink
|
||||
from importlib.metadata import (
|
||||
Distribution,
|
||||
EntryPoint,
|
||||
PackageNotFoundError,
|
||||
_unique,
|
||||
distributions,
|
||||
entry_points,
|
||||
metadata,
|
||||
packages_distributions,
|
||||
version,
|
||||
)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def suppress_known_deprecation():
|
||||
with warnings.catch_warnings(record=True) as ctx:
|
||||
warnings.simplefilter('default', category=DeprecationWarning)
|
||||
yield ctx
|
||||
|
||||
|
||||
class BasicTests(fixtures.DistInfoPkg, unittest.TestCase):
|
||||
version_pattern = r'\d+\.\d+(\.\d)?'
|
||||
|
||||
def test_retrieves_version_of_self(self):
|
||||
dist = Distribution.from_name('distinfo-pkg')
|
||||
assert isinstance(dist.version, str)
|
||||
assert re.match(self.version_pattern, dist.version)
|
||||
|
||||
def test_for_name_does_not_exist(self):
|
||||
with self.assertRaises(PackageNotFoundError):
|
||||
Distribution.from_name('does-not-exist')
|
||||
|
||||
def test_package_not_found_mentions_metadata(self):
|
||||
"""
|
||||
When a package is not found, that could indicate that the
|
||||
package is not installed or that it is installed without
|
||||
metadata. Ensure the exception mentions metadata to help
|
||||
guide users toward the cause. See #124.
|
||||
"""
|
||||
with self.assertRaises(PackageNotFoundError) as ctx:
|
||||
Distribution.from_name('does-not-exist')
|
||||
|
||||
assert "metadata" in str(ctx.exception)
|
||||
|
||||
# expected to fail until ABC is enforced
|
||||
@suppress(AssertionError)
|
||||
@suppress_known_deprecation()
|
||||
def test_abc_enforced(self):
|
||||
with self.assertRaises(TypeError):
|
||||
type('DistributionSubclass', (Distribution,), {})()
|
||||
|
||||
@fixtures.parameterize(
|
||||
dict(name=None),
|
||||
dict(name=''),
|
||||
)
|
||||
def test_invalid_inputs_to_from_name(self, name):
|
||||
with self.assertRaises(Exception):
|
||||
Distribution.from_name(name)
|
||||
|
||||
|
||||
class ImportTests(fixtures.DistInfoPkg, unittest.TestCase):
|
||||
def test_import_nonexistent_module(self):
|
||||
# Ensure that the MetadataPathFinder does not crash an import of a
|
||||
# non-existent module.
|
||||
with self.assertRaises(ImportError):
|
||||
importlib.import_module('does_not_exist')
|
||||
|
||||
def test_resolve(self):
|
||||
ep = entry_points(group='entries')['main']
|
||||
self.assertEqual(ep.load().__name__, "main")
|
||||
|
||||
def test_entrypoint_with_colon_in_name(self):
|
||||
ep = entry_points(group='entries')['ns:sub']
|
||||
self.assertEqual(ep.value, 'mod:main')
|
||||
|
||||
def test_resolve_without_attr(self):
|
||||
ep = EntryPoint(
|
||||
name='ep',
|
||||
value='importlib.metadata',
|
||||
group='grp',
|
||||
)
|
||||
assert ep.load() is importlib.metadata
|
||||
|
||||
|
||||
class NameNormalizationTests(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase):
|
||||
@staticmethod
|
||||
def make_pkg(name):
|
||||
"""
|
||||
Create minimal metadata for a dist-info package with
|
||||
the indicated name on the file system.
|
||||
"""
|
||||
return {
|
||||
f'{name}.dist-info': {
|
||||
'METADATA': 'VERSION: 1.0\n',
|
||||
},
|
||||
}
|
||||
|
||||
def test_dashes_in_dist_name_found_as_underscores(self):
|
||||
"""
|
||||
For a package with a dash in the name, the dist-info metadata
|
||||
uses underscores in the name. Ensure the metadata loads.
|
||||
"""
|
||||
fixtures.build_files(self.make_pkg('my_pkg'), self.site_dir)
|
||||
assert version('my-pkg') == '1.0'
|
||||
|
||||
def test_dist_name_found_as_any_case(self):
|
||||
"""
|
||||
Ensure the metadata loads when queried with any case.
|
||||
"""
|
||||
pkg_name = 'CherryPy'
|
||||
fixtures.build_files(self.make_pkg(pkg_name), self.site_dir)
|
||||
assert version(pkg_name) == '1.0'
|
||||
assert version(pkg_name.lower()) == '1.0'
|
||||
assert version(pkg_name.upper()) == '1.0'
|
||||
|
||||
def test_unique_distributions(self):
|
||||
"""
|
||||
Two distributions varying only by non-normalized name on
|
||||
the file system should resolve as the same.
|
||||
"""
|
||||
fixtures.build_files(self.make_pkg('abc'), self.site_dir)
|
||||
before = list(_unique(distributions()))
|
||||
|
||||
alt_site_dir = self.fixtures.enter_context(fixtures.tempdir())
|
||||
self.fixtures.enter_context(self.add_sys_path(alt_site_dir))
|
||||
fixtures.build_files(self.make_pkg('ABC'), alt_site_dir)
|
||||
after = list(_unique(distributions()))
|
||||
|
||||
assert len(after) == len(before)
|
||||
|
||||
|
||||
class NonASCIITests(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase):
|
||||
@staticmethod
|
||||
def pkg_with_non_ascii_description(site_dir):
|
||||
"""
|
||||
Create minimal metadata for a package with non-ASCII in
|
||||
the description.
|
||||
"""
|
||||
contents = {
|
||||
'portend.dist-info': {
|
||||
'METADATA': 'Description: pôrˈtend',
|
||||
},
|
||||
}
|
||||
fixtures.build_files(contents, site_dir)
|
||||
return 'portend'
|
||||
|
||||
@staticmethod
|
||||
def pkg_with_non_ascii_description_egg_info(site_dir):
|
||||
"""
|
||||
Create minimal metadata for an egg-info package with
|
||||
non-ASCII in the description.
|
||||
"""
|
||||
contents = {
|
||||
'portend.dist-info': {
|
||||
'METADATA': """
|
||||
Name: portend
|
||||
|
||||
pôrˈtend""",
|
||||
},
|
||||
}
|
||||
fixtures.build_files(contents, site_dir)
|
||||
return 'portend'
|
||||
|
||||
def test_metadata_loads(self):
|
||||
pkg_name = self.pkg_with_non_ascii_description(self.site_dir)
|
||||
meta = metadata(pkg_name)
|
||||
assert meta['Description'] == 'pôrˈtend'
|
||||
|
||||
def test_metadata_loads_egg_info(self):
|
||||
pkg_name = self.pkg_with_non_ascii_description_egg_info(self.site_dir)
|
||||
meta = metadata(pkg_name)
|
||||
assert meta['Description'] == 'pôrˈtend'
|
||||
|
||||
|
||||
class DiscoveryTests(
|
||||
fixtures.EggInfoPkg,
|
||||
fixtures.EggInfoPkgPipInstalledNoToplevel,
|
||||
fixtures.EggInfoPkgPipInstalledNoModules,
|
||||
fixtures.EggInfoPkgSourcesFallback,
|
||||
fixtures.DistInfoPkg,
|
||||
unittest.TestCase,
|
||||
):
|
||||
def test_package_discovery(self):
|
||||
dists = list(distributions())
|
||||
assert all(isinstance(dist, Distribution) for dist in dists)
|
||||
assert any(dist.metadata['Name'] == 'egginfo-pkg' for dist in dists)
|
||||
assert any(dist.metadata['Name'] == 'egg_with_module-pkg' for dist in dists)
|
||||
assert any(dist.metadata['Name'] == 'egg_with_no_modules-pkg' for dist in dists)
|
||||
assert any(dist.metadata['Name'] == 'sources_fallback-pkg' for dist in dists)
|
||||
assert any(dist.metadata['Name'] == 'distinfo-pkg' for dist in dists)
|
||||
|
||||
def test_invalid_usage(self):
|
||||
with self.assertRaises(ValueError):
|
||||
list(distributions(context='something', name='else'))
|
||||
|
||||
def test_interleaved_discovery(self):
|
||||
"""
|
||||
Ensure interleaved searches are safe.
|
||||
|
||||
When the search is cached, it is possible for searches to be
|
||||
interleaved, so make sure those use-cases are safe.
|
||||
|
||||
Ref #293
|
||||
"""
|
||||
dists = distributions()
|
||||
next(dists)
|
||||
version('egginfo-pkg')
|
||||
next(dists)
|
||||
|
||||
|
||||
class DirectoryTest(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase):
|
||||
def test_egg_info(self):
|
||||
# make an `EGG-INFO` directory that's unrelated
|
||||
self.site_dir.joinpath('EGG-INFO').mkdir()
|
||||
# used to crash with `IsADirectoryError`
|
||||
with self.assertRaises(PackageNotFoundError):
|
||||
version('unknown-package')
|
||||
|
||||
def test_egg(self):
|
||||
egg = self.site_dir.joinpath('foo-3.6.egg')
|
||||
egg.mkdir()
|
||||
with self.add_sys_path(egg):
|
||||
with self.assertRaises(PackageNotFoundError):
|
||||
version('foo')
|
||||
|
||||
|
||||
class MissingSysPath(fixtures.OnSysPath, unittest.TestCase):
|
||||
site_dir = '/does-not-exist'
|
||||
|
||||
def test_discovery(self):
|
||||
"""
|
||||
Discovering distributions should succeed even if
|
||||
there is an invalid path on sys.path.
|
||||
"""
|
||||
importlib.metadata.distributions()
|
||||
|
||||
|
||||
class InaccessibleSysPath(fixtures.OnSysPath, ffs.TestCase):
|
||||
site_dir = '/access-denied'
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.setUpPyfakefs()
|
||||
self.fs.create_dir(self.site_dir, perm_bits=000)
|
||||
|
||||
def test_discovery(self):
|
||||
"""
|
||||
Discovering distributions should succeed even if
|
||||
there is an invalid path on sys.path.
|
||||
"""
|
||||
list(importlib.metadata.distributions())
|
||||
|
||||
|
||||
class TestEntryPoints(unittest.TestCase):
|
||||
def __init__(self, *args):
|
||||
super().__init__(*args)
|
||||
self.ep = importlib.metadata.EntryPoint(
|
||||
name='name', value='value', group='group'
|
||||
)
|
||||
|
||||
def test_entry_point_pickleable(self):
|
||||
revived = pickle.loads(pickle.dumps(self.ep))
|
||||
assert revived == self.ep
|
||||
|
||||
def test_positional_args(self):
|
||||
"""
|
||||
Capture legacy (namedtuple) construction, discouraged.
|
||||
"""
|
||||
EntryPoint('name', 'value', 'group')
|
||||
|
||||
def test_immutable(self):
|
||||
"""EntryPoints should be immutable"""
|
||||
with self.assertRaises(AttributeError):
|
||||
self.ep.name = 'badactor'
|
||||
|
||||
def test_repr(self):
|
||||
assert 'EntryPoint' in repr(self.ep)
|
||||
assert 'name=' in repr(self.ep)
|
||||
assert "'name'" in repr(self.ep)
|
||||
|
||||
def test_hashable(self):
|
||||
"""EntryPoints should be hashable"""
|
||||
hash(self.ep)
|
||||
|
||||
def test_module(self):
|
||||
assert self.ep.module == 'value'
|
||||
|
||||
def test_attr(self):
|
||||
assert self.ep.attr is None
|
||||
|
||||
def test_sortable(self):
|
||||
"""
|
||||
EntryPoint objects are sortable, but result is undefined.
|
||||
"""
|
||||
sorted([
|
||||
EntryPoint(name='b', value='val', group='group'),
|
||||
EntryPoint(name='a', value='val', group='group'),
|
||||
])
|
||||
|
||||
|
||||
class FileSystem(
|
||||
fixtures.OnSysPath, fixtures.SiteDir, fixtures.FileBuilder, unittest.TestCase
|
||||
):
|
||||
def test_unicode_dir_on_sys_path(self):
|
||||
"""
|
||||
Ensure a Unicode subdirectory of a directory on sys.path
|
||||
does not crash.
|
||||
"""
|
||||
fixtures.build_files(
|
||||
{self.unicode_filename(): {}},
|
||||
prefix=self.site_dir,
|
||||
)
|
||||
list(distributions())
|
||||
|
||||
|
||||
class PackagesDistributionsPrebuiltTest(fixtures.ZipFixtures, unittest.TestCase):
|
||||
def test_packages_distributions_example(self):
|
||||
self._fixture_on_path('example-21.12-py3-none-any.whl')
|
||||
assert packages_distributions()['example'] == ['example']
|
||||
|
||||
def test_packages_distributions_example2(self):
|
||||
"""
|
||||
Test packages_distributions on a wheel built
|
||||
by trampolim.
|
||||
"""
|
||||
self._fixture_on_path('example2-1.0.0-py3-none-any.whl')
|
||||
assert packages_distributions()['example2'] == ['example2']
|
||||
|
||||
|
||||
class PackagesDistributionsTest(
|
||||
fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase
|
||||
):
|
||||
def test_packages_distributions_neither_toplevel_nor_files(self):
|
||||
"""
|
||||
Test a package built without 'top-level.txt' or a file list.
|
||||
"""
|
||||
fixtures.build_files(
|
||||
{
|
||||
'trim_example-1.0.0.dist-info': {
|
||||
'METADATA': """
|
||||
Name: trim_example
|
||||
Version: 1.0.0
|
||||
""",
|
||||
}
|
||||
},
|
||||
prefix=self.site_dir,
|
||||
)
|
||||
packages_distributions()
|
||||
|
||||
def test_packages_distributions_all_module_types(self):
|
||||
"""
|
||||
Test top-level modules detected on a package without 'top-level.txt'.
|
||||
"""
|
||||
suffixes = importlib.machinery.all_suffixes()
|
||||
metadata = dict(
|
||||
METADATA="""
|
||||
Name: all_distributions
|
||||
Version: 1.0.0
|
||||
""",
|
||||
)
|
||||
files = {
|
||||
'all_distributions-1.0.0.dist-info': metadata,
|
||||
}
|
||||
for i, suffix in enumerate(suffixes):
|
||||
files.update({
|
||||
f'importable-name {i}{suffix}': '',
|
||||
f'in_namespace_{i}': {
|
||||
f'mod{suffix}': '',
|
||||
},
|
||||
f'in_package_{i}': {
|
||||
'__init__.py': '',
|
||||
f'mod{suffix}': '',
|
||||
},
|
||||
})
|
||||
metadata.update(RECORD=fixtures.build_record(files))
|
||||
fixtures.build_files(files, prefix=self.site_dir)
|
||||
|
||||
distributions = packages_distributions()
|
||||
|
||||
for i in range(len(suffixes)):
|
||||
assert distributions[f'importable-name {i}'] == ['all_distributions']
|
||||
assert distributions[f'in_namespace_{i}'] == ['all_distributions']
|
||||
assert distributions[f'in_package_{i}'] == ['all_distributions']
|
||||
|
||||
assert not any(name.endswith('.dist-info') for name in distributions)
|
||||
|
||||
@os_helper.skip_unless_symlink
|
||||
def test_packages_distributions_symlinked_top_level(self) -> None:
|
||||
"""
|
||||
Distribution is resolvable from a simple top-level symlink in RECORD.
|
||||
See #452.
|
||||
"""
|
||||
|
||||
files: fixtures.FilesSpec = {
|
||||
"symlinked_pkg-1.0.0.dist-info": {
|
||||
"METADATA": """
|
||||
Name: symlinked-pkg
|
||||
Version: 1.0.0
|
||||
""",
|
||||
"RECORD": "symlinked,,\n",
|
||||
},
|
||||
".symlink.target": {},
|
||||
"symlinked": Symlink(".symlink.target"),
|
||||
}
|
||||
|
||||
fixtures.build_files(files, self.site_dir)
|
||||
assert packages_distributions()['symlinked'] == ['symlinked-pkg']
|
||||
|
||||
|
||||
class PackagesDistributionsEggTest(
|
||||
fixtures.EggInfoPkg,
|
||||
fixtures.EggInfoPkgPipInstalledNoToplevel,
|
||||
fixtures.EggInfoPkgPipInstalledNoModules,
|
||||
fixtures.EggInfoPkgSourcesFallback,
|
||||
unittest.TestCase,
|
||||
):
|
||||
def test_packages_distributions_on_eggs(self):
|
||||
"""
|
||||
Test old-style egg packages with a variation of 'top_level.txt',
|
||||
'SOURCES.txt', and 'installed-files.txt', available.
|
||||
"""
|
||||
distributions = packages_distributions()
|
||||
|
||||
def import_names_from_package(package_name):
|
||||
return {
|
||||
import_name
|
||||
for import_name, package_names in distributions.items()
|
||||
if package_name in package_names
|
||||
}
|
||||
|
||||
# egginfo-pkg declares one import ('mod') via top_level.txt
|
||||
assert import_names_from_package('egginfo-pkg') == {'mod'}
|
||||
|
||||
# egg_with_module-pkg has one import ('egg_with_module') inferred from
|
||||
# installed-files.txt (top_level.txt is missing)
|
||||
assert import_names_from_package('egg_with_module-pkg') == {'egg_with_module'}
|
||||
|
||||
# egg_with_no_modules-pkg should not be associated with any import names
|
||||
# (top_level.txt is empty, and installed-files.txt has no .py files)
|
||||
assert import_names_from_package('egg_with_no_modules-pkg') == set()
|
||||
|
||||
# sources_fallback-pkg has one import ('sources_fallback') inferred from
|
||||
# SOURCES.txt (top_level.txt and installed-files.txt is missing)
|
||||
assert import_names_from_package('sources_fallback-pkg') == {'sources_fallback'}
|
||||
|
||||
|
||||
class EditableDistributionTest(fixtures.DistInfoPkgEditable, unittest.TestCase):
|
||||
def test_origin(self):
|
||||
dist = Distribution.from_name('distinfo-pkg')
|
||||
assert dist.origin.url.endswith('.whl')
|
||||
assert dist.origin.archive_info.hashes.sha256
|
||||
62
Dependencies/Python/Lib/test/test_importlib/metadata/test_zip.py
vendored
Normal file
62
Dependencies/Python/Lib/test/test_importlib/metadata/test_zip.py
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from . import fixtures
|
||||
from importlib.metadata import (
|
||||
PackageNotFoundError,
|
||||
distribution,
|
||||
distributions,
|
||||
entry_points,
|
||||
files,
|
||||
version,
|
||||
)
|
||||
|
||||
|
||||
class TestZip(fixtures.ZipFixtures, unittest.TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self._fixture_on_path('example-21.12-py3-none-any.whl')
|
||||
|
||||
def test_zip_version(self):
|
||||
self.assertEqual(version('example'), '21.12')
|
||||
|
||||
def test_zip_version_does_not_match(self):
|
||||
with self.assertRaises(PackageNotFoundError):
|
||||
version('definitely-not-installed')
|
||||
|
||||
def test_zip_entry_points(self):
|
||||
scripts = entry_points(group='console_scripts')
|
||||
entry_point = scripts['example']
|
||||
self.assertEqual(entry_point.value, 'example:main')
|
||||
entry_point = scripts['Example']
|
||||
self.assertEqual(entry_point.value, 'example:main')
|
||||
|
||||
def test_missing_metadata(self):
|
||||
self.assertIsNone(distribution('example').read_text('does not exist'))
|
||||
|
||||
def test_case_insensitive(self):
|
||||
self.assertEqual(version('Example'), '21.12')
|
||||
|
||||
def test_files(self):
|
||||
for file in files('example'):
|
||||
path = str(file.dist.locate_file(file))
|
||||
assert '.whl/' in path, path
|
||||
|
||||
def test_one_distribution(self):
|
||||
dists = list(distributions(path=sys.path[:1]))
|
||||
assert len(dists) == 1
|
||||
|
||||
|
||||
class TestEgg(TestZip):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self._fixture_on_path('example-21.12-py3.6.egg')
|
||||
|
||||
def test_files(self):
|
||||
for file in files('example'):
|
||||
path = str(file.dist.locate_file(file))
|
||||
assert '.egg/' in path, path
|
||||
|
||||
def test_normalized_name(self):
|
||||
dist = distribution('example')
|
||||
assert dist._normalized_name == 'example'
|
||||
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/one.py
vendored
Normal file
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/one.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
attr = 'both_portions foo one'
|
||||
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/two.py
vendored
Normal file
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/both_portions/foo/two.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
attr = 'both_portions foo two'
|
||||
BIN
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/missing_directory.zip
vendored
Normal file
BIN
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/missing_directory.zip
vendored
Normal file
Binary file not shown.
@@ -0,0 +1 @@
|
||||
attr = 'in module'
|
||||
BIN
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/nested_portion1.zip
vendored
Normal file
BIN
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/nested_portion1.zip
vendored
Normal file
Binary file not shown.
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/one.py
vendored
Normal file
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo/one.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
attr = 'portion1 foo one'
|
||||
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/portion1/foo/one.py
vendored
Normal file
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/portion1/foo/one.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
attr = 'portion1 foo one'
|
||||
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/portion2/foo/two.py
vendored
Normal file
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/portion2/foo/two.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
attr = 'portion2 foo two'
|
||||
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/project1/parent/child/one.py
vendored
Normal file
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/project1/parent/child/one.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
attr = 'parent child one'
|
||||
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/project2/parent/child/two.py
vendored
Normal file
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/project2/parent/child/two.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
attr = 'parent child two'
|
||||
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/project3/parent/child/three.py
vendored
Normal file
1
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/project3/parent/child/three.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
attr = 'parent child three'
|
||||
BIN
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/top_level_portion1.zip
vendored
Normal file
BIN
Dependencies/Python/Lib/test/test_importlib/namespace_pkgs/top_level_portion1.zip
vendored
Normal file
Binary file not shown.
38
Dependencies/Python/Lib/test/test_importlib/partial/cfimport.py
vendored
Normal file
38
Dependencies/Python/Lib/test/test_importlib/partial/cfimport.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
import traceback
|
||||
|
||||
|
||||
NLOOPS = 50
|
||||
NTHREADS = 30
|
||||
|
||||
|
||||
def t1():
|
||||
try:
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
os._exit(1)
|
||||
|
||||
def t2():
|
||||
try:
|
||||
from concurrent.futures.thread import ThreadPoolExecutor
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
os._exit(1)
|
||||
|
||||
def main():
|
||||
for j in range(NLOOPS):
|
||||
threads = []
|
||||
for i in range(NTHREADS):
|
||||
threads.append(threading.Thread(target=t2 if i % 1 else t1))
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
sys.modules.pop('concurrent.futures', None)
|
||||
sys.modules.pop('concurrent.futures.thread', None)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
27
Dependencies/Python/Lib/test/test_importlib/partial/pool_in_threads.py
vendored
Normal file
27
Dependencies/Python/Lib/test/test_importlib/partial/pool_in_threads.py
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import multiprocessing
|
||||
import os
|
||||
import threading
|
||||
import traceback
|
||||
|
||||
|
||||
def t():
|
||||
try:
|
||||
with multiprocessing.Pool(1):
|
||||
pass
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
os._exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
threads = []
|
||||
for i in range(20):
|
||||
threads.append(threading.Thread(target=t))
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
0
Dependencies/Python/Lib/test/test_importlib/resources/__init__.py
vendored
Normal file
0
Dependencies/Python/Lib/test/test_importlib/resources/__init__.py
vendored
Normal file
94
Dependencies/Python/Lib/test/test_importlib/resources/_path.py
vendored
Normal file
94
Dependencies/Python/Lib/test/test_importlib/resources/_path.py
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
import pathlib
|
||||
import functools
|
||||
|
||||
from typing import Dict, Union
|
||||
from typing import runtime_checkable
|
||||
from typing import Protocol
|
||||
|
||||
|
||||
####
|
||||
# from jaraco.path 3.7.1
|
||||
|
||||
|
||||
class Symlink(str):
|
||||
"""
|
||||
A string indicating the target of a symlink.
|
||||
"""
|
||||
|
||||
|
||||
FilesSpec = Dict[str, Union[str, bytes, Symlink, 'FilesSpec']]
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class TreeMaker(Protocol):
|
||||
def __truediv__(self, *args, **kwargs): ... # pragma: no cover
|
||||
|
||||
def mkdir(self, **kwargs): ... # pragma: no cover
|
||||
|
||||
def write_text(self, content, **kwargs): ... # pragma: no cover
|
||||
|
||||
def write_bytes(self, content): ... # pragma: no cover
|
||||
|
||||
def symlink_to(self, target): ... # pragma: no cover
|
||||
|
||||
|
||||
def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker:
|
||||
return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type: ignore[return-value]
|
||||
|
||||
|
||||
def build(
|
||||
spec: FilesSpec,
|
||||
prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore[assignment]
|
||||
):
|
||||
"""
|
||||
Build a set of files/directories, as described by the spec.
|
||||
|
||||
Each key represents a pathname, and the value represents
|
||||
the content. Content may be a nested directory.
|
||||
|
||||
>>> spec = {
|
||||
... 'README.txt': "A README file",
|
||||
... "foo": {
|
||||
... "__init__.py": "",
|
||||
... "bar": {
|
||||
... "__init__.py": "",
|
||||
... },
|
||||
... "baz.py": "# Some code",
|
||||
... "bar.py": Symlink("baz.py"),
|
||||
... },
|
||||
... "bing": Symlink("foo"),
|
||||
... }
|
||||
>>> target = getfixture('tmp_path')
|
||||
>>> build(spec, target)
|
||||
>>> target.joinpath('foo/baz.py').read_text(encoding='utf-8')
|
||||
'# Some code'
|
||||
>>> target.joinpath('bing/bar.py').read_text(encoding='utf-8')
|
||||
'# Some code'
|
||||
"""
|
||||
for name, contents in spec.items():
|
||||
create(contents, _ensure_tree_maker(prefix) / name)
|
||||
|
||||
|
||||
@functools.singledispatch
|
||||
def create(content: Union[str, bytes, FilesSpec], path):
|
||||
path.mkdir(exist_ok=True)
|
||||
build(content, prefix=path) # type: ignore[arg-type]
|
||||
|
||||
|
||||
@create.register
|
||||
def _(content: bytes, path):
|
||||
path.write_bytes(content)
|
||||
|
||||
|
||||
@create.register
|
||||
def _(content: str, path):
|
||||
path.write_text(content, encoding='utf-8')
|
||||
|
||||
|
||||
@create.register
|
||||
def _(content: Symlink, path):
|
||||
path.symlink_to(content)
|
||||
|
||||
|
||||
# end from jaraco.path
|
||||
####
|
||||
104
Dependencies/Python/Lib/test/test_importlib/resources/test_compatibilty_files.py
vendored
Normal file
104
Dependencies/Python/Lib/test/test_importlib/resources/test_compatibilty_files.py
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
import io
|
||||
import unittest
|
||||
|
||||
from importlib import resources
|
||||
|
||||
from importlib.resources._adapters import (
|
||||
CompatibilityFiles,
|
||||
wrap_spec,
|
||||
)
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class CompatibilityFilesTests(unittest.TestCase):
|
||||
@property
|
||||
def package(self):
|
||||
bytes_data = io.BytesIO(b'Hello, world!')
|
||||
return util.create_package(
|
||||
file=bytes_data,
|
||||
path='some_path',
|
||||
contents=('a', 'b', 'c'),
|
||||
)
|
||||
|
||||
@property
|
||||
def files(self):
|
||||
return resources.files(self.package)
|
||||
|
||||
def test_spec_path_iter(self):
|
||||
self.assertEqual(
|
||||
sorted(path.name for path in self.files.iterdir()),
|
||||
['a', 'b', 'c'],
|
||||
)
|
||||
|
||||
def test_child_path_iter(self):
|
||||
self.assertEqual(list((self.files / 'a').iterdir()), [])
|
||||
|
||||
def test_orphan_path_iter(self):
|
||||
self.assertEqual(list((self.files / 'a' / 'a').iterdir()), [])
|
||||
self.assertEqual(list((self.files / 'a' / 'a' / 'a').iterdir()), [])
|
||||
|
||||
def test_spec_path_is(self):
|
||||
self.assertFalse(self.files.is_file())
|
||||
self.assertFalse(self.files.is_dir())
|
||||
|
||||
def test_child_path_is(self):
|
||||
self.assertTrue((self.files / 'a').is_file())
|
||||
self.assertFalse((self.files / 'a').is_dir())
|
||||
|
||||
def test_orphan_path_is(self):
|
||||
self.assertFalse((self.files / 'a' / 'a').is_file())
|
||||
self.assertFalse((self.files / 'a' / 'a').is_dir())
|
||||
self.assertFalse((self.files / 'a' / 'a' / 'a').is_file())
|
||||
self.assertFalse((self.files / 'a' / 'a' / 'a').is_dir())
|
||||
|
||||
def test_spec_path_name(self):
|
||||
self.assertEqual(self.files.name, 'testingpackage')
|
||||
|
||||
def test_child_path_name(self):
|
||||
self.assertEqual((self.files / 'a').name, 'a')
|
||||
|
||||
def test_orphan_path_name(self):
|
||||
self.assertEqual((self.files / 'a' / 'b').name, 'b')
|
||||
self.assertEqual((self.files / 'a' / 'b' / 'c').name, 'c')
|
||||
|
||||
def test_spec_path_open(self):
|
||||
self.assertEqual(self.files.read_bytes(), b'Hello, world!')
|
||||
self.assertEqual(self.files.read_text(encoding='utf-8'), 'Hello, world!')
|
||||
|
||||
def test_child_path_open(self):
|
||||
self.assertEqual((self.files / 'a').read_bytes(), b'Hello, world!')
|
||||
self.assertEqual(
|
||||
(self.files / 'a').read_text(encoding='utf-8'), 'Hello, world!'
|
||||
)
|
||||
|
||||
def test_orphan_path_open(self):
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
(self.files / 'a' / 'b').read_bytes()
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
(self.files / 'a' / 'b' / 'c').read_bytes()
|
||||
|
||||
def test_open_invalid_mode(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.files.open('0')
|
||||
|
||||
def test_orphan_path_invalid(self):
|
||||
with self.assertRaises(ValueError):
|
||||
CompatibilityFiles.OrphanPath()
|
||||
|
||||
def test_wrap_spec(self):
|
||||
spec = wrap_spec(self.package)
|
||||
self.assertIsInstance(spec.loader.get_resource_reader(None), CompatibilityFiles)
|
||||
|
||||
|
||||
class CompatibilityFilesNoReaderTests(unittest.TestCase):
|
||||
@property
|
||||
def package(self):
|
||||
return util.create_package_from_loader(None)
|
||||
|
||||
@property
|
||||
def files(self):
|
||||
return resources.files(self.package)
|
||||
|
||||
def test_spec_path_joinpath(self):
|
||||
self.assertIsInstance(self.files / 'a', CompatibilityFiles.OrphanPath)
|
||||
38
Dependencies/Python/Lib/test/test_importlib/resources/test_contents.py
vendored
Normal file
38
Dependencies/Python/Lib/test/test_importlib/resources/test_contents.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import unittest
|
||||
from importlib import resources
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class ContentsTests:
|
||||
expected = {
|
||||
'__init__.py',
|
||||
'binary.file',
|
||||
'subdirectory',
|
||||
'utf-16.file',
|
||||
'utf-8.file',
|
||||
}
|
||||
|
||||
def test_contents(self):
|
||||
contents = {path.name for path in resources.files(self.data).iterdir()}
|
||||
assert self.expected <= contents
|
||||
|
||||
|
||||
class ContentsDiskTests(ContentsTests, util.DiskSetup, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class ContentsZipTests(ContentsTests, util.ZipSetup, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class ContentsNamespaceTests(ContentsTests, util.DiskSetup, unittest.TestCase):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
expected = {
|
||||
# no __init__ because of namespace design
|
||||
'binary.file',
|
||||
'subdirectory',
|
||||
'utf-16.file',
|
||||
'utf-8.file',
|
||||
}
|
||||
48
Dependencies/Python/Lib/test/test_importlib/resources/test_custom.py
vendored
Normal file
48
Dependencies/Python/Lib/test/test_importlib/resources/test_custom.py
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
import unittest
|
||||
import contextlib
|
||||
import pathlib
|
||||
|
||||
from test.support import os_helper
|
||||
|
||||
from importlib import resources
|
||||
from importlib.resources import abc
|
||||
from importlib.resources.abc import TraversableResources, ResourceReader
|
||||
from . import util
|
||||
|
||||
|
||||
class SimpleLoader:
|
||||
"""
|
||||
A simple loader that only implements a resource reader.
|
||||
"""
|
||||
|
||||
def __init__(self, reader: ResourceReader):
|
||||
self.reader = reader
|
||||
|
||||
def get_resource_reader(self, package):
|
||||
return self.reader
|
||||
|
||||
|
||||
class MagicResources(TraversableResources):
|
||||
"""
|
||||
Magically returns the resources at path.
|
||||
"""
|
||||
|
||||
def __init__(self, path: pathlib.Path):
|
||||
self.path = path
|
||||
|
||||
def files(self):
|
||||
return self.path
|
||||
|
||||
|
||||
class CustomTraversableResourcesTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.fixtures = contextlib.ExitStack()
|
||||
self.addCleanup(self.fixtures.close)
|
||||
|
||||
def test_custom_loader(self):
|
||||
temp_dir = pathlib.Path(self.fixtures.enter_context(os_helper.temp_dir()))
|
||||
loader = SimpleLoader(MagicResources(temp_dir))
|
||||
pkg = util.create_package_from_loader(loader)
|
||||
files = resources.files(pkg)
|
||||
assert isinstance(files, abc.Traversable)
|
||||
assert list(files.iterdir()) == []
|
||||
159
Dependencies/Python/Lib/test/test_importlib/resources/test_files.py
vendored
Normal file
159
Dependencies/Python/Lib/test/test_importlib/resources/test_files.py
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
import textwrap
|
||||
import unittest
|
||||
import warnings
|
||||
import importlib
|
||||
import contextlib
|
||||
|
||||
from importlib import resources
|
||||
from importlib.resources.abc import Traversable
|
||||
from . import util
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def suppress_known_deprecation():
|
||||
with warnings.catch_warnings(record=True) as ctx:
|
||||
warnings.simplefilter('default', category=DeprecationWarning)
|
||||
yield ctx
|
||||
|
||||
|
||||
class FilesTests:
|
||||
def test_read_bytes(self):
|
||||
files = resources.files(self.data)
|
||||
actual = files.joinpath('utf-8.file').read_bytes()
|
||||
assert actual == b'Hello, UTF-8 world!\n'
|
||||
|
||||
def test_read_text(self):
|
||||
files = resources.files(self.data)
|
||||
actual = files.joinpath('utf-8.file').read_text(encoding='utf-8')
|
||||
assert actual == 'Hello, UTF-8 world!\n'
|
||||
|
||||
def test_traversable(self):
|
||||
assert isinstance(resources.files(self.data), Traversable)
|
||||
|
||||
def test_joinpath_with_multiple_args(self):
|
||||
files = resources.files(self.data)
|
||||
binfile = files.joinpath('subdirectory', 'binary.file')
|
||||
self.assertTrue(binfile.is_file())
|
||||
|
||||
def test_old_parameter(self):
|
||||
"""
|
||||
Files used to take a 'package' parameter. Make sure anyone
|
||||
passing by name is still supported.
|
||||
"""
|
||||
with suppress_known_deprecation():
|
||||
resources.files(package=self.data)
|
||||
|
||||
|
||||
class OpenDiskTests(FilesTests, util.DiskSetup, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class OpenZipTests(FilesTests, util.ZipSetup, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class OpenNamespaceTests(FilesTests, util.DiskSetup, unittest.TestCase):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
def test_non_paths_in_dunder_path(self):
|
||||
"""
|
||||
Non-path items in a namespace package's ``__path__`` are ignored.
|
||||
|
||||
As reported in python/importlib_resources#311, some tools
|
||||
like Setuptools, when creating editable packages, will inject
|
||||
non-paths into a namespace package's ``__path__``, a
|
||||
sentinel like
|
||||
``__editable__.sample_namespace-1.0.finder.__path_hook__``
|
||||
to cause the ``PathEntryFinder`` to be called when searching
|
||||
for packages. In that case, resources should still be loadable.
|
||||
"""
|
||||
import namespacedata01
|
||||
|
||||
namespacedata01.__path__.append(
|
||||
'__editable__.sample_namespace-1.0.finder.__path_hook__'
|
||||
)
|
||||
|
||||
resources.files(namespacedata01)
|
||||
|
||||
|
||||
class OpenNamespaceZipTests(FilesTests, util.ZipSetup, unittest.TestCase):
|
||||
ZIP_MODULE = 'namespacedata01'
|
||||
|
||||
|
||||
class DirectSpec:
|
||||
"""
|
||||
Override behavior of ModuleSetup to write a full spec directly.
|
||||
"""
|
||||
|
||||
MODULE = 'unused'
|
||||
|
||||
def load_fixture(self, name):
|
||||
self.tree_on_path(self.spec)
|
||||
|
||||
|
||||
class ModulesFiles:
|
||||
spec = {
|
||||
'mod.py': '',
|
||||
'res.txt': 'resources are the best',
|
||||
}
|
||||
|
||||
def test_module_resources(self):
|
||||
"""
|
||||
A module can have resources found adjacent to the module.
|
||||
"""
|
||||
import mod # type: ignore[import-not-found]
|
||||
|
||||
actual = resources.files(mod).joinpath('res.txt').read_text(encoding='utf-8')
|
||||
assert actual == self.spec['res.txt']
|
||||
|
||||
|
||||
class ModuleFilesDiskTests(DirectSpec, util.DiskSetup, ModulesFiles, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class ModuleFilesZipTests(DirectSpec, util.ZipSetup, ModulesFiles, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class ImplicitContextFiles:
|
||||
set_val = textwrap.dedent(
|
||||
"""
|
||||
import importlib.resources as res
|
||||
val = res.files().joinpath('res.txt').read_text(encoding='utf-8')
|
||||
"""
|
||||
)
|
||||
spec = {
|
||||
'somepkg': {
|
||||
'__init__.py': set_val,
|
||||
'submod.py': set_val,
|
||||
'res.txt': 'resources are the best',
|
||||
},
|
||||
}
|
||||
|
||||
def test_implicit_files_package(self):
|
||||
"""
|
||||
Without any parameter, files() will infer the location as the caller.
|
||||
"""
|
||||
assert importlib.import_module('somepkg').val == 'resources are the best'
|
||||
|
||||
def test_implicit_files_submodule(self):
|
||||
"""
|
||||
Without any parameter, files() will infer the location as the caller.
|
||||
"""
|
||||
assert importlib.import_module('somepkg.submod').val == 'resources are the best'
|
||||
|
||||
|
||||
class ImplicitContextFilesDiskTests(
|
||||
DirectSpec, util.DiskSetup, ImplicitContextFiles, unittest.TestCase
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
class ImplicitContextFilesZipTests(
|
||||
DirectSpec, util.ZipSetup, ImplicitContextFiles, unittest.TestCase
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
250
Dependencies/Python/Lib/test/test_importlib/resources/test_functional.py
vendored
Normal file
250
Dependencies/Python/Lib/test/test_importlib/resources/test_functional.py
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
import unittest
|
||||
import os
|
||||
import importlib
|
||||
|
||||
from test.support import warnings_helper
|
||||
from test.support.testcase import ExtraAssertions
|
||||
|
||||
from importlib import resources
|
||||
|
||||
from . import util
|
||||
|
||||
# Since the functional API forwards to Traversable, we only test
|
||||
# filesystem resources here -- not zip files, namespace packages etc.
|
||||
# We do test for two kinds of Anchor, though.
|
||||
|
||||
|
||||
class StringAnchorMixin:
|
||||
anchor01 = 'data01'
|
||||
anchor02 = 'data02'
|
||||
|
||||
|
||||
class ModuleAnchorMixin:
|
||||
@property
|
||||
def anchor01(self):
|
||||
return importlib.import_module('data01')
|
||||
|
||||
@property
|
||||
def anchor02(self):
|
||||
return importlib.import_module('data02')
|
||||
|
||||
|
||||
class FunctionalAPIBase(util.DiskSetup, ExtraAssertions):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.load_fixture('data02')
|
||||
|
||||
def _gen_resourcetxt_path_parts(self):
|
||||
"""Yield various names of a text file in anchor02, each in a subTest"""
|
||||
for path_parts in (
|
||||
('subdirectory', 'subsubdir', 'resource.txt'),
|
||||
('subdirectory/subsubdir/resource.txt',),
|
||||
('subdirectory/subsubdir', 'resource.txt'),
|
||||
):
|
||||
with self.subTest(path_parts=path_parts):
|
||||
yield path_parts
|
||||
|
||||
def test_read_text(self):
|
||||
self.assertEqual(
|
||||
resources.read_text(self.anchor01, 'utf-8.file'),
|
||||
'Hello, UTF-8 world!\n',
|
||||
)
|
||||
self.assertEqual(
|
||||
resources.read_text(
|
||||
self.anchor02,
|
||||
'subdirectory',
|
||||
'subsubdir',
|
||||
'resource.txt',
|
||||
encoding='utf-8',
|
||||
),
|
||||
'a resource',
|
||||
)
|
||||
for path_parts in self._gen_resourcetxt_path_parts():
|
||||
self.assertEqual(
|
||||
resources.read_text(
|
||||
self.anchor02,
|
||||
*path_parts,
|
||||
encoding='utf-8',
|
||||
),
|
||||
'a resource',
|
||||
)
|
||||
# Use generic OSError, since e.g. attempting to read a directory can
|
||||
# fail with PermissionError rather than IsADirectoryError
|
||||
with self.assertRaises(OSError):
|
||||
resources.read_text(self.anchor01)
|
||||
with self.assertRaises(OSError):
|
||||
resources.read_text(self.anchor01, 'no-such-file')
|
||||
with self.assertRaises(UnicodeDecodeError):
|
||||
resources.read_text(self.anchor01, 'utf-16.file')
|
||||
self.assertEqual(
|
||||
resources.read_text(
|
||||
self.anchor01,
|
||||
'binary.file',
|
||||
encoding='latin1',
|
||||
),
|
||||
'\x00\x01\x02\x03',
|
||||
)
|
||||
self.assertEndsWith( # ignore the BOM
|
||||
resources.read_text(
|
||||
self.anchor01,
|
||||
'utf-16.file',
|
||||
errors='backslashreplace',
|
||||
),
|
||||
'Hello, UTF-16 world!\n'.encode('utf-16-le').decode(
|
||||
errors='backslashreplace',
|
||||
),
|
||||
)
|
||||
|
||||
def test_read_binary(self):
|
||||
self.assertEqual(
|
||||
resources.read_binary(self.anchor01, 'utf-8.file'),
|
||||
b'Hello, UTF-8 world!\n',
|
||||
)
|
||||
for path_parts in self._gen_resourcetxt_path_parts():
|
||||
self.assertEqual(
|
||||
resources.read_binary(self.anchor02, *path_parts),
|
||||
b'a resource',
|
||||
)
|
||||
|
||||
def test_open_text(self):
|
||||
with resources.open_text(self.anchor01, 'utf-8.file') as f:
|
||||
self.assertEqual(f.read(), 'Hello, UTF-8 world!\n')
|
||||
for path_parts in self._gen_resourcetxt_path_parts():
|
||||
with resources.open_text(
|
||||
self.anchor02,
|
||||
*path_parts,
|
||||
encoding='utf-8',
|
||||
) as f:
|
||||
self.assertEqual(f.read(), 'a resource')
|
||||
# Use generic OSError, since e.g. attempting to read a directory can
|
||||
# fail with PermissionError rather than IsADirectoryError
|
||||
with self.assertRaises(OSError):
|
||||
resources.open_text(self.anchor01)
|
||||
with self.assertRaises(OSError):
|
||||
resources.open_text(self.anchor01, 'no-such-file')
|
||||
with resources.open_text(self.anchor01, 'utf-16.file') as f:
|
||||
with self.assertRaises(UnicodeDecodeError):
|
||||
f.read()
|
||||
with resources.open_text(
|
||||
self.anchor01,
|
||||
'binary.file',
|
||||
encoding='latin1',
|
||||
) as f:
|
||||
self.assertEqual(f.read(), '\x00\x01\x02\x03')
|
||||
with resources.open_text(
|
||||
self.anchor01,
|
||||
'utf-16.file',
|
||||
errors='backslashreplace',
|
||||
) as f:
|
||||
self.assertEndsWith( # ignore the BOM
|
||||
f.read(),
|
||||
'Hello, UTF-16 world!\n'.encode('utf-16-le').decode(
|
||||
errors='backslashreplace',
|
||||
),
|
||||
)
|
||||
|
||||
def test_open_binary(self):
|
||||
with resources.open_binary(self.anchor01, 'utf-8.file') as f:
|
||||
self.assertEqual(f.read(), b'Hello, UTF-8 world!\n')
|
||||
for path_parts in self._gen_resourcetxt_path_parts():
|
||||
with resources.open_binary(
|
||||
self.anchor02,
|
||||
*path_parts,
|
||||
) as f:
|
||||
self.assertEqual(f.read(), b'a resource')
|
||||
|
||||
def test_path(self):
|
||||
with resources.path(self.anchor01, 'utf-8.file') as path:
|
||||
with open(str(path), encoding='utf-8') as f:
|
||||
self.assertEqual(f.read(), 'Hello, UTF-8 world!\n')
|
||||
with resources.path(self.anchor01) as path:
|
||||
with open(os.path.join(path, 'utf-8.file'), encoding='utf-8') as f:
|
||||
self.assertEqual(f.read(), 'Hello, UTF-8 world!\n')
|
||||
|
||||
def test_is_resource(self):
|
||||
is_resource = resources.is_resource
|
||||
self.assertTrue(is_resource(self.anchor01, 'utf-8.file'))
|
||||
self.assertFalse(is_resource(self.anchor01, 'no_such_file'))
|
||||
self.assertFalse(is_resource(self.anchor01))
|
||||
self.assertFalse(is_resource(self.anchor01, 'subdirectory'))
|
||||
for path_parts in self._gen_resourcetxt_path_parts():
|
||||
self.assertTrue(is_resource(self.anchor02, *path_parts))
|
||||
|
||||
def test_contents(self):
|
||||
with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)):
|
||||
c = resources.contents(self.anchor01)
|
||||
self.assertGreaterEqual(
|
||||
set(c),
|
||||
{'utf-8.file', 'utf-16.file', 'binary.file', 'subdirectory'},
|
||||
)
|
||||
with self.assertRaises(OSError), warnings_helper.check_warnings((
|
||||
".*contents.*",
|
||||
DeprecationWarning,
|
||||
)):
|
||||
list(resources.contents(self.anchor01, 'utf-8.file'))
|
||||
|
||||
for path_parts in self._gen_resourcetxt_path_parts():
|
||||
with self.assertRaises(OSError), warnings_helper.check_warnings((
|
||||
".*contents.*",
|
||||
DeprecationWarning,
|
||||
)):
|
||||
list(resources.contents(self.anchor01, *path_parts))
|
||||
with warnings_helper.check_warnings((".*contents.*", DeprecationWarning)):
|
||||
c = resources.contents(self.anchor01, 'subdirectory')
|
||||
self.assertGreaterEqual(
|
||||
set(c),
|
||||
{'binary.file'},
|
||||
)
|
||||
|
||||
@warnings_helper.ignore_warnings(category=DeprecationWarning)
|
||||
def test_common_errors(self):
|
||||
for func in (
|
||||
resources.read_text,
|
||||
resources.read_binary,
|
||||
resources.open_text,
|
||||
resources.open_binary,
|
||||
resources.path,
|
||||
resources.is_resource,
|
||||
resources.contents,
|
||||
):
|
||||
with self.subTest(func=func):
|
||||
# Rejecting None anchor
|
||||
with self.assertRaises(TypeError):
|
||||
func(None)
|
||||
# Rejecting invalid anchor type
|
||||
with self.assertRaises((TypeError, AttributeError)):
|
||||
func(1234)
|
||||
# Unknown module
|
||||
with self.assertRaises(ModuleNotFoundError):
|
||||
func('$missing module$')
|
||||
|
||||
def test_text_errors(self):
|
||||
for func in (
|
||||
resources.read_text,
|
||||
resources.open_text,
|
||||
):
|
||||
with self.subTest(func=func):
|
||||
# Multiple path arguments need explicit encoding argument.
|
||||
with self.assertRaises(TypeError):
|
||||
func(
|
||||
self.anchor02,
|
||||
'subdirectory',
|
||||
'subsubdir',
|
||||
'resource.txt',
|
||||
)
|
||||
|
||||
|
||||
class FunctionalAPITest_StringAnchor(
|
||||
StringAnchorMixin,
|
||||
FunctionalAPIBase,
|
||||
unittest.TestCase,
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
class FunctionalAPITest_ModuleAnchor(
|
||||
ModuleAnchorMixin,
|
||||
FunctionalAPIBase,
|
||||
unittest.TestCase,
|
||||
):
|
||||
pass
|
||||
84
Dependencies/Python/Lib/test/test_importlib/resources/test_open.py
vendored
Normal file
84
Dependencies/Python/Lib/test/test_importlib/resources/test_open.py
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
import unittest
|
||||
|
||||
from importlib import resources
|
||||
from . import util
|
||||
|
||||
|
||||
class CommonBinaryTests(util.CommonTests, unittest.TestCase):
|
||||
def execute(self, package, path):
|
||||
target = resources.files(package).joinpath(path)
|
||||
with target.open('rb'):
|
||||
pass
|
||||
|
||||
|
||||
class CommonTextTests(util.CommonTests, unittest.TestCase):
|
||||
def execute(self, package, path):
|
||||
target = resources.files(package).joinpath(path)
|
||||
with target.open(encoding='utf-8'):
|
||||
pass
|
||||
|
||||
|
||||
class OpenTests:
|
||||
def test_open_binary(self):
|
||||
target = resources.files(self.data) / 'binary.file'
|
||||
with target.open('rb') as fp:
|
||||
result = fp.read()
|
||||
self.assertEqual(result, bytes(range(4)))
|
||||
|
||||
def test_open_text_default_encoding(self):
|
||||
target = resources.files(self.data) / 'utf-8.file'
|
||||
with target.open(encoding='utf-8') as fp:
|
||||
result = fp.read()
|
||||
self.assertEqual(result, 'Hello, UTF-8 world!\n')
|
||||
|
||||
def test_open_text_given_encoding(self):
|
||||
target = resources.files(self.data) / 'utf-16.file'
|
||||
with target.open(encoding='utf-16', errors='strict') as fp:
|
||||
result = fp.read()
|
||||
self.assertEqual(result, 'Hello, UTF-16 world!\n')
|
||||
|
||||
def test_open_text_with_errors(self):
|
||||
"""
|
||||
Raises UnicodeError without the 'errors' argument.
|
||||
"""
|
||||
target = resources.files(self.data) / 'utf-16.file'
|
||||
with target.open(encoding='utf-8', errors='strict') as fp:
|
||||
self.assertRaises(UnicodeError, fp.read)
|
||||
with target.open(encoding='utf-8', errors='ignore') as fp:
|
||||
result = fp.read()
|
||||
self.assertEqual(
|
||||
result,
|
||||
'H\x00e\x00l\x00l\x00o\x00,\x00 '
|
||||
'\x00U\x00T\x00F\x00-\x001\x006\x00 '
|
||||
'\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00',
|
||||
)
|
||||
|
||||
def test_open_binary_FileNotFoundError(self):
|
||||
target = resources.files(self.data) / 'does-not-exist'
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
target.open('rb')
|
||||
|
||||
def test_open_text_FileNotFoundError(self):
|
||||
target = resources.files(self.data) / 'does-not-exist'
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
target.open(encoding='utf-8')
|
||||
|
||||
|
||||
class OpenDiskTests(OpenTests, util.DiskSetup, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class OpenDiskNamespaceTests(OpenTests, util.DiskSetup, unittest.TestCase):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
|
||||
class OpenZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class OpenNamespaceZipTests(OpenTests, util.ZipSetup, unittest.TestCase):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
61
Dependencies/Python/Lib/test/test_importlib/resources/test_path.py
vendored
Normal file
61
Dependencies/Python/Lib/test/test_importlib/resources/test_path.py
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
import io
|
||||
import pathlib
|
||||
import unittest
|
||||
|
||||
from importlib import resources
|
||||
from . import util
|
||||
from test.support.testcase import ExtraAssertions
|
||||
|
||||
|
||||
class CommonTests(util.CommonTests, unittest.TestCase):
|
||||
def execute(self, package, path):
|
||||
with resources.as_file(resources.files(package).joinpath(path)):
|
||||
pass
|
||||
|
||||
|
||||
class PathTests(ExtraAssertions):
|
||||
def test_reading(self):
|
||||
"""
|
||||
Path should be readable and a pathlib.Path instance.
|
||||
"""
|
||||
target = resources.files(self.data) / 'utf-8.file'
|
||||
with resources.as_file(target) as path:
|
||||
self.assertIsInstance(path, pathlib.Path)
|
||||
self.assertEndsWith(path.name, "utf-8.file")
|
||||
self.assertEqual('Hello, UTF-8 world!\n', path.read_text(encoding='utf-8'))
|
||||
|
||||
|
||||
class PathDiskTests(PathTests, util.DiskSetup, unittest.TestCase):
|
||||
def test_natural_path(self):
|
||||
# Guarantee the internal implementation detail that
|
||||
# file-system-backed resources do not get the tempdir
|
||||
# treatment.
|
||||
target = resources.files(self.data) / 'utf-8.file'
|
||||
with resources.as_file(target) as path:
|
||||
assert 'data' in str(path)
|
||||
|
||||
|
||||
class PathMemoryTests(PathTests, unittest.TestCase):
|
||||
def setUp(self):
|
||||
file = io.BytesIO(b'Hello, UTF-8 world!\n')
|
||||
self.addCleanup(file.close)
|
||||
self.data = util.create_package(
|
||||
file=file, path=FileNotFoundError("package exists only in memory")
|
||||
)
|
||||
self.data.__spec__.origin = None
|
||||
self.data.__spec__.has_location = False
|
||||
|
||||
|
||||
class PathZipTests(PathTests, util.ZipSetup, unittest.TestCase):
|
||||
def test_remove_in_context_manager(self):
|
||||
"""
|
||||
It is not an error if the file that was temporarily stashed on the
|
||||
file system is removed inside the `with` stanza.
|
||||
"""
|
||||
target = resources.files(self.data) / 'utf-8.file'
|
||||
with resources.as_file(target) as path:
|
||||
path.unlink()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
93
Dependencies/Python/Lib/test/test_importlib/resources/test_read.py
vendored
Normal file
93
Dependencies/Python/Lib/test/test_importlib/resources/test_read.py
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import unittest
|
||||
|
||||
from importlib import import_module, resources
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class CommonBinaryTests(util.CommonTests, unittest.TestCase):
|
||||
def execute(self, package, path):
|
||||
resources.files(package).joinpath(path).read_bytes()
|
||||
|
||||
|
||||
class CommonTextTests(util.CommonTests, unittest.TestCase):
|
||||
def execute(self, package, path):
|
||||
resources.files(package).joinpath(path).read_text(encoding='utf-8')
|
||||
|
||||
|
||||
class ReadTests:
|
||||
def test_read_bytes(self):
|
||||
result = resources.files(self.data).joinpath('binary.file').read_bytes()
|
||||
self.assertEqual(result, bytes(range(4)))
|
||||
|
||||
def test_read_text_default_encoding(self):
|
||||
result = (
|
||||
resources.files(self.data)
|
||||
.joinpath('utf-8.file')
|
||||
.read_text(encoding='utf-8')
|
||||
)
|
||||
self.assertEqual(result, 'Hello, UTF-8 world!\n')
|
||||
|
||||
def test_read_text_given_encoding(self):
|
||||
result = (
|
||||
resources.files(self.data)
|
||||
.joinpath('utf-16.file')
|
||||
.read_text(encoding='utf-16')
|
||||
)
|
||||
self.assertEqual(result, 'Hello, UTF-16 world!\n')
|
||||
|
||||
def test_read_text_with_errors(self):
|
||||
"""
|
||||
Raises UnicodeError without the 'errors' argument.
|
||||
"""
|
||||
target = resources.files(self.data) / 'utf-16.file'
|
||||
self.assertRaises(UnicodeError, target.read_text, encoding='utf-8')
|
||||
result = target.read_text(encoding='utf-8', errors='ignore')
|
||||
self.assertEqual(
|
||||
result,
|
||||
'H\x00e\x00l\x00l\x00o\x00,\x00 '
|
||||
'\x00U\x00T\x00F\x00-\x001\x006\x00 '
|
||||
'\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00',
|
||||
)
|
||||
|
||||
|
||||
class ReadDiskTests(ReadTests, util.DiskSetup, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
|
||||
def test_read_submodule_resource(self):
|
||||
submodule = import_module('data01.subdirectory')
|
||||
result = resources.files(submodule).joinpath('binary.file').read_bytes()
|
||||
self.assertEqual(result, bytes(range(4, 8)))
|
||||
|
||||
def test_read_submodule_resource_by_name(self):
|
||||
result = (
|
||||
resources.files('data01.subdirectory').joinpath('binary.file').read_bytes()
|
||||
)
|
||||
self.assertEqual(result, bytes(range(4, 8)))
|
||||
|
||||
|
||||
class ReadNamespaceTests(ReadTests, util.DiskSetup, unittest.TestCase):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
|
||||
class ReadNamespaceZipTests(ReadTests, util.ZipSetup, unittest.TestCase):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
def test_read_submodule_resource(self):
|
||||
submodule = import_module('namespacedata01.subdirectory')
|
||||
result = resources.files(submodule).joinpath('binary.file').read_bytes()
|
||||
self.assertEqual(result, bytes(range(12, 16)))
|
||||
|
||||
def test_read_submodule_resource_by_name(self):
|
||||
result = (
|
||||
resources.files('namespacedata01.subdirectory')
|
||||
.joinpath('binary.file')
|
||||
.read_bytes()
|
||||
)
|
||||
self.assertEqual(result, bytes(range(12, 16)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
137
Dependencies/Python/Lib/test/test_importlib/resources/test_reader.py
vendored
Normal file
137
Dependencies/Python/Lib/test/test_importlib/resources/test_reader.py
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
import os.path
|
||||
import pathlib
|
||||
import unittest
|
||||
|
||||
from importlib import import_module
|
||||
from importlib.readers import MultiplexedPath, NamespaceReader
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class MultiplexedPathTest(util.DiskSetup, unittest.TestCase):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.folder = pathlib.Path(self.data.__path__[0])
|
||||
self.data01 = pathlib.Path(self.load_fixture('data01').__file__).parent
|
||||
self.data02 = pathlib.Path(self.load_fixture('data02').__file__).parent
|
||||
|
||||
def test_init_no_paths(self):
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
MultiplexedPath()
|
||||
|
||||
def test_init_file(self):
|
||||
with self.assertRaises(NotADirectoryError):
|
||||
MultiplexedPath(self.folder / 'binary.file')
|
||||
|
||||
def test_iterdir(self):
|
||||
contents = {path.name for path in MultiplexedPath(self.folder).iterdir()}
|
||||
try:
|
||||
contents.remove('__pycache__')
|
||||
except (KeyError, ValueError):
|
||||
pass
|
||||
self.assertEqual(
|
||||
contents, {'subdirectory', 'binary.file', 'utf-16.file', 'utf-8.file'}
|
||||
)
|
||||
|
||||
def test_iterdir_duplicate(self):
|
||||
contents = {
|
||||
path.name for path in MultiplexedPath(self.folder, self.data01).iterdir()
|
||||
}
|
||||
for remove in ('__pycache__', '__init__.pyc'):
|
||||
try:
|
||||
contents.remove(remove)
|
||||
except (KeyError, ValueError):
|
||||
pass
|
||||
self.assertEqual(
|
||||
contents,
|
||||
{'__init__.py', 'binary.file', 'subdirectory', 'utf-16.file', 'utf-8.file'},
|
||||
)
|
||||
|
||||
def test_is_dir(self):
|
||||
self.assertEqual(MultiplexedPath(self.folder).is_dir(), True)
|
||||
|
||||
def test_is_file(self):
|
||||
self.assertEqual(MultiplexedPath(self.folder).is_file(), False)
|
||||
|
||||
def test_open_file(self):
|
||||
path = MultiplexedPath(self.folder)
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
path.read_bytes()
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
path.read_text()
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
path.open()
|
||||
|
||||
def test_join_path(self):
|
||||
prefix = str(self.folder.parent)
|
||||
path = MultiplexedPath(self.folder, self.data01)
|
||||
self.assertEqual(
|
||||
str(path.joinpath('binary.file'))[len(prefix) + 1 :],
|
||||
os.path.join('namespacedata01', 'binary.file'),
|
||||
)
|
||||
sub = path.joinpath('subdirectory')
|
||||
assert isinstance(sub, MultiplexedPath)
|
||||
assert 'namespacedata01' in str(sub)
|
||||
assert 'data01' in str(sub)
|
||||
self.assertEqual(
|
||||
str(path.joinpath('imaginary'))[len(prefix) + 1 :],
|
||||
os.path.join('namespacedata01', 'imaginary'),
|
||||
)
|
||||
self.assertEqual(path.joinpath(), path)
|
||||
|
||||
def test_join_path_compound(self):
|
||||
path = MultiplexedPath(self.folder)
|
||||
assert not path.joinpath('imaginary/foo.py').exists()
|
||||
|
||||
def test_join_path_common_subdir(self):
|
||||
prefix = str(self.data02.parent)
|
||||
path = MultiplexedPath(self.data01, self.data02)
|
||||
self.assertIsInstance(path.joinpath('subdirectory'), MultiplexedPath)
|
||||
self.assertEqual(
|
||||
str(path.joinpath('subdirectory', 'subsubdir'))[len(prefix) + 1 :],
|
||||
os.path.join('data02', 'subdirectory', 'subsubdir'),
|
||||
)
|
||||
|
||||
def test_repr(self):
|
||||
self.assertEqual(
|
||||
repr(MultiplexedPath(self.folder)),
|
||||
f"MultiplexedPath('{self.folder}')",
|
||||
)
|
||||
|
||||
def test_name(self):
|
||||
self.assertEqual(
|
||||
MultiplexedPath(self.folder).name,
|
||||
os.path.basename(self.folder),
|
||||
)
|
||||
|
||||
|
||||
class NamespaceReaderTest(util.DiskSetup, unittest.TestCase):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
def test_init_error(self):
|
||||
with self.assertRaises(ValueError):
|
||||
NamespaceReader(['path1', 'path2'])
|
||||
|
||||
def test_resource_path(self):
|
||||
namespacedata01 = import_module('namespacedata01')
|
||||
reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations)
|
||||
|
||||
root = self.data.__path__[0]
|
||||
self.assertEqual(
|
||||
reader.resource_path('binary.file'), os.path.join(root, 'binary.file')
|
||||
)
|
||||
self.assertEqual(
|
||||
reader.resource_path('imaginary'), os.path.join(root, 'imaginary')
|
||||
)
|
||||
|
||||
def test_files(self):
|
||||
reader = NamespaceReader(self.data.__spec__.submodule_search_locations)
|
||||
root = self.data.__path__[0]
|
||||
self.assertIsInstance(reader.files(), MultiplexedPath)
|
||||
self.assertEqual(repr(reader.files()), f"MultiplexedPath('{root}')")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
236
Dependencies/Python/Lib/test/test_importlib/resources/test_resource.py
vendored
Normal file
236
Dependencies/Python/Lib/test/test_importlib/resources/test_resource.py
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
import unittest
|
||||
|
||||
from . import util
|
||||
from importlib import resources, import_module
|
||||
|
||||
|
||||
class ResourceTests:
|
||||
# Subclasses are expected to set the `data` attribute.
|
||||
|
||||
def test_is_file_exists(self):
|
||||
target = resources.files(self.data) / 'binary.file'
|
||||
self.assertTrue(target.is_file())
|
||||
|
||||
def test_is_file_missing(self):
|
||||
target = resources.files(self.data) / 'not-a-file'
|
||||
self.assertFalse(target.is_file())
|
||||
|
||||
def test_is_dir(self):
|
||||
target = resources.files(self.data) / 'subdirectory'
|
||||
self.assertFalse(target.is_file())
|
||||
self.assertTrue(target.is_dir())
|
||||
|
||||
|
||||
class ResourceDiskTests(ResourceTests, util.DiskSetup, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
class ResourceZipTests(ResourceTests, util.ZipSetup, unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
def names(traversable):
|
||||
return {item.name for item in traversable.iterdir()}
|
||||
|
||||
|
||||
class ResourceLoaderTests(util.DiskSetup, unittest.TestCase):
|
||||
def test_resource_contents(self):
|
||||
package = util.create_package(
|
||||
file=self.data, path=self.data.__file__, contents=['A', 'B', 'C']
|
||||
)
|
||||
self.assertEqual(names(resources.files(package)), {'A', 'B', 'C'})
|
||||
|
||||
def test_is_file(self):
|
||||
package = util.create_package(
|
||||
file=self.data,
|
||||
path=self.data.__file__,
|
||||
contents=['A', 'B', 'C', 'D/E', 'D/F'],
|
||||
)
|
||||
self.assertTrue(resources.files(package).joinpath('B').is_file())
|
||||
|
||||
def test_is_dir(self):
|
||||
package = util.create_package(
|
||||
file=self.data,
|
||||
path=self.data.__file__,
|
||||
contents=['A', 'B', 'C', 'D/E', 'D/F'],
|
||||
)
|
||||
self.assertTrue(resources.files(package).joinpath('D').is_dir())
|
||||
|
||||
def test_resource_missing(self):
|
||||
package = util.create_package(
|
||||
file=self.data,
|
||||
path=self.data.__file__,
|
||||
contents=['A', 'B', 'C', 'D/E', 'D/F'],
|
||||
)
|
||||
self.assertFalse(resources.files(package).joinpath('Z').is_file())
|
||||
|
||||
|
||||
class ResourceCornerCaseTests(util.DiskSetup, unittest.TestCase):
|
||||
def test_package_has_no_reader_fallback(self):
|
||||
"""
|
||||
Test odd ball packages which:
|
||||
# 1. Do not have a ResourceReader as a loader
|
||||
# 2. Are not on the file system
|
||||
# 3. Are not in a zip file
|
||||
"""
|
||||
module = util.create_package(
|
||||
file=self.data, path=self.data.__file__, contents=['A', 'B', 'C']
|
||||
)
|
||||
# Give the module a dummy loader.
|
||||
module.__loader__ = object()
|
||||
# Give the module a dummy origin.
|
||||
module.__file__ = '/path/which/shall/not/be/named'
|
||||
module.__spec__.loader = module.__loader__
|
||||
module.__spec__.origin = module.__file__
|
||||
self.assertFalse(resources.files(module).joinpath('A').is_file())
|
||||
|
||||
|
||||
class ResourceFromZipsTest01(util.ZipSetup, unittest.TestCase):
|
||||
def test_is_submodule_resource(self):
|
||||
submodule = import_module('data01.subdirectory')
|
||||
self.assertTrue(resources.files(submodule).joinpath('binary.file').is_file())
|
||||
|
||||
def test_read_submodule_resource_by_name(self):
|
||||
self.assertTrue(
|
||||
resources.files('data01.subdirectory').joinpath('binary.file').is_file()
|
||||
)
|
||||
|
||||
def test_submodule_contents(self):
|
||||
submodule = import_module('data01.subdirectory')
|
||||
self.assertEqual(
|
||||
names(resources.files(submodule)), {'__init__.py', 'binary.file'}
|
||||
)
|
||||
|
||||
def test_submodule_contents_by_name(self):
|
||||
self.assertEqual(
|
||||
names(resources.files('data01.subdirectory')),
|
||||
{'__init__.py', 'binary.file'},
|
||||
)
|
||||
|
||||
def test_as_file_directory(self):
|
||||
with resources.as_file(resources.files('data01')) as data:
|
||||
assert data.name == 'data01'
|
||||
assert data.is_dir()
|
||||
assert data.joinpath('subdirectory').is_dir()
|
||||
assert len(list(data.iterdir()))
|
||||
assert not data.parent.exists()
|
||||
|
||||
|
||||
class ResourceFromZipsTest02(util.ZipSetup, unittest.TestCase):
|
||||
MODULE = 'data02'
|
||||
|
||||
def test_unrelated_contents(self):
|
||||
"""
|
||||
Test thata zip with two unrelated subpackages return
|
||||
distinct resources. Ref python/importlib_resources#44.
|
||||
"""
|
||||
self.assertEqual(
|
||||
names(resources.files('data02.one')),
|
||||
{'__init__.py', 'resource1.txt'},
|
||||
)
|
||||
self.assertEqual(
|
||||
names(resources.files('data02.two')),
|
||||
{'__init__.py', 'resource2.txt'},
|
||||
)
|
||||
|
||||
|
||||
class DeletingZipsTest(util.ZipSetup, unittest.TestCase):
|
||||
"""Having accessed resources in a zip file should not keep an open
|
||||
reference to the zip.
|
||||
"""
|
||||
|
||||
def test_iterdir_does_not_keep_open(self):
|
||||
[item.name for item in resources.files('data01').iterdir()]
|
||||
|
||||
def test_is_file_does_not_keep_open(self):
|
||||
resources.files('data01').joinpath('binary.file').is_file()
|
||||
|
||||
def test_is_file_failure_does_not_keep_open(self):
|
||||
resources.files('data01').joinpath('not-present').is_file()
|
||||
|
||||
@unittest.skip("Desired but not supported.")
|
||||
def test_as_file_does_not_keep_open(self): # pragma: no cover
|
||||
resources.as_file(resources.files('data01') / 'binary.file')
|
||||
|
||||
def test_entered_path_does_not_keep_open(self):
|
||||
"""
|
||||
Mimic what certifi does on import to make its bundle
|
||||
available for the process duration.
|
||||
"""
|
||||
resources.as_file(resources.files('data01') / 'binary.file').__enter__()
|
||||
|
||||
def test_read_binary_does_not_keep_open(self):
|
||||
resources.files('data01').joinpath('binary.file').read_bytes()
|
||||
|
||||
def test_read_text_does_not_keep_open(self):
|
||||
resources.files('data01').joinpath('utf-8.file').read_text(encoding='utf-8')
|
||||
|
||||
|
||||
class ResourceFromNamespaceTests:
|
||||
def test_is_submodule_resource(self):
|
||||
self.assertTrue(
|
||||
resources.files(import_module('namespacedata01'))
|
||||
.joinpath('binary.file')
|
||||
.is_file()
|
||||
)
|
||||
|
||||
def test_read_submodule_resource_by_name(self):
|
||||
self.assertTrue(
|
||||
resources.files('namespacedata01').joinpath('binary.file').is_file()
|
||||
)
|
||||
|
||||
def test_submodule_contents(self):
|
||||
contents = names(resources.files(import_module('namespacedata01')))
|
||||
try:
|
||||
contents.remove('__pycache__')
|
||||
except KeyError:
|
||||
pass
|
||||
self.assertEqual(
|
||||
contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'}
|
||||
)
|
||||
|
||||
def test_submodule_contents_by_name(self):
|
||||
contents = names(resources.files('namespacedata01'))
|
||||
try:
|
||||
contents.remove('__pycache__')
|
||||
except KeyError:
|
||||
pass
|
||||
self.assertEqual(
|
||||
contents, {'subdirectory', 'binary.file', 'utf-8.file', 'utf-16.file'}
|
||||
)
|
||||
|
||||
def test_submodule_sub_contents(self):
|
||||
contents = names(resources.files(import_module('namespacedata01.subdirectory')))
|
||||
try:
|
||||
contents.remove('__pycache__')
|
||||
except KeyError:
|
||||
pass
|
||||
self.assertEqual(contents, {'binary.file'})
|
||||
|
||||
def test_submodule_sub_contents_by_name(self):
|
||||
contents = names(resources.files('namespacedata01.subdirectory'))
|
||||
try:
|
||||
contents.remove('__pycache__')
|
||||
except KeyError:
|
||||
pass
|
||||
self.assertEqual(contents, {'binary.file'})
|
||||
|
||||
|
||||
class ResourceFromNamespaceDiskTests(
|
||||
util.DiskSetup,
|
||||
ResourceFromNamespaceTests,
|
||||
unittest.TestCase,
|
||||
):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
|
||||
class ResourceFromNamespaceZipTests(
|
||||
util.ZipSetup,
|
||||
ResourceFromNamespaceTests,
|
||||
unittest.TestCase,
|
||||
):
|
||||
MODULE = 'namespacedata01'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
206
Dependencies/Python/Lib/test/test_importlib/resources/util.py
vendored
Normal file
206
Dependencies/Python/Lib/test/test_importlib/resources/util.py
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
import abc
|
||||
import importlib
|
||||
import io
|
||||
import sys
|
||||
import types
|
||||
import pathlib
|
||||
import contextlib
|
||||
|
||||
from importlib.resources.abc import ResourceReader
|
||||
from test.support import import_helper, os_helper
|
||||
from . import zip as zip_
|
||||
from . import _path
|
||||
|
||||
|
||||
from importlib.machinery import ModuleSpec
|
||||
|
||||
|
||||
class Reader(ResourceReader):
|
||||
def __init__(self, **kwargs):
|
||||
vars(self).update(kwargs)
|
||||
|
||||
def get_resource_reader(self, package):
|
||||
return self
|
||||
|
||||
def open_resource(self, path):
|
||||
self._path = path
|
||||
if isinstance(self.file, Exception):
|
||||
raise self.file
|
||||
return self.file
|
||||
|
||||
def resource_path(self, path_):
|
||||
self._path = path_
|
||||
if isinstance(self.path, Exception):
|
||||
raise self.path
|
||||
return self.path
|
||||
|
||||
def is_resource(self, path_):
|
||||
self._path = path_
|
||||
if isinstance(self.path, Exception):
|
||||
raise self.path
|
||||
|
||||
def part(entry):
|
||||
return entry.split('/')
|
||||
|
||||
return any(
|
||||
len(parts) == 1 and parts[0] == path_ for parts in map(part, self._contents)
|
||||
)
|
||||
|
||||
def contents(self):
|
||||
if isinstance(self.path, Exception):
|
||||
raise self.path
|
||||
yield from self._contents
|
||||
|
||||
|
||||
def create_package_from_loader(loader, is_package=True):
|
||||
name = 'testingpackage'
|
||||
module = types.ModuleType(name)
|
||||
spec = ModuleSpec(name, loader, origin='does-not-exist', is_package=is_package)
|
||||
module.__spec__ = spec
|
||||
module.__loader__ = loader
|
||||
return module
|
||||
|
||||
|
||||
def create_package(file=None, path=None, is_package=True, contents=()):
|
||||
return create_package_from_loader(
|
||||
Reader(file=file, path=path, _contents=contents),
|
||||
is_package,
|
||||
)
|
||||
|
||||
|
||||
class CommonTestsBase(metaclass=abc.ABCMeta):
|
||||
"""
|
||||
Tests shared by test_open, test_path, and test_read.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def execute(self, package, path):
|
||||
"""
|
||||
Call the pertinent legacy API function (e.g. open_text, path)
|
||||
on package and path.
|
||||
"""
|
||||
|
||||
def test_package_name(self):
|
||||
"""
|
||||
Passing in the package name should succeed.
|
||||
"""
|
||||
self.execute(self.data.__name__, 'utf-8.file')
|
||||
|
||||
def test_package_object(self):
|
||||
"""
|
||||
Passing in the package itself should succeed.
|
||||
"""
|
||||
self.execute(self.data, 'utf-8.file')
|
||||
|
||||
def test_string_path(self):
|
||||
"""
|
||||
Passing in a string for the path should succeed.
|
||||
"""
|
||||
path = 'utf-8.file'
|
||||
self.execute(self.data, path)
|
||||
|
||||
def test_pathlib_path(self):
|
||||
"""
|
||||
Passing in a pathlib.PurePath object for the path should succeed.
|
||||
"""
|
||||
path = pathlib.PurePath('utf-8.file')
|
||||
self.execute(self.data, path)
|
||||
|
||||
def test_importing_module_as_side_effect(self):
|
||||
"""
|
||||
The anchor package can already be imported.
|
||||
"""
|
||||
del sys.modules[self.data.__name__]
|
||||
self.execute(self.data.__name__, 'utf-8.file')
|
||||
|
||||
def test_missing_path(self):
|
||||
"""
|
||||
Attempting to open or read or request the path for a
|
||||
non-existent path should succeed if open_resource
|
||||
can return a viable data stream.
|
||||
"""
|
||||
bytes_data = io.BytesIO(b'Hello, world!')
|
||||
package = create_package(file=bytes_data, path=FileNotFoundError())
|
||||
self.execute(package, 'utf-8.file')
|
||||
self.assertEqual(package.__loader__._path, 'utf-8.file')
|
||||
|
||||
def test_extant_path(self):
|
||||
# Attempting to open or read or request the path when the
|
||||
# path does exist should still succeed. Does not assert
|
||||
# anything about the result.
|
||||
bytes_data = io.BytesIO(b'Hello, world!')
|
||||
# any path that exists
|
||||
path = __file__
|
||||
package = create_package(file=bytes_data, path=path)
|
||||
self.execute(package, 'utf-8.file')
|
||||
self.assertEqual(package.__loader__._path, 'utf-8.file')
|
||||
|
||||
def test_useless_loader(self):
|
||||
package = create_package(file=FileNotFoundError(), path=FileNotFoundError())
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
self.execute(package, 'utf-8.file')
|
||||
|
||||
|
||||
fixtures = dict(
|
||||
data01={
|
||||
'__init__.py': '',
|
||||
'binary.file': bytes(range(4)),
|
||||
'utf-16.file': '\ufeffHello, UTF-16 world!\n'.encode('utf-16-le'),
|
||||
'utf-8.file': 'Hello, UTF-8 world!\n'.encode('utf-8'),
|
||||
'subdirectory': {
|
||||
'__init__.py': '',
|
||||
'binary.file': bytes(range(4, 8)),
|
||||
},
|
||||
},
|
||||
data02={
|
||||
'__init__.py': '',
|
||||
'one': {'__init__.py': '', 'resource1.txt': 'one resource'},
|
||||
'two': {'__init__.py': '', 'resource2.txt': 'two resource'},
|
||||
'subdirectory': {'subsubdir': {'resource.txt': 'a resource'}},
|
||||
},
|
||||
namespacedata01={
|
||||
'binary.file': bytes(range(4)),
|
||||
'utf-16.file': '\ufeffHello, UTF-16 world!\n'.encode('utf-16-le'),
|
||||
'utf-8.file': 'Hello, UTF-8 world!\n'.encode('utf-8'),
|
||||
'subdirectory': {
|
||||
'binary.file': bytes(range(12, 16)),
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class ModuleSetup:
|
||||
def setUp(self):
|
||||
self.fixtures = contextlib.ExitStack()
|
||||
self.addCleanup(self.fixtures.close)
|
||||
|
||||
self.fixtures.enter_context(import_helper.isolated_modules())
|
||||
self.data = self.load_fixture(self.MODULE)
|
||||
|
||||
def load_fixture(self, module):
|
||||
self.tree_on_path({module: fixtures[module]})
|
||||
return importlib.import_module(module)
|
||||
|
||||
|
||||
class ZipSetup(ModuleSetup):
|
||||
MODULE = 'data01'
|
||||
|
||||
def tree_on_path(self, spec):
|
||||
temp_dir = self.fixtures.enter_context(os_helper.temp_dir())
|
||||
modules = pathlib.Path(temp_dir) / 'zipped modules.zip'
|
||||
self.fixtures.enter_context(
|
||||
import_helper.DirsOnSysPath(str(zip_.make_zip_file(spec, modules)))
|
||||
)
|
||||
|
||||
|
||||
class DiskSetup(ModuleSetup):
|
||||
MODULE = 'data01'
|
||||
|
||||
def tree_on_path(self, spec):
|
||||
temp_dir = self.fixtures.enter_context(os_helper.temp_dir())
|
||||
_path.build(spec, pathlib.Path(temp_dir))
|
||||
self.fixtures.enter_context(import_helper.DirsOnSysPath(temp_dir))
|
||||
|
||||
|
||||
class CommonTests(DiskSetup, CommonTestsBase):
|
||||
pass
|
||||
24
Dependencies/Python/Lib/test/test_importlib/resources/zip.py
vendored
Normal file
24
Dependencies/Python/Lib/test/test_importlib/resources/zip.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
"""
|
||||
Generate zip test data files.
|
||||
"""
|
||||
|
||||
import zipfile
|
||||
|
||||
|
||||
def make_zip_file(tree, dst):
|
||||
"""
|
||||
Zip the files in tree into a new zipfile at dst.
|
||||
"""
|
||||
with zipfile.ZipFile(dst, 'w') as zf:
|
||||
for name, contents in walk(tree):
|
||||
zf.writestr(name, contents)
|
||||
zipfile._path.CompleteDirs.inject(zf)
|
||||
return dst
|
||||
|
||||
|
||||
def walk(tree, prefix=''):
|
||||
for name, contents in tree.items():
|
||||
if isinstance(contents, dict):
|
||||
yield from walk(contents, prefix=f'{prefix}{name}/')
|
||||
else:
|
||||
yield f'{prefix}{name}', contents
|
||||
5
Dependencies/Python/Lib/test/test_importlib/source/__init__.py
vendored
Normal file
5
Dependencies/Python/Lib/test/test_importlib/source/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
from test.support import load_package_tests
|
||||
|
||||
def load_tests(*args):
|
||||
return load_package_tests(os.path.dirname(__file__), *args)
|
||||
4
Dependencies/Python/Lib/test/test_importlib/source/__main__.py
vendored
Normal file
4
Dependencies/Python/Lib/test/test_importlib/source/__main__.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
from . import load_tests
|
||||
import unittest
|
||||
|
||||
unittest.main()
|
||||
78
Dependencies/Python/Lib/test/test_importlib/source/test_case_sensitivity.py
vendored
Normal file
78
Dependencies/Python/Lib/test/test_importlib/source/test_case_sensitivity.py
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
"""Test case-sensitivity (PEP 235)."""
|
||||
import sys
|
||||
|
||||
from test.test_importlib import util
|
||||
|
||||
importlib = util.import_importlib('importlib')
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import os
|
||||
from test.support import os_helper
|
||||
import unittest
|
||||
|
||||
|
||||
@util.case_insensitive_tests
|
||||
class CaseSensitivityTest(util.CASEOKTestBase):
|
||||
|
||||
"""PEP 235 dictates that on case-preserving, case-insensitive file systems
|
||||
that imports are case-sensitive unless the PYTHONCASEOK environment
|
||||
variable is set."""
|
||||
|
||||
name = 'MoDuLe'
|
||||
assert name != name.lower()
|
||||
|
||||
def finder(self, path):
|
||||
return self.machinery.FileFinder(path,
|
||||
(self.machinery.SourceFileLoader,
|
||||
self.machinery.SOURCE_SUFFIXES),
|
||||
(self.machinery.SourcelessFileLoader,
|
||||
self.machinery.BYTECODE_SUFFIXES))
|
||||
|
||||
def sensitivity_test(self):
|
||||
"""Look for a module with matching and non-matching sensitivity."""
|
||||
sensitive_pkg = 'sensitive.{0}'.format(self.name)
|
||||
insensitive_pkg = 'insensitive.{0}'.format(self.name.lower())
|
||||
context = util.create_modules(insensitive_pkg, sensitive_pkg)
|
||||
with context as mapping:
|
||||
sensitive_path = os.path.join(mapping['.root'], 'sensitive')
|
||||
insensitive_path = os.path.join(mapping['.root'], 'insensitive')
|
||||
sensitive_finder = self.finder(sensitive_path)
|
||||
insensitive_finder = self.finder(insensitive_path)
|
||||
return self.find(sensitive_finder), self.find(insensitive_finder)
|
||||
|
||||
@unittest.skipIf(sys.flags.ignore_environment, 'ignore_environment flag was set')
|
||||
def test_sensitive(self):
|
||||
with os_helper.EnvironmentVarGuard() as env:
|
||||
env.unset('PYTHONCASEOK')
|
||||
self.caseok_env_changed(should_exist=False)
|
||||
sensitive, insensitive = self.sensitivity_test()
|
||||
self.assertIsNotNone(sensitive)
|
||||
self.assertIn(self.name, sensitive.get_filename(self.name))
|
||||
self.assertIsNone(insensitive)
|
||||
|
||||
@unittest.skipIf(sys.flags.ignore_environment, 'ignore_environment flag was set')
|
||||
def test_insensitive(self):
|
||||
with os_helper.EnvironmentVarGuard() as env:
|
||||
env.set('PYTHONCASEOK', '1')
|
||||
self.caseok_env_changed(should_exist=True)
|
||||
sensitive, insensitive = self.sensitivity_test()
|
||||
self.assertIsNotNone(sensitive)
|
||||
self.assertIn(self.name, sensitive.get_filename(self.name))
|
||||
self.assertIsNotNone(insensitive)
|
||||
self.assertIn(self.name, insensitive.get_filename(self.name))
|
||||
|
||||
|
||||
class CaseSensitivityTestPEP451(CaseSensitivityTest):
|
||||
def find(self, finder):
|
||||
found = finder.find_spec(self.name)
|
||||
return found.loader if found is not None else found
|
||||
|
||||
|
||||
(Frozen_CaseSensitivityTestPEP451,
|
||||
Source_CaseSensitivityTestPEP451
|
||||
) = util.test_both(CaseSensitivityTestPEP451, importlib=importlib,
|
||||
machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
795
Dependencies/Python/Lib/test/test_importlib/source/test_file_loader.py
vendored
Normal file
795
Dependencies/Python/Lib/test/test_importlib/source/test_file_loader.py
vendored
Normal file
@@ -0,0 +1,795 @@
|
||||
from test.test_importlib import abc, util
|
||||
|
||||
importlib = util.import_importlib('importlib')
|
||||
importlib_abc = util.import_importlib('importlib.abc')
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
importlib_util = util.import_importlib('importlib.util')
|
||||
|
||||
import errno
|
||||
import marshal
|
||||
import os
|
||||
import py_compile
|
||||
import shutil
|
||||
import stat
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from test.support.import_helper import make_legacy_pyc, unload
|
||||
|
||||
from test.test_py_compile import without_source_date_epoch
|
||||
from test.test_py_compile import SourceDateEpochTestMeta
|
||||
|
||||
|
||||
class SimpleTest(abc.LoaderTests):
|
||||
|
||||
"""Should have no issue importing a source module [basic]. And if there is
|
||||
a syntax error, it should raise a SyntaxError [syntax error].
|
||||
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.name = 'spam'
|
||||
self.filepath = os.path.join('ham', self.name + '.py')
|
||||
self.loader = self.machinery.SourceFileLoader(self.name, self.filepath)
|
||||
|
||||
def test_load_module_API(self):
|
||||
class Tester(self.abc.FileLoader):
|
||||
def get_source(self, _): return 'attr = 42'
|
||||
def is_package(self, _): return False
|
||||
|
||||
loader = Tester('blah', 'blah.py')
|
||||
self.addCleanup(unload, 'blah')
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
module = loader.load_module() # Should not raise an exception.
|
||||
|
||||
def test_get_filename_API(self):
|
||||
# If fullname is not set then assume self.path is desired.
|
||||
class Tester(self.abc.FileLoader):
|
||||
def get_code(self, _): pass
|
||||
def get_source(self, _): pass
|
||||
def is_package(self, _): pass
|
||||
|
||||
path = 'some_path'
|
||||
name = 'some_name'
|
||||
loader = Tester(name, path)
|
||||
self.assertEqual(path, loader.get_filename(name))
|
||||
self.assertEqual(path, loader.get_filename())
|
||||
self.assertEqual(path, loader.get_filename(None))
|
||||
with self.assertRaises(ImportError):
|
||||
loader.get_filename(name + 'XXX')
|
||||
|
||||
def test_equality(self):
|
||||
other = self.machinery.SourceFileLoader(self.name, self.filepath)
|
||||
self.assertEqual(self.loader, other)
|
||||
|
||||
def test_inequality(self):
|
||||
other = self.machinery.SourceFileLoader('_' + self.name, self.filepath)
|
||||
self.assertNotEqual(self.loader, other)
|
||||
|
||||
# [basic]
|
||||
def test_module(self):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
module = loader.load_module('_temp')
|
||||
self.assertIn('_temp', sys.modules)
|
||||
check = {'__name__': '_temp', '__file__': mapping['_temp'],
|
||||
'__package__': ''}
|
||||
for attr, value in check.items():
|
||||
self.assertEqual(getattr(module, attr), value)
|
||||
|
||||
def test_package(self):
|
||||
with util.create_modules('_pkg.__init__') as mapping:
|
||||
loader = self.machinery.SourceFileLoader('_pkg',
|
||||
mapping['_pkg.__init__'])
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
module = loader.load_module('_pkg')
|
||||
self.assertIn('_pkg', sys.modules)
|
||||
check = {'__name__': '_pkg', '__file__': mapping['_pkg.__init__'],
|
||||
'__path__': [os.path.dirname(mapping['_pkg.__init__'])],
|
||||
'__package__': '_pkg'}
|
||||
for attr, value in check.items():
|
||||
self.assertEqual(getattr(module, attr), value)
|
||||
|
||||
|
||||
def test_lacking_parent(self):
|
||||
with util.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
|
||||
loader = self.machinery.SourceFileLoader('_pkg.mod',
|
||||
mapping['_pkg.mod'])
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
module = loader.load_module('_pkg.mod')
|
||||
self.assertIn('_pkg.mod', sys.modules)
|
||||
check = {'__name__': '_pkg.mod', '__file__': mapping['_pkg.mod'],
|
||||
'__package__': '_pkg'}
|
||||
for attr, value in check.items():
|
||||
self.assertEqual(getattr(module, attr), value)
|
||||
|
||||
def fake_mtime(self, fxn):
|
||||
"""Fake mtime to always be higher than expected."""
|
||||
return lambda name: fxn(name) + 1
|
||||
|
||||
def test_module_reuse(self):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
module = loader.load_module('_temp')
|
||||
module_id = id(module)
|
||||
module_dict_id = id(module.__dict__)
|
||||
with open(mapping['_temp'], 'w', encoding='utf-8') as file:
|
||||
file.write("testing_var = 42\n")
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
module = loader.load_module('_temp')
|
||||
self.assertIn('testing_var', module.__dict__,
|
||||
"'testing_var' not in "
|
||||
"{0}".format(list(module.__dict__.keys())))
|
||||
self.assertEqual(module, sys.modules['_temp'])
|
||||
self.assertEqual(id(module), module_id)
|
||||
self.assertEqual(id(module.__dict__), module_dict_id)
|
||||
|
||||
def test_state_after_failure(self):
|
||||
# A failed reload should leave the original module intact.
|
||||
attributes = ('__file__', '__path__', '__package__')
|
||||
value = '<test>'
|
||||
name = '_temp'
|
||||
with util.create_modules(name) as mapping:
|
||||
orig_module = types.ModuleType(name)
|
||||
for attr in attributes:
|
||||
setattr(orig_module, attr, value)
|
||||
with open(mapping[name], 'w', encoding='utf-8') as file:
|
||||
file.write('+++ bad syntax +++')
|
||||
loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
|
||||
with self.assertRaises(SyntaxError):
|
||||
loader.exec_module(orig_module)
|
||||
for attr in attributes:
|
||||
self.assertEqual(getattr(orig_module, attr), value)
|
||||
with self.assertRaises(SyntaxError):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
loader.load_module(name)
|
||||
for attr in attributes:
|
||||
self.assertEqual(getattr(orig_module, attr), value)
|
||||
|
||||
# [syntax error]
|
||||
def test_bad_syntax(self):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
with open(mapping['_temp'], 'w', encoding='utf-8') as file:
|
||||
file.write('=')
|
||||
loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
|
||||
with self.assertRaises(SyntaxError):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
loader.load_module('_temp')
|
||||
self.assertNotIn('_temp', sys.modules)
|
||||
|
||||
def test_file_from_empty_string_dir(self):
|
||||
# Loading a module found from an empty string entry on sys.path should
|
||||
# not only work, but keep all attributes relative.
|
||||
file_path = '_temp.py'
|
||||
with open(file_path, 'w', encoding='utf-8') as file:
|
||||
file.write("# test file for importlib")
|
||||
try:
|
||||
with util.uncache('_temp'):
|
||||
loader = self.machinery.SourceFileLoader('_temp', file_path)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
mod = loader.load_module('_temp')
|
||||
self.assertEqual(file_path, mod.__file__)
|
||||
self.assertEqual(self.util.cache_from_source(file_path),
|
||||
mod.__cached__)
|
||||
finally:
|
||||
os.unlink(file_path)
|
||||
pycache = os.path.dirname(self.util.cache_from_source(file_path))
|
||||
if os.path.exists(pycache):
|
||||
shutil.rmtree(pycache)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_timestamp_overflow(self):
|
||||
# When a modification timestamp is larger than 2**32, it should be
|
||||
# truncated rather than raise an OverflowError.
|
||||
with util.create_modules('_temp') as mapping:
|
||||
source = mapping['_temp']
|
||||
compiled = self.util.cache_from_source(source)
|
||||
with open(source, 'w', encoding='utf-8') as f:
|
||||
f.write("x = 5")
|
||||
try:
|
||||
os.utime(source, (2 ** 33 - 5, 2 ** 33 - 5))
|
||||
except OverflowError:
|
||||
self.skipTest("cannot set modification time to large integer")
|
||||
except OSError as e:
|
||||
if e.errno != getattr(errno, 'EOVERFLOW', None):
|
||||
raise
|
||||
self.skipTest("cannot set modification time to large integer ({})".format(e))
|
||||
loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
|
||||
# PEP 451
|
||||
module = types.ModuleType('_temp')
|
||||
module.__spec__ = self.util.spec_from_loader('_temp', loader)
|
||||
loader.exec_module(module)
|
||||
self.assertEqual(module.x, 5)
|
||||
self.assertTrue(os.path.exists(compiled))
|
||||
os.unlink(compiled)
|
||||
# PEP 302
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
mod = loader.load_module('_temp')
|
||||
# Sanity checks.
|
||||
self.assertEqual(mod.__cached__, compiled)
|
||||
self.assertEqual(mod.x, 5)
|
||||
# The pyc file was created.
|
||||
self.assertTrue(os.path.exists(compiled))
|
||||
|
||||
def test_unloadable(self):
|
||||
loader = self.machinery.SourceFileLoader('good name', {})
|
||||
module = types.ModuleType('bad name')
|
||||
module.__spec__ = self.machinery.ModuleSpec('bad name', loader)
|
||||
with self.assertRaises(ImportError):
|
||||
loader.exec_module(module)
|
||||
with self.assertRaises(ImportError):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
loader.load_module('bad name')
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_checked_hash_based_pyc(self):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
source = mapping['_temp']
|
||||
pyc = self.util.cache_from_source(source)
|
||||
with open(source, 'wb') as fp:
|
||||
fp.write(b'state = "old"')
|
||||
os.utime(source, (50, 50))
|
||||
py_compile.compile(
|
||||
source,
|
||||
invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH,
|
||||
)
|
||||
loader = self.machinery.SourceFileLoader('_temp', source)
|
||||
mod = types.ModuleType('_temp')
|
||||
mod.__spec__ = self.util.spec_from_loader('_temp', loader)
|
||||
loader.exec_module(mod)
|
||||
self.assertEqual(mod.state, 'old')
|
||||
# Write a new source with the same mtime and size as before.
|
||||
with open(source, 'wb') as fp:
|
||||
fp.write(b'state = "new"')
|
||||
os.utime(source, (50, 50))
|
||||
loader.exec_module(mod)
|
||||
self.assertEqual(mod.state, 'new')
|
||||
with open(pyc, 'rb') as fp:
|
||||
data = fp.read()
|
||||
self.assertEqual(int.from_bytes(data[4:8], 'little'), 0b11)
|
||||
self.assertEqual(
|
||||
self.util.source_hash(b'state = "new"'),
|
||||
data[8:16],
|
||||
)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_overridden_checked_hash_based_pyc(self):
|
||||
with util.create_modules('_temp') as mapping, \
|
||||
unittest.mock.patch('_imp.check_hash_based_pycs', 'never'):
|
||||
source = mapping['_temp']
|
||||
pyc = self.util.cache_from_source(source)
|
||||
with open(source, 'wb') as fp:
|
||||
fp.write(b'state = "old"')
|
||||
os.utime(source, (50, 50))
|
||||
py_compile.compile(
|
||||
source,
|
||||
invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH,
|
||||
)
|
||||
loader = self.machinery.SourceFileLoader('_temp', source)
|
||||
mod = types.ModuleType('_temp')
|
||||
mod.__spec__ = self.util.spec_from_loader('_temp', loader)
|
||||
loader.exec_module(mod)
|
||||
self.assertEqual(mod.state, 'old')
|
||||
# Write a new source with the same mtime and size as before.
|
||||
with open(source, 'wb') as fp:
|
||||
fp.write(b'state = "new"')
|
||||
os.utime(source, (50, 50))
|
||||
loader.exec_module(mod)
|
||||
self.assertEqual(mod.state, 'old')
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_unchecked_hash_based_pyc(self):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
source = mapping['_temp']
|
||||
pyc = self.util.cache_from_source(source)
|
||||
with open(source, 'wb') as fp:
|
||||
fp.write(b'state = "old"')
|
||||
os.utime(source, (50, 50))
|
||||
py_compile.compile(
|
||||
source,
|
||||
invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH,
|
||||
)
|
||||
loader = self.machinery.SourceFileLoader('_temp', source)
|
||||
mod = types.ModuleType('_temp')
|
||||
mod.__spec__ = self.util.spec_from_loader('_temp', loader)
|
||||
loader.exec_module(mod)
|
||||
self.assertEqual(mod.state, 'old')
|
||||
# Update the source file, which should be ignored.
|
||||
with open(source, 'wb') as fp:
|
||||
fp.write(b'state = "new"')
|
||||
loader.exec_module(mod)
|
||||
self.assertEqual(mod.state, 'old')
|
||||
with open(pyc, 'rb') as fp:
|
||||
data = fp.read()
|
||||
self.assertEqual(int.from_bytes(data[4:8], 'little'), 0b1)
|
||||
self.assertEqual(
|
||||
self.util.source_hash(b'state = "old"'),
|
||||
data[8:16],
|
||||
)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_overridden_unchecked_hash_based_pyc(self):
|
||||
with util.create_modules('_temp') as mapping, \
|
||||
unittest.mock.patch('_imp.check_hash_based_pycs', 'always'):
|
||||
source = mapping['_temp']
|
||||
pyc = self.util.cache_from_source(source)
|
||||
with open(source, 'wb') as fp:
|
||||
fp.write(b'state = "old"')
|
||||
os.utime(source, (50, 50))
|
||||
py_compile.compile(
|
||||
source,
|
||||
invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH,
|
||||
)
|
||||
loader = self.machinery.SourceFileLoader('_temp', source)
|
||||
mod = types.ModuleType('_temp')
|
||||
mod.__spec__ = self.util.spec_from_loader('_temp', loader)
|
||||
loader.exec_module(mod)
|
||||
self.assertEqual(mod.state, 'old')
|
||||
# Update the source file, which should be ignored.
|
||||
with open(source, 'wb') as fp:
|
||||
fp.write(b'state = "new"')
|
||||
loader.exec_module(mod)
|
||||
self.assertEqual(mod.state, 'new')
|
||||
with open(pyc, 'rb') as fp:
|
||||
data = fp.read()
|
||||
self.assertEqual(int.from_bytes(data[4:8], 'little'), 0b1)
|
||||
self.assertEqual(
|
||||
self.util.source_hash(b'state = "new"'),
|
||||
data[8:16],
|
||||
)
|
||||
|
||||
|
||||
(Frozen_SimpleTest,
|
||||
Source_SimpleTest
|
||||
) = util.test_both(SimpleTest, importlib=importlib, machinery=machinery,
|
||||
abc=importlib_abc, util=importlib_util)
|
||||
|
||||
|
||||
class SourceDateEpochTestMeta(SourceDateEpochTestMeta,
|
||||
type(Source_SimpleTest)):
|
||||
pass
|
||||
|
||||
|
||||
class SourceDateEpoch_SimpleTest(Source_SimpleTest,
|
||||
metaclass=SourceDateEpochTestMeta,
|
||||
source_date_epoch=True):
|
||||
pass
|
||||
|
||||
|
||||
class BadBytecodeTest:
|
||||
|
||||
def import_(self, file, module_name):
|
||||
raise NotImplementedError
|
||||
|
||||
def manipulate_bytecode(self,
|
||||
name, mapping, manipulator, *,
|
||||
del_source=False,
|
||||
invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP):
|
||||
"""Manipulate the bytecode of a module by passing it into a callable
|
||||
that returns what to use as the new bytecode."""
|
||||
try:
|
||||
del sys.modules['_temp']
|
||||
except KeyError:
|
||||
pass
|
||||
py_compile.compile(mapping[name], invalidation_mode=invalidation_mode)
|
||||
if not del_source:
|
||||
bytecode_path = self.util.cache_from_source(mapping[name])
|
||||
else:
|
||||
os.unlink(mapping[name])
|
||||
bytecode_path = make_legacy_pyc(mapping[name])
|
||||
if manipulator:
|
||||
with open(bytecode_path, 'rb') as file:
|
||||
bc = file.read()
|
||||
new_bc = manipulator(bc)
|
||||
with open(bytecode_path, 'wb') as file:
|
||||
if new_bc is not None:
|
||||
file.write(new_bc)
|
||||
return bytecode_path
|
||||
|
||||
def _test_empty_file(self, test, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: b'',
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def _test_partial_magic(self, test, *, del_source=False):
|
||||
# When their are less than 4 bytes to a .pyc, regenerate it if
|
||||
# possible, else raise ImportError.
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:3],
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_magic_only(self, test, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:4],
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_partial_flags(self, test, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:7],
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_partial_hash(self, test, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode(
|
||||
'_temp',
|
||||
mapping,
|
||||
lambda bc: bc[:13],
|
||||
del_source=del_source,
|
||||
invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH,
|
||||
)
|
||||
test('_temp', mapping, bc_path)
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode(
|
||||
'_temp',
|
||||
mapping,
|
||||
lambda bc: bc[:13],
|
||||
del_source=del_source,
|
||||
invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH,
|
||||
)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_partial_timestamp(self, test, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:11],
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_partial_size(self, test, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:15],
|
||||
del_source=del_source)
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
def _test_no_marshal(self, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:16],
|
||||
del_source=del_source)
|
||||
file_path = mapping['_temp'] if not del_source else bc_path
|
||||
with self.assertRaises(EOFError):
|
||||
self.import_(file_path, '_temp')
|
||||
|
||||
def _test_non_code_marshal(self, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bytecode_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:16] + marshal.dumps(b'abcd'),
|
||||
del_source=del_source)
|
||||
file_path = mapping['_temp'] if not del_source else bytecode_path
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.import_(file_path, '_temp')
|
||||
self.assertEqual(cm.exception.name, '_temp')
|
||||
self.assertEqual(cm.exception.path, bytecode_path)
|
||||
|
||||
def _test_bad_marshal(self, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bytecode_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: bc[:16] + b'<test>',
|
||||
del_source=del_source)
|
||||
file_path = mapping['_temp'] if not del_source else bytecode_path
|
||||
with self.assertRaises(EOFError):
|
||||
self.import_(file_path, '_temp')
|
||||
|
||||
def _test_bad_magic(self, test, *, del_source=False):
|
||||
with util.create_modules('_temp') as mapping:
|
||||
bc_path = self.manipulate_bytecode('_temp', mapping,
|
||||
lambda bc: b'\x00\x00\x00\x00' + bc[4:])
|
||||
test('_temp', mapping, bc_path)
|
||||
|
||||
|
||||
class BadBytecodeTestPEP451(BadBytecodeTest):
|
||||
|
||||
def import_(self, file, module_name):
|
||||
loader = self.loader(module_name, file)
|
||||
module = types.ModuleType(module_name)
|
||||
module.__spec__ = self.util.spec_from_loader(module_name, loader)
|
||||
loader.exec_module(module)
|
||||
|
||||
|
||||
class BadBytecodeTestPEP302(BadBytecodeTest):
|
||||
|
||||
def import_(self, file, module_name):
|
||||
loader = self.loader(module_name, file)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
module = loader.load_module(module_name)
|
||||
self.assertIn(module_name, sys.modules)
|
||||
|
||||
|
||||
class SourceLoaderBadBytecodeTest:
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.loader = cls.machinery.SourceFileLoader
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_empty_file(self):
|
||||
# When a .pyc is empty, regenerate it if possible, else raise
|
||||
# ImportError.
|
||||
def test(name, mapping, bytecode_path):
|
||||
self.import_(mapping[name], name)
|
||||
with open(bytecode_path, 'rb') as file:
|
||||
self.assertGreater(len(file.read()), 16)
|
||||
|
||||
self._test_empty_file(test)
|
||||
|
||||
def test_partial_magic(self):
|
||||
def test(name, mapping, bytecode_path):
|
||||
self.import_(mapping[name], name)
|
||||
with open(bytecode_path, 'rb') as file:
|
||||
self.assertGreater(len(file.read()), 16)
|
||||
|
||||
self._test_partial_magic(test)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_magic_only(self):
|
||||
# When there is only the magic number, regenerate the .pyc if possible,
|
||||
# else raise EOFError.
|
||||
def test(name, mapping, bytecode_path):
|
||||
self.import_(mapping[name], name)
|
||||
with open(bytecode_path, 'rb') as file:
|
||||
self.assertGreater(len(file.read()), 16)
|
||||
|
||||
self._test_magic_only(test)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_bad_magic(self):
|
||||
# When the magic number is different, the bytecode should be
|
||||
# regenerated.
|
||||
def test(name, mapping, bytecode_path):
|
||||
self.import_(mapping[name], name)
|
||||
with open(bytecode_path, 'rb') as bytecode_file:
|
||||
self.assertEqual(bytecode_file.read(4),
|
||||
self.util.MAGIC_NUMBER)
|
||||
|
||||
self._test_bad_magic(test)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_partial_timestamp(self):
|
||||
# When the timestamp is partial, regenerate the .pyc, else
|
||||
# raise EOFError.
|
||||
def test(name, mapping, bc_path):
|
||||
self.import_(mapping[name], name)
|
||||
with open(bc_path, 'rb') as file:
|
||||
self.assertGreater(len(file.read()), 16)
|
||||
|
||||
self._test_partial_timestamp(test)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_partial_flags(self):
|
||||
# When the flags is partial, regenerate the .pyc, else raise EOFError.
|
||||
def test(name, mapping, bc_path):
|
||||
self.import_(mapping[name], name)
|
||||
with open(bc_path, 'rb') as file:
|
||||
self.assertGreater(len(file.read()), 16)
|
||||
|
||||
self._test_partial_flags(test)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_partial_hash(self):
|
||||
# When the hash is partial, regenerate the .pyc, else raise EOFError.
|
||||
def test(name, mapping, bc_path):
|
||||
self.import_(mapping[name], name)
|
||||
with open(bc_path, 'rb') as file:
|
||||
self.assertGreater(len(file.read()), 16)
|
||||
|
||||
self._test_partial_hash(test)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_partial_size(self):
|
||||
# When the size is partial, regenerate the .pyc, else
|
||||
# raise EOFError.
|
||||
def test(name, mapping, bc_path):
|
||||
self.import_(mapping[name], name)
|
||||
with open(bc_path, 'rb') as file:
|
||||
self.assertGreater(len(file.read()), 16)
|
||||
|
||||
self._test_partial_size(test)
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_no_marshal(self):
|
||||
# When there is only the magic number and timestamp, raise EOFError.
|
||||
self._test_no_marshal()
|
||||
|
||||
@util.writes_bytecode_files
|
||||
def test_non_code_marshal(self):
|
||||
self._test_non_code_marshal()
|
||||
# XXX ImportError when sourceless
|
||||
|
||||
# [bad marshal]
|
||||
@util.writes_bytecode_files
|
||||
def test_bad_marshal(self):
|
||||
# Bad marshal data should raise a ValueError.
|
||||
self._test_bad_marshal()
|
||||
|
||||
# [bad timestamp]
|
||||
@util.writes_bytecode_files
|
||||
@without_source_date_epoch
|
||||
def test_old_timestamp(self):
|
||||
# When the timestamp is older than the source, bytecode should be
|
||||
# regenerated.
|
||||
zeros = b'\x00\x00\x00\x00'
|
||||
with util.create_modules('_temp') as mapping:
|
||||
py_compile.compile(mapping['_temp'])
|
||||
bytecode_path = self.util.cache_from_source(mapping['_temp'])
|
||||
with open(bytecode_path, 'r+b') as bytecode_file:
|
||||
bytecode_file.seek(8)
|
||||
bytecode_file.write(zeros)
|
||||
self.import_(mapping['_temp'], '_temp')
|
||||
source_mtime = os.path.getmtime(mapping['_temp'])
|
||||
source_timestamp = self.importlib._pack_uint32(source_mtime)
|
||||
with open(bytecode_path, 'rb') as bytecode_file:
|
||||
bytecode_file.seek(8)
|
||||
self.assertEqual(bytecode_file.read(4), source_timestamp)
|
||||
|
||||
# [bytecode read-only]
|
||||
@util.writes_bytecode_files
|
||||
def test_read_only_bytecode(self):
|
||||
# When bytecode is read-only but should be rewritten, fail silently.
|
||||
with util.create_modules('_temp') as mapping:
|
||||
# Create bytecode that will need to be re-created.
|
||||
py_compile.compile(mapping['_temp'])
|
||||
bytecode_path = self.util.cache_from_source(mapping['_temp'])
|
||||
with open(bytecode_path, 'r+b') as bytecode_file:
|
||||
bytecode_file.seek(0)
|
||||
bytecode_file.write(b'\x00\x00\x00\x00')
|
||||
# Make the bytecode read-only.
|
||||
os.chmod(bytecode_path,
|
||||
stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
|
||||
try:
|
||||
# Should not raise OSError!
|
||||
self.import_(mapping['_temp'], '_temp')
|
||||
finally:
|
||||
# Make writable for eventual clean-up.
|
||||
os.chmod(bytecode_path, stat.S_IWUSR)
|
||||
|
||||
|
||||
class SourceLoaderBadBytecodeTestPEP451(
|
||||
SourceLoaderBadBytecodeTest, BadBytecodeTestPEP451):
|
||||
pass
|
||||
|
||||
|
||||
(Frozen_SourceBadBytecodePEP451,
|
||||
Source_SourceBadBytecodePEP451
|
||||
) = util.test_both(SourceLoaderBadBytecodeTestPEP451, importlib=importlib,
|
||||
machinery=machinery, abc=importlib_abc,
|
||||
util=importlib_util)
|
||||
|
||||
|
||||
class SourceLoaderBadBytecodeTestPEP302(
|
||||
SourceLoaderBadBytecodeTest, BadBytecodeTestPEP302):
|
||||
pass
|
||||
|
||||
|
||||
(Frozen_SourceBadBytecodePEP302,
|
||||
Source_SourceBadBytecodePEP302
|
||||
) = util.test_both(SourceLoaderBadBytecodeTestPEP302, importlib=importlib,
|
||||
machinery=machinery, abc=importlib_abc,
|
||||
util=importlib_util)
|
||||
|
||||
|
||||
class SourcelessLoaderBadBytecodeTest:
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.loader = cls.machinery.SourcelessFileLoader
|
||||
|
||||
def test_empty_file(self):
|
||||
def test(name, mapping, bytecode_path):
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.import_(bytecode_path, name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
self.assertEqual(cm.exception.path, bytecode_path)
|
||||
|
||||
self._test_empty_file(test, del_source=True)
|
||||
|
||||
def test_partial_magic(self):
|
||||
def test(name, mapping, bytecode_path):
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.import_(bytecode_path, name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
self.assertEqual(cm.exception.path, bytecode_path)
|
||||
self._test_partial_magic(test, del_source=True)
|
||||
|
||||
def test_magic_only(self):
|
||||
def test(name, mapping, bytecode_path):
|
||||
with self.assertRaises(EOFError):
|
||||
self.import_(bytecode_path, name)
|
||||
|
||||
self._test_magic_only(test, del_source=True)
|
||||
|
||||
def test_bad_magic(self):
|
||||
def test(name, mapping, bytecode_path):
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.import_(bytecode_path, name)
|
||||
self.assertEqual(cm.exception.name, name)
|
||||
self.assertEqual(cm.exception.path, bytecode_path)
|
||||
|
||||
self._test_bad_magic(test, del_source=True)
|
||||
|
||||
def test_partial_timestamp(self):
|
||||
def test(name, mapping, bytecode_path):
|
||||
with self.assertRaises(EOFError):
|
||||
self.import_(bytecode_path, name)
|
||||
|
||||
self._test_partial_timestamp(test, del_source=True)
|
||||
|
||||
def test_partial_flags(self):
|
||||
def test(name, mapping, bytecode_path):
|
||||
with self.assertRaises(EOFError):
|
||||
self.import_(bytecode_path, name)
|
||||
|
||||
self._test_partial_flags(test, del_source=True)
|
||||
|
||||
def test_partial_hash(self):
|
||||
def test(name, mapping, bytecode_path):
|
||||
with self.assertRaises(EOFError):
|
||||
self.import_(bytecode_path, name)
|
||||
|
||||
self._test_partial_hash(test, del_source=True)
|
||||
|
||||
def test_partial_size(self):
|
||||
def test(name, mapping, bytecode_path):
|
||||
with self.assertRaises(EOFError):
|
||||
self.import_(bytecode_path, name)
|
||||
|
||||
self._test_partial_size(test, del_source=True)
|
||||
|
||||
def test_no_marshal(self):
|
||||
self._test_no_marshal(del_source=True)
|
||||
|
||||
def test_non_code_marshal(self):
|
||||
self._test_non_code_marshal(del_source=True)
|
||||
|
||||
|
||||
class SourcelessLoaderBadBytecodeTestPEP451(SourcelessLoaderBadBytecodeTest,
|
||||
BadBytecodeTestPEP451):
|
||||
pass
|
||||
|
||||
|
||||
(Frozen_SourcelessBadBytecodePEP451,
|
||||
Source_SourcelessBadBytecodePEP451
|
||||
) = util.test_both(SourcelessLoaderBadBytecodeTestPEP451, importlib=importlib,
|
||||
machinery=machinery, abc=importlib_abc,
|
||||
util=importlib_util)
|
||||
|
||||
|
||||
class SourcelessLoaderBadBytecodeTestPEP302(SourcelessLoaderBadBytecodeTest,
|
||||
BadBytecodeTestPEP302):
|
||||
pass
|
||||
|
||||
|
||||
(Frozen_SourcelessBadBytecodePEP302,
|
||||
Source_SourcelessBadBytecodePEP302
|
||||
) = util.test_both(SourcelessLoaderBadBytecodeTestPEP302, importlib=importlib,
|
||||
machinery=machinery, abc=importlib_abc,
|
||||
util=importlib_util)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
212
Dependencies/Python/Lib/test/test_importlib/source/test_finder.py
vendored
Normal file
212
Dependencies/Python/Lib/test/test_importlib/source/test_finder.py
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
from test.test_importlib import abc, util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import errno
|
||||
import os
|
||||
import py_compile
|
||||
import stat
|
||||
import sys
|
||||
import tempfile
|
||||
from test.support.import_helper import make_legacy_pyc
|
||||
import unittest
|
||||
|
||||
|
||||
class FinderTests(abc.FinderTests):
|
||||
|
||||
"""For a top-level module, it should just be found directly in the
|
||||
directory being searched. This is true for a directory with source
|
||||
[top-level source], bytecode [top-level bc], or both [top-level both].
|
||||
There is also the possibility that it is a package [top-level package], in
|
||||
which case there will be a directory with the module name and an
|
||||
__init__.py file. If there is a directory without an __init__.py an
|
||||
ImportWarning is returned [empty dir].
|
||||
|
||||
For sub-modules and sub-packages, the same happens as above but only use
|
||||
the tail end of the name [sub module] [sub package] [sub empty].
|
||||
|
||||
When there is a conflict between a package and module having the same name
|
||||
in the same directory, the package wins out [package over module]. This is
|
||||
so that imports of modules within the package can occur rather than trigger
|
||||
an import error.
|
||||
|
||||
When there is a package and module with the same name, always pick the
|
||||
package over the module [package over module]. This is so that imports from
|
||||
the package have the possibility of succeeding.
|
||||
|
||||
"""
|
||||
|
||||
def get_finder(self, root):
|
||||
loader_details = [(self.machinery.SourceFileLoader,
|
||||
self.machinery.SOURCE_SUFFIXES),
|
||||
(self.machinery.SourcelessFileLoader,
|
||||
self.machinery.BYTECODE_SUFFIXES)]
|
||||
return self.machinery.FileFinder(root, *loader_details)
|
||||
|
||||
def import_(self, root, module):
|
||||
finder = self.get_finder(root)
|
||||
return self._find(finder, module, loader_only=True)
|
||||
|
||||
def run_test(self, test, create=None, *, compile_=None, unlink=None):
|
||||
"""Test the finding of 'test' with the creation of modules listed in
|
||||
'create'.
|
||||
|
||||
Any names listed in 'compile_' are byte-compiled. Modules
|
||||
listed in 'unlink' have their source files deleted.
|
||||
|
||||
"""
|
||||
if create is None:
|
||||
create = {test}
|
||||
with util.create_modules(*create) as mapping:
|
||||
if compile_:
|
||||
for name in compile_:
|
||||
py_compile.compile(mapping[name])
|
||||
if unlink:
|
||||
for name in unlink:
|
||||
os.unlink(mapping[name])
|
||||
try:
|
||||
make_legacy_pyc(mapping[name])
|
||||
except OSError as error:
|
||||
# Some tests do not set compile_=True so the source
|
||||
# module will not get compiled and there will be no
|
||||
# PEP 3147 pyc file to rename.
|
||||
if error.errno != errno.ENOENT:
|
||||
raise
|
||||
loader = self.import_(mapping['.root'], test)
|
||||
self.assertHasAttr(loader, 'load_module')
|
||||
return loader
|
||||
|
||||
def test_module(self):
|
||||
# [top-level source]
|
||||
self.run_test('top_level')
|
||||
# [top-level bc]
|
||||
self.run_test('top_level', compile_={'top_level'},
|
||||
unlink={'top_level'})
|
||||
# [top-level both]
|
||||
self.run_test('top_level', compile_={'top_level'})
|
||||
|
||||
# [top-level package]
|
||||
def test_package(self):
|
||||
# Source.
|
||||
self.run_test('pkg', {'pkg.__init__'})
|
||||
# Bytecode.
|
||||
self.run_test('pkg', {'pkg.__init__'}, compile_={'pkg.__init__'},
|
||||
unlink={'pkg.__init__'})
|
||||
# Both.
|
||||
self.run_test('pkg', {'pkg.__init__'}, compile_={'pkg.__init__'})
|
||||
|
||||
# [sub module]
|
||||
def test_module_in_package(self):
|
||||
with util.create_modules('pkg.__init__', 'pkg.sub') as mapping:
|
||||
pkg_dir = os.path.dirname(mapping['pkg.__init__'])
|
||||
loader = self.import_(pkg_dir, 'pkg.sub')
|
||||
self.assertHasAttr(loader, 'load_module')
|
||||
|
||||
# [sub package]
|
||||
def test_package_in_package(self):
|
||||
context = util.create_modules('pkg.__init__', 'pkg.sub.__init__')
|
||||
with context as mapping:
|
||||
pkg_dir = os.path.dirname(mapping['pkg.__init__'])
|
||||
loader = self.import_(pkg_dir, 'pkg.sub')
|
||||
self.assertHasAttr(loader, 'load_module')
|
||||
|
||||
# [package over modules]
|
||||
def test_package_over_module(self):
|
||||
name = '_temp'
|
||||
loader = self.run_test(name, {'{0}.__init__'.format(name), name})
|
||||
self.assertIn('__init__', loader.get_filename(name))
|
||||
|
||||
def test_failure(self):
|
||||
with util.create_modules('blah') as mapping:
|
||||
nothing = self.import_(mapping['.root'], 'sdfsadsadf')
|
||||
self.assertEqual(nothing, self.NOT_FOUND)
|
||||
|
||||
def test_empty_string_for_dir(self):
|
||||
# The empty string from sys.path means to search in the cwd.
|
||||
finder = self.machinery.FileFinder('', (self.machinery.SourceFileLoader,
|
||||
self.machinery.SOURCE_SUFFIXES))
|
||||
with open('mod.py', 'w', encoding='utf-8') as file:
|
||||
file.write("# test file for importlib")
|
||||
try:
|
||||
loader = self._find(finder, 'mod', loader_only=True)
|
||||
self.assertHasAttr(loader, 'load_module')
|
||||
finally:
|
||||
os.unlink('mod.py')
|
||||
|
||||
def test_invalidate_caches(self):
|
||||
# invalidate_caches() should reset the mtime.
|
||||
finder = self.machinery.FileFinder('', (self.machinery.SourceFileLoader,
|
||||
self.machinery.SOURCE_SUFFIXES))
|
||||
finder._path_mtime = 42
|
||||
finder.invalidate_caches()
|
||||
self.assertEqual(finder._path_mtime, -1)
|
||||
|
||||
# Regression test for http://bugs.python.org/issue14846
|
||||
def test_dir_removal_handling(self):
|
||||
mod = 'mod'
|
||||
with util.create_modules(mod) as mapping:
|
||||
finder = self.get_finder(mapping['.root'])
|
||||
found = self._find(finder, 'mod', loader_only=True)
|
||||
self.assertIsNotNone(found)
|
||||
found = self._find(finder, 'mod', loader_only=True)
|
||||
self.assertEqual(found, self.NOT_FOUND)
|
||||
|
||||
@unittest.skipUnless(sys.platform != 'win32',
|
||||
'os.chmod() does not support the needed arguments under Windows')
|
||||
def test_no_read_directory(self):
|
||||
# Issue #16730
|
||||
tempdir = tempfile.TemporaryDirectory()
|
||||
self.enterContext(tempdir)
|
||||
# Since we muck with the permissions, we want to set them back to
|
||||
# their original values to make sure the directory can be properly
|
||||
# cleaned up.
|
||||
original_mode = os.stat(tempdir.name).st_mode
|
||||
self.addCleanup(os.chmod, tempdir.name, original_mode)
|
||||
os.chmod(tempdir.name, stat.S_IWUSR | stat.S_IXUSR)
|
||||
finder = self.get_finder(tempdir.name)
|
||||
found = self._find(finder, 'doesnotexist')
|
||||
self.assertEqual(found, self.NOT_FOUND)
|
||||
|
||||
def test_ignore_file(self):
|
||||
# If a directory got changed to a file from underneath us, then don't
|
||||
# worry about looking for submodules.
|
||||
with tempfile.NamedTemporaryFile() as file_obj:
|
||||
finder = self.get_finder(file_obj.name)
|
||||
found = self._find(finder, 'doesnotexist')
|
||||
self.assertEqual(found, self.NOT_FOUND)
|
||||
|
||||
|
||||
class FinderTestsPEP451(FinderTests):
|
||||
|
||||
NOT_FOUND = None
|
||||
|
||||
def _find(self, finder, name, loader_only=False):
|
||||
spec = finder.find_spec(name)
|
||||
return spec.loader if spec is not None else spec
|
||||
|
||||
|
||||
(Frozen_FinderTestsPEP451,
|
||||
Source_FinderTestsPEP451
|
||||
) = util.test_both(FinderTestsPEP451, machinery=machinery)
|
||||
|
||||
|
||||
class FinderTestsPEP420(FinderTests):
|
||||
|
||||
NOT_FOUND = (None, [])
|
||||
|
||||
def _find(self, finder, name, loader_only=False):
|
||||
spec = finder.find_spec(name)
|
||||
if spec is None:
|
||||
return self.NOT_FOUND
|
||||
if loader_only:
|
||||
return spec.loader
|
||||
return spec.loader, spec.submodule_search_locations
|
||||
|
||||
|
||||
(Frozen_FinderTestsPEP420,
|
||||
Source_FinderTestsPEP420
|
||||
) = util.test_both(FinderTestsPEP420, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
32
Dependencies/Python/Lib/test/test_importlib/source/test_path_hook.py
vendored
Normal file
32
Dependencies/Python/Lib/test/test_importlib/source/test_path_hook.py
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
from test.test_importlib import util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class PathHookTest:
|
||||
|
||||
"""Test the path hook for source."""
|
||||
|
||||
def path_hook(self):
|
||||
return self.machinery.FileFinder.path_hook((self.machinery.SourceFileLoader,
|
||||
self.machinery.SOURCE_SUFFIXES))
|
||||
|
||||
def test_success(self):
|
||||
with util.create_modules('dummy') as mapping:
|
||||
self.assertHasAttr(self.path_hook()(mapping['.root']),
|
||||
'find_spec')
|
||||
|
||||
def test_empty_string(self):
|
||||
# The empty string represents the cwd.
|
||||
self.assertHasAttr(self.path_hook()(''), 'find_spec')
|
||||
|
||||
|
||||
(Frozen_PathHookTest,
|
||||
Source_PathHooktest
|
||||
) = util.test_both(PathHookTest, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
175
Dependencies/Python/Lib/test/test_importlib/source/test_source_encoding.py
vendored
Normal file
175
Dependencies/Python/Lib/test/test_importlib/source/test_source_encoding.py
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
from test.test_importlib import util
|
||||
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
|
||||
import codecs
|
||||
import importlib.util
|
||||
import re
|
||||
import types
|
||||
# Because sys.path gets essentially blanked, need to have unicodedata already
|
||||
# imported for the parser to use.
|
||||
import unicodedata
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
|
||||
CODING_RE = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII)
|
||||
|
||||
|
||||
class EncodingTest:
|
||||
|
||||
"""PEP 3120 makes UTF-8 the default encoding for source code
|
||||
[default encoding].
|
||||
|
||||
PEP 263 specifies how that can change on a per-file basis. Either the first
|
||||
or second line can contain the encoding line [encoding first line]
|
||||
[encoding second line]. If the file has the BOM marker it is considered UTF-8
|
||||
implicitly [BOM]. If any encoding is specified it must be UTF-8, else it is
|
||||
an error [BOM and utf-8][BOM conflict].
|
||||
|
||||
"""
|
||||
|
||||
variable = '\u00fc'
|
||||
character = '\u00c9'
|
||||
source_line = "{0} = '{1}'\n".format(variable, character)
|
||||
module_name = '_temp'
|
||||
|
||||
def run_test(self, source):
|
||||
with util.create_modules(self.module_name) as mapping:
|
||||
with open(mapping[self.module_name], 'wb') as file:
|
||||
file.write(source)
|
||||
loader = self.machinery.SourceFileLoader(self.module_name,
|
||||
mapping[self.module_name])
|
||||
return self.load(loader)
|
||||
|
||||
def create_source(self, encoding):
|
||||
encoding_line = "# coding={0}".format(encoding)
|
||||
assert CODING_RE.match(encoding_line)
|
||||
source_lines = [encoding_line.encode('utf-8')]
|
||||
source_lines.append(self.source_line.encode(encoding))
|
||||
return b'\n'.join(source_lines)
|
||||
|
||||
def test_non_obvious_encoding(self):
|
||||
# Make sure that an encoding that has never been a standard one for
|
||||
# Python works.
|
||||
encoding_line = "# coding=koi8-r"
|
||||
assert CODING_RE.match(encoding_line)
|
||||
source = "{0}\na=42\n".format(encoding_line).encode("koi8-r")
|
||||
self.run_test(source)
|
||||
|
||||
# [default encoding]
|
||||
def test_default_encoding(self):
|
||||
self.run_test(self.source_line.encode('utf-8'))
|
||||
|
||||
# [encoding first line]
|
||||
def test_encoding_on_first_line(self):
|
||||
encoding = 'Latin-1'
|
||||
source = self.create_source(encoding)
|
||||
self.run_test(source)
|
||||
|
||||
# [encoding second line]
|
||||
def test_encoding_on_second_line(self):
|
||||
source = b"#/usr/bin/python\n" + self.create_source('Latin-1')
|
||||
self.run_test(source)
|
||||
|
||||
# [BOM]
|
||||
def test_bom(self):
|
||||
self.run_test(codecs.BOM_UTF8 + self.source_line.encode('utf-8'))
|
||||
|
||||
# [BOM and utf-8]
|
||||
def test_bom_and_utf_8(self):
|
||||
source = codecs.BOM_UTF8 + self.create_source('utf-8')
|
||||
self.run_test(source)
|
||||
|
||||
# [BOM conflict]
|
||||
def test_bom_conflict(self):
|
||||
source = codecs.BOM_UTF8 + self.create_source('latin-1')
|
||||
with self.assertRaises(SyntaxError):
|
||||
self.run_test(source)
|
||||
|
||||
|
||||
class EncodingTestPEP451(EncodingTest):
|
||||
|
||||
def load(self, loader):
|
||||
module = types.ModuleType(self.module_name)
|
||||
module.__spec__ = importlib.util.spec_from_loader(self.module_name, loader)
|
||||
loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
(Frozen_EncodingTestPEP451,
|
||||
Source_EncodingTestPEP451
|
||||
) = util.test_both(EncodingTestPEP451, machinery=machinery)
|
||||
|
||||
|
||||
class EncodingTestPEP302(EncodingTest):
|
||||
|
||||
def load(self, loader):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
return loader.load_module(self.module_name)
|
||||
|
||||
|
||||
(Frozen_EncodingTestPEP302,
|
||||
Source_EncodingTestPEP302
|
||||
) = util.test_both(EncodingTestPEP302, machinery=machinery)
|
||||
|
||||
|
||||
class LineEndingTest:
|
||||
|
||||
r"""Source written with the three types of line endings (\n, \r\n, \r)
|
||||
need to be readable [cr][crlf][lf]."""
|
||||
|
||||
def run_test(self, line_ending):
|
||||
module_name = '_temp'
|
||||
source_lines = [b"a = 42", b"b = -13", b'']
|
||||
source = line_ending.join(source_lines)
|
||||
with util.create_modules(module_name) as mapping:
|
||||
with open(mapping[module_name], 'wb') as file:
|
||||
file.write(source)
|
||||
loader = self.machinery.SourceFileLoader(module_name,
|
||||
mapping[module_name])
|
||||
return self.load(loader, module_name)
|
||||
|
||||
# [cr]
|
||||
def test_cr(self):
|
||||
self.run_test(b'\r')
|
||||
|
||||
# [crlf]
|
||||
def test_crlf(self):
|
||||
self.run_test(b'\r\n')
|
||||
|
||||
# [lf]
|
||||
def test_lf(self):
|
||||
self.run_test(b'\n')
|
||||
|
||||
|
||||
class LineEndingTestPEP451(LineEndingTest):
|
||||
|
||||
def load(self, loader, module_name):
|
||||
module = types.ModuleType(module_name)
|
||||
module.__spec__ = importlib.util.spec_from_loader(module_name, loader)
|
||||
loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
(Frozen_LineEndingTestPEP451,
|
||||
Source_LineEndingTestPEP451
|
||||
) = util.test_both(LineEndingTestPEP451, machinery=machinery)
|
||||
|
||||
|
||||
class LineEndingTestPEP302(LineEndingTest):
|
||||
|
||||
def load(self, loader, module_name):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
return loader.load_module(module_name)
|
||||
|
||||
|
||||
(Frozen_LineEndingTestPEP302,
|
||||
Source_LineEndingTestPEP302
|
||||
) = util.test_both(LineEndingTestPEP302, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
940
Dependencies/Python/Lib/test/test_importlib/test_abc.py
vendored
Normal file
940
Dependencies/Python/Lib/test/test_importlib/test_abc.py
vendored
Normal file
@@ -0,0 +1,940 @@
|
||||
import io
|
||||
import marshal
|
||||
import os
|
||||
import sys
|
||||
from test.support import import_helper
|
||||
import types
|
||||
import unittest
|
||||
from unittest import mock
|
||||
import warnings
|
||||
|
||||
from test.test_importlib import util as test_util
|
||||
|
||||
init = test_util.import_importlib('importlib')
|
||||
abc = test_util.import_importlib('importlib.abc')
|
||||
machinery = test_util.import_importlib('importlib.machinery')
|
||||
util = test_util.import_importlib('importlib.util')
|
||||
|
||||
|
||||
##### Inheritance ##############################################################
|
||||
class InheritanceTests:
|
||||
|
||||
"""Test that the specified class is a subclass/superclass of the expected
|
||||
classes."""
|
||||
|
||||
subclasses = []
|
||||
superclasses = []
|
||||
|
||||
def setUp(self):
|
||||
self.superclasses = [getattr(self.abc, class_name)
|
||||
for class_name in self.superclass_names]
|
||||
if hasattr(self, 'subclass_names'):
|
||||
# Because test.support.import_fresh_module() creates a new
|
||||
# importlib._bootstrap per module, inheritance checks fail when
|
||||
# checking across module boundaries (i.e. the _bootstrap in abc is
|
||||
# not the same as the one in machinery). That means stealing one of
|
||||
# the modules from the other to make sure the same instance is used.
|
||||
machinery = self.abc.machinery
|
||||
self.subclasses = [getattr(machinery, class_name)
|
||||
for class_name in self.subclass_names]
|
||||
assert self.subclasses or self.superclasses, self.__class__
|
||||
self.__test = getattr(self.abc, self._NAME)
|
||||
|
||||
def test_subclasses(self):
|
||||
# Test that the expected subclasses inherit.
|
||||
for subclass in self.subclasses:
|
||||
self.assertIsSubclass(subclass, self.__test)
|
||||
|
||||
def test_superclasses(self):
|
||||
# Test that the class inherits from the expected superclasses.
|
||||
for superclass in self.superclasses:
|
||||
self.assertIsSubclass(self.__test, superclass)
|
||||
|
||||
|
||||
class MetaPathFinder(InheritanceTests):
|
||||
superclass_names = []
|
||||
subclass_names = ['BuiltinImporter', 'FrozenImporter', 'PathFinder',
|
||||
'WindowsRegistryFinder']
|
||||
|
||||
|
||||
(Frozen_MetaPathFinderInheritanceTests,
|
||||
Source_MetaPathFinderInheritanceTests
|
||||
) = test_util.test_both(MetaPathFinder, abc=abc)
|
||||
|
||||
|
||||
class PathEntryFinder(InheritanceTests):
|
||||
superclass_names = []
|
||||
subclass_names = ['FileFinder']
|
||||
|
||||
|
||||
(Frozen_PathEntryFinderInheritanceTests,
|
||||
Source_PathEntryFinderInheritanceTests
|
||||
) = test_util.test_both(PathEntryFinder, abc=abc)
|
||||
|
||||
|
||||
class ResourceLoader(InheritanceTests):
|
||||
superclass_names = ['Loader']
|
||||
|
||||
|
||||
(Frozen_ResourceLoaderInheritanceTests,
|
||||
Source_ResourceLoaderInheritanceTests
|
||||
) = test_util.test_both(ResourceLoader, abc=abc)
|
||||
|
||||
|
||||
class InspectLoader(InheritanceTests):
|
||||
superclass_names = ['Loader']
|
||||
subclass_names = ['BuiltinImporter', 'FrozenImporter', 'ExtensionFileLoader']
|
||||
|
||||
|
||||
(Frozen_InspectLoaderInheritanceTests,
|
||||
Source_InspectLoaderInheritanceTests
|
||||
) = test_util.test_both(InspectLoader, abc=abc)
|
||||
|
||||
|
||||
class ExecutionLoader(InheritanceTests):
|
||||
superclass_names = ['InspectLoader']
|
||||
subclass_names = ['ExtensionFileLoader']
|
||||
|
||||
|
||||
(Frozen_ExecutionLoaderInheritanceTests,
|
||||
Source_ExecutionLoaderInheritanceTests
|
||||
) = test_util.test_both(ExecutionLoader, abc=abc)
|
||||
|
||||
|
||||
class FileLoader(InheritanceTests):
|
||||
superclass_names = ['ResourceLoader', 'ExecutionLoader']
|
||||
subclass_names = ['SourceFileLoader', 'SourcelessFileLoader']
|
||||
|
||||
|
||||
(Frozen_FileLoaderInheritanceTests,
|
||||
Source_FileLoaderInheritanceTests
|
||||
) = test_util.test_both(FileLoader, abc=abc)
|
||||
|
||||
|
||||
class SourceLoader(InheritanceTests):
|
||||
superclass_names = ['ResourceLoader', 'ExecutionLoader']
|
||||
subclass_names = ['SourceFileLoader']
|
||||
|
||||
|
||||
(Frozen_SourceLoaderInheritanceTests,
|
||||
Source_SourceLoaderInheritanceTests
|
||||
) = test_util.test_both(SourceLoader, abc=abc)
|
||||
|
||||
|
||||
##### Default return values ####################################################
|
||||
|
||||
def make_abc_subclasses(base_class, name=None, inst=False, **kwargs):
|
||||
if name is None:
|
||||
name = base_class.__name__
|
||||
base = {kind: getattr(splitabc, name)
|
||||
for kind, splitabc in abc.items()}
|
||||
return {cls._KIND: cls() if inst else cls
|
||||
for cls in test_util.split_frozen(base_class, base, **kwargs)}
|
||||
|
||||
|
||||
class ABCTestHarness:
|
||||
|
||||
@property
|
||||
def ins(self):
|
||||
# Lazily set ins on the class.
|
||||
cls = self.SPLIT[self._KIND]
|
||||
ins = cls()
|
||||
self.__class__.ins = ins
|
||||
return ins
|
||||
|
||||
|
||||
class MetaPathFinder:
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class MetaPathFinderDefaultsTests(ABCTestHarness):
|
||||
|
||||
SPLIT = make_abc_subclasses(MetaPathFinder)
|
||||
|
||||
def test_invalidate_caches(self):
|
||||
# Calling the method is a no-op.
|
||||
self.ins.invalidate_caches()
|
||||
|
||||
|
||||
(Frozen_MPFDefaultTests,
|
||||
Source_MPFDefaultTests
|
||||
) = test_util.test_both(MetaPathFinderDefaultsTests)
|
||||
|
||||
|
||||
class PathEntryFinder:
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class PathEntryFinderDefaultsTests(ABCTestHarness):
|
||||
|
||||
SPLIT = make_abc_subclasses(PathEntryFinder)
|
||||
|
||||
def test_invalidate_caches(self):
|
||||
# Should be a no-op.
|
||||
self.ins.invalidate_caches()
|
||||
|
||||
|
||||
(Frozen_PEFDefaultTests,
|
||||
Source_PEFDefaultTests
|
||||
) = test_util.test_both(PathEntryFinderDefaultsTests)
|
||||
|
||||
|
||||
class Loader:
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class LoaderDefaultsTests(ABCTestHarness):
|
||||
|
||||
SPLIT = make_abc_subclasses(Loader)
|
||||
|
||||
def test_create_module(self):
|
||||
spec = 'a spec'
|
||||
self.assertIsNone(self.ins.create_module(spec))
|
||||
|
||||
def test_load_module(self):
|
||||
with self.assertRaises(ImportError):
|
||||
self.ins.load_module('something')
|
||||
|
||||
def test_module_repr(self):
|
||||
mod = types.ModuleType('blah')
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
original_repr = repr(mod)
|
||||
mod.__loader__ = self.ins
|
||||
# Should still return a proper repr.
|
||||
self.assertTrue(repr(mod))
|
||||
|
||||
|
||||
(Frozen_LDefaultTests,
|
||||
SourceLDefaultTests
|
||||
) = test_util.test_both(LoaderDefaultsTests)
|
||||
|
||||
|
||||
class ResourceLoader(Loader):
|
||||
|
||||
def get_data(self, path):
|
||||
return super().get_data(path)
|
||||
|
||||
|
||||
class ResourceLoaderDefaultsTests(ABCTestHarness):
|
||||
|
||||
SPLIT = make_abc_subclasses(ResourceLoader)
|
||||
|
||||
def test_get_data(self):
|
||||
with self.assertRaises(IOError):
|
||||
self.ins.get_data('/some/path')
|
||||
|
||||
|
||||
(Frozen_RLDefaultTests,
|
||||
Source_RLDefaultTests
|
||||
) = test_util.test_both(ResourceLoaderDefaultsTests)
|
||||
|
||||
|
||||
class InspectLoader(Loader):
|
||||
|
||||
def is_package(self, fullname):
|
||||
return super().is_package(fullname)
|
||||
|
||||
def get_source(self, fullname):
|
||||
return super().get_source(fullname)
|
||||
|
||||
|
||||
SPLIT_IL = make_abc_subclasses(InspectLoader)
|
||||
|
||||
|
||||
class InspectLoaderDefaultsTests(ABCTestHarness):
|
||||
|
||||
SPLIT = SPLIT_IL
|
||||
|
||||
def test_is_package(self):
|
||||
with self.assertRaises(ImportError):
|
||||
self.ins.is_package('blah')
|
||||
|
||||
def test_get_source(self):
|
||||
with self.assertRaises(ImportError):
|
||||
self.ins.get_source('blah')
|
||||
|
||||
|
||||
(Frozen_ILDefaultTests,
|
||||
Source_ILDefaultTests
|
||||
) = test_util.test_both(InspectLoaderDefaultsTests)
|
||||
|
||||
|
||||
class ExecutionLoader(InspectLoader):
|
||||
|
||||
def get_filename(self, fullname):
|
||||
return super().get_filename(fullname)
|
||||
|
||||
|
||||
SPLIT_EL = make_abc_subclasses(ExecutionLoader)
|
||||
|
||||
|
||||
class ExecutionLoaderDefaultsTests(ABCTestHarness):
|
||||
|
||||
SPLIT = SPLIT_EL
|
||||
|
||||
def test_get_filename(self):
|
||||
with self.assertRaises(ImportError):
|
||||
self.ins.get_filename('blah')
|
||||
|
||||
|
||||
(Frozen_ELDefaultTests,
|
||||
Source_ELDefaultsTests
|
||||
) = test_util.test_both(InspectLoaderDefaultsTests)
|
||||
|
||||
|
||||
class ResourceReader:
|
||||
|
||||
def open_resource(self, *args, **kwargs):
|
||||
return super().open_resource(*args, **kwargs)
|
||||
|
||||
def resource_path(self, *args, **kwargs):
|
||||
return super().resource_path(*args, **kwargs)
|
||||
|
||||
def is_resource(self, *args, **kwargs):
|
||||
return super().is_resource(*args, **kwargs)
|
||||
|
||||
def contents(self, *args, **kwargs):
|
||||
return super().contents(*args, **kwargs)
|
||||
|
||||
|
||||
##### MetaPathFinder concrete methods ##########################################
|
||||
class MetaPathFinderFindModuleTests:
|
||||
|
||||
@classmethod
|
||||
def finder(cls, spec):
|
||||
class MetaPathSpecFinder(cls.abc.MetaPathFinder):
|
||||
|
||||
def find_spec(self, fullname, path, target=None):
|
||||
self.called_for = fullname, path
|
||||
return spec
|
||||
|
||||
return MetaPathSpecFinder()
|
||||
|
||||
def test_find_spec_with_explicit_target(self):
|
||||
loader = object()
|
||||
spec = self.util.spec_from_loader('blah', loader)
|
||||
finder = self.finder(spec)
|
||||
found = finder.find_spec('blah', 'blah', None)
|
||||
self.assertEqual(found, spec)
|
||||
|
||||
def test_no_spec(self):
|
||||
finder = self.finder(None)
|
||||
path = ['a', 'b', 'c']
|
||||
name = 'blah'
|
||||
found = finder.find_spec(name, path, None)
|
||||
self.assertIsNone(found)
|
||||
self.assertEqual(name, finder.called_for[0])
|
||||
self.assertEqual(path, finder.called_for[1])
|
||||
|
||||
def test_spec(self):
|
||||
loader = object()
|
||||
spec = self.util.spec_from_loader('blah', loader)
|
||||
finder = self.finder(spec)
|
||||
found = finder.find_spec('blah', None)
|
||||
self.assertIs(found, spec)
|
||||
|
||||
|
||||
(Frozen_MPFFindModuleTests,
|
||||
Source_MPFFindModuleTests
|
||||
) = test_util.test_both(MetaPathFinderFindModuleTests, abc=abc, util=util)
|
||||
|
||||
|
||||
##### Loader concrete methods ##################################################
|
||||
class LoaderLoadModuleTests:
|
||||
|
||||
def loader(self):
|
||||
class SpecLoader(self.abc.Loader):
|
||||
found = None
|
||||
def exec_module(self, module):
|
||||
self.found = module
|
||||
|
||||
def is_package(self, fullname):
|
||||
"""Force some non-default module state to be set."""
|
||||
return True
|
||||
|
||||
return SpecLoader()
|
||||
|
||||
def test_fresh(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
loader = self.loader()
|
||||
name = 'blah'
|
||||
with test_util.uncache(name):
|
||||
loader.load_module(name)
|
||||
module = loader.found
|
||||
self.assertIs(sys.modules[name], module)
|
||||
self.assertEqual(loader, module.__loader__)
|
||||
self.assertEqual(loader, module.__spec__.loader)
|
||||
self.assertEqual(name, module.__name__)
|
||||
self.assertEqual(name, module.__spec__.name)
|
||||
self.assertIsNotNone(module.__path__)
|
||||
self.assertIsNotNone(module.__path__,
|
||||
module.__spec__.submodule_search_locations)
|
||||
|
||||
def test_reload(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
name = 'blah'
|
||||
loader = self.loader()
|
||||
module = types.ModuleType(name)
|
||||
module.__spec__ = self.util.spec_from_loader(name, loader)
|
||||
module.__loader__ = loader
|
||||
with test_util.uncache(name):
|
||||
sys.modules[name] = module
|
||||
loader.load_module(name)
|
||||
found = loader.found
|
||||
self.assertIs(found, sys.modules[name])
|
||||
self.assertIs(module, sys.modules[name])
|
||||
|
||||
|
||||
(Frozen_LoaderLoadModuleTests,
|
||||
Source_LoaderLoadModuleTests
|
||||
) = test_util.test_both(LoaderLoadModuleTests, abc=abc, util=util)
|
||||
|
||||
|
||||
##### InspectLoader concrete methods ###########################################
|
||||
class InspectLoaderSourceToCodeTests:
|
||||
|
||||
def source_to_module(self, data, path=None):
|
||||
"""Help with source_to_code() tests."""
|
||||
module = types.ModuleType('blah')
|
||||
loader = self.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.assertHasAttr(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.assertHasAttr(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 = self.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 = self.InspectLoaderSubclass()
|
||||
code = loader.source_to_code('')
|
||||
self.assertEqual(code.co_filename, '<string>')
|
||||
|
||||
|
||||
(Frozen_ILSourceToCodeTests,
|
||||
Source_ILSourceToCodeTests
|
||||
) = test_util.test_both(InspectLoaderSourceToCodeTests,
|
||||
InspectLoaderSubclass=SPLIT_IL)
|
||||
|
||||
|
||||
class InspectLoaderGetCodeTests:
|
||||
|
||||
def test_get_code(self):
|
||||
# Test success.
|
||||
module = types.ModuleType('blah')
|
||||
with mock.patch.object(self.InspectLoaderSubclass, 'get_source') as mocked:
|
||||
mocked.return_value = 'attr = 42'
|
||||
loader = self.InspectLoaderSubclass()
|
||||
code = loader.get_code('blah')
|
||||
exec(code, module.__dict__)
|
||||
self.assertEqual(module.attr, 42)
|
||||
|
||||
def test_get_code_source_is_None(self):
|
||||
# If get_source() is None then this should be None.
|
||||
with mock.patch.object(self.InspectLoaderSubclass, 'get_source') as mocked:
|
||||
mocked.return_value = None
|
||||
loader = self.InspectLoaderSubclass()
|
||||
code = loader.get_code('blah')
|
||||
self.assertIsNone(code)
|
||||
|
||||
def test_get_code_source_not_found(self):
|
||||
# If there is no source then there is no code object.
|
||||
loader = self.InspectLoaderSubclass()
|
||||
with self.assertRaises(ImportError):
|
||||
loader.get_code('blah')
|
||||
|
||||
|
||||
(Frozen_ILGetCodeTests,
|
||||
Source_ILGetCodeTests
|
||||
) = test_util.test_both(InspectLoaderGetCodeTests,
|
||||
InspectLoaderSubclass=SPLIT_IL)
|
||||
|
||||
|
||||
class InspectLoaderLoadModuleTests:
|
||||
|
||||
"""Test InspectLoader.load_module()."""
|
||||
|
||||
module_name = 'blah'
|
||||
|
||||
def setUp(self):
|
||||
import_helper.unload(self.module_name)
|
||||
self.addCleanup(import_helper.unload, self.module_name)
|
||||
|
||||
def load(self, loader):
|
||||
spec = self.util.spec_from_loader(self.module_name, loader)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
return self.init._bootstrap._load_unlocked(spec)
|
||||
|
||||
def mock_get_code(self):
|
||||
return mock.patch.object(self.InspectLoaderSubclass, 'get_code')
|
||||
|
||||
def test_get_code_ImportError(self):
|
||||
# If get_code() raises ImportError, it should propagate.
|
||||
with self.mock_get_code() as mocked_get_code:
|
||||
mocked_get_code.side_effect = ImportError
|
||||
with self.assertRaises(ImportError):
|
||||
loader = self.InspectLoaderSubclass()
|
||||
self.load(loader)
|
||||
|
||||
def test_get_code_None(self):
|
||||
# If get_code() returns None, raise ImportError.
|
||||
with self.mock_get_code() as mocked_get_code:
|
||||
mocked_get_code.return_value = None
|
||||
with self.assertRaises(ImportError):
|
||||
loader = self.InspectLoaderSubclass()
|
||||
self.load(loader)
|
||||
|
||||
def test_module_returned(self):
|
||||
# The loaded module should be returned.
|
||||
code = compile('attr = 42', '<string>', 'exec')
|
||||
with self.mock_get_code() as mocked_get_code:
|
||||
mocked_get_code.return_value = code
|
||||
loader = self.InspectLoaderSubclass()
|
||||
module = self.load(loader)
|
||||
self.assertEqual(module, sys.modules[self.module_name])
|
||||
|
||||
|
||||
(Frozen_ILLoadModuleTests,
|
||||
Source_ILLoadModuleTests
|
||||
) = test_util.test_both(InspectLoaderLoadModuleTests,
|
||||
InspectLoaderSubclass=SPLIT_IL,
|
||||
init=init,
|
||||
util=util)
|
||||
|
||||
|
||||
##### ExecutionLoader concrete methods #########################################
|
||||
class ExecutionLoaderGetCodeTests:
|
||||
|
||||
def mock_methods(self, *, get_source=False, get_filename=False):
|
||||
source_mock_context, filename_mock_context = None, None
|
||||
if get_source:
|
||||
source_mock_context = mock.patch.object(self.ExecutionLoaderSubclass,
|
||||
'get_source')
|
||||
if get_filename:
|
||||
filename_mock_context = mock.patch.object(self.ExecutionLoaderSubclass,
|
||||
'get_filename')
|
||||
return source_mock_context, filename_mock_context
|
||||
|
||||
def test_get_code(self):
|
||||
path = 'blah.py'
|
||||
source_mock_context, filename_mock_context = self.mock_methods(
|
||||
get_source=True, get_filename=True)
|
||||
with source_mock_context as source_mock, filename_mock_context as name_mock:
|
||||
source_mock.return_value = 'attr = 42'
|
||||
name_mock.return_value = path
|
||||
loader = self.ExecutionLoaderSubclass()
|
||||
code = loader.get_code('blah')
|
||||
self.assertEqual(code.co_filename, path)
|
||||
module = types.ModuleType('blah')
|
||||
exec(code, module.__dict__)
|
||||
self.assertEqual(module.attr, 42)
|
||||
|
||||
def test_get_code_source_is_None(self):
|
||||
# If get_source() is None then this should be None.
|
||||
source_mock_context, _ = self.mock_methods(get_source=True)
|
||||
with source_mock_context as mocked:
|
||||
mocked.return_value = None
|
||||
loader = self.ExecutionLoaderSubclass()
|
||||
code = loader.get_code('blah')
|
||||
self.assertIsNone(code)
|
||||
|
||||
def test_get_code_source_not_found(self):
|
||||
# If there is no source then there is no code object.
|
||||
loader = self.ExecutionLoaderSubclass()
|
||||
with self.assertRaises(ImportError):
|
||||
loader.get_code('blah')
|
||||
|
||||
def test_get_code_no_path(self):
|
||||
# If get_filename() raises ImportError then simply skip setting the path
|
||||
# on the code object.
|
||||
source_mock_context, filename_mock_context = self.mock_methods(
|
||||
get_source=True, get_filename=True)
|
||||
with source_mock_context as source_mock, filename_mock_context as name_mock:
|
||||
source_mock.return_value = 'attr = 42'
|
||||
name_mock.side_effect = ImportError
|
||||
loader = self.ExecutionLoaderSubclass()
|
||||
code = loader.get_code('blah')
|
||||
self.assertEqual(code.co_filename, '<string>')
|
||||
module = types.ModuleType('blah')
|
||||
exec(code, module.__dict__)
|
||||
self.assertEqual(module.attr, 42)
|
||||
|
||||
|
||||
(Frozen_ELGetCodeTests,
|
||||
Source_ELGetCodeTests
|
||||
) = test_util.test_both(ExecutionLoaderGetCodeTests,
|
||||
ExecutionLoaderSubclass=SPLIT_EL)
|
||||
|
||||
|
||||
##### SourceLoader concrete methods ############################################
|
||||
class SourceOnlyLoader:
|
||||
|
||||
# Globals that should be defined for all modules.
|
||||
source = (b"_ = '::'.join([__name__, __file__, __cached__, __package__, "
|
||||
b"repr(__loader__)])")
|
||||
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
def get_data(self, path):
|
||||
if path != self.path:
|
||||
raise IOError
|
||||
return self.source
|
||||
|
||||
def get_filename(self, fullname):
|
||||
return self.path
|
||||
|
||||
|
||||
SPLIT_SOL = make_abc_subclasses(SourceOnlyLoader, 'SourceLoader')
|
||||
|
||||
|
||||
class SourceLoader(SourceOnlyLoader):
|
||||
|
||||
source_mtime = 1
|
||||
|
||||
def __init__(self, path, magic=None):
|
||||
super().__init__(path)
|
||||
self.bytecode_path = self.util.cache_from_source(self.path)
|
||||
self.source_size = len(self.source)
|
||||
if magic is None:
|
||||
magic = self.util.MAGIC_NUMBER
|
||||
data = bytearray(magic)
|
||||
data.extend(self.init._pack_uint32(0))
|
||||
data.extend(self.init._pack_uint32(self.source_mtime))
|
||||
data.extend(self.init._pack_uint32(self.source_size))
|
||||
code_object = compile(self.source, self.path, 'exec',
|
||||
dont_inherit=True)
|
||||
data.extend(marshal.dumps(code_object))
|
||||
self.bytecode = bytes(data)
|
||||
self.written = {}
|
||||
|
||||
def get_data(self, path):
|
||||
if path == self.path:
|
||||
return super().get_data(path)
|
||||
elif path == self.bytecode_path:
|
||||
return self.bytecode
|
||||
else:
|
||||
raise OSError
|
||||
|
||||
def path_stats(self, path):
|
||||
if path != self.path:
|
||||
raise IOError
|
||||
return {'mtime': self.source_mtime, 'size': self.source_size}
|
||||
|
||||
def set_data(self, path, data):
|
||||
self.written[path] = bytes(data)
|
||||
return path == self.bytecode_path
|
||||
|
||||
|
||||
SPLIT_SL = make_abc_subclasses(SourceLoader, util=util, init=init)
|
||||
|
||||
|
||||
class SourceLoaderTestHarness:
|
||||
|
||||
def setUp(self, *, is_package=True, **kwargs):
|
||||
self.package = 'pkg'
|
||||
if is_package:
|
||||
self.path = os.path.join(self.package, '__init__.py')
|
||||
self.name = self.package
|
||||
else:
|
||||
module_name = 'mod'
|
||||
self.path = os.path.join(self.package, '.'.join(['mod', 'py']))
|
||||
self.name = '.'.join([self.package, module_name])
|
||||
self.cached = self.util.cache_from_source(self.path)
|
||||
self.loader = self.loader_mock(self.path, **kwargs)
|
||||
|
||||
def verify_module(self, module):
|
||||
self.assertEqual(module.__name__, self.name)
|
||||
self.assertEqual(module.__file__, self.path)
|
||||
self.assertEqual(module.__cached__, self.cached)
|
||||
self.assertEqual(module.__package__, self.package)
|
||||
self.assertEqual(module.__loader__, self.loader)
|
||||
values = module._.split('::')
|
||||
self.assertEqual(values[0], self.name)
|
||||
self.assertEqual(values[1], self.path)
|
||||
self.assertEqual(values[2], self.cached)
|
||||
self.assertEqual(values[3], self.package)
|
||||
self.assertEqual(values[4], repr(self.loader))
|
||||
|
||||
def verify_code(self, code_object):
|
||||
module = types.ModuleType(self.name)
|
||||
module.__file__ = self.path
|
||||
module.__cached__ = self.cached
|
||||
module.__package__ = self.package
|
||||
module.__loader__ = self.loader
|
||||
module.__path__ = []
|
||||
exec(code_object, module.__dict__)
|
||||
self.verify_module(module)
|
||||
|
||||
|
||||
class SourceOnlyLoaderTests(SourceLoaderTestHarness):
|
||||
"""Test importlib.abc.SourceLoader for source-only loading."""
|
||||
|
||||
def test_get_source(self):
|
||||
# Verify the source code is returned as a string.
|
||||
# If an OSError is raised by get_data then raise ImportError.
|
||||
expected_source = self.loader.source.decode('utf-8')
|
||||
self.assertEqual(self.loader.get_source(self.name), expected_source)
|
||||
def raise_OSError(path):
|
||||
raise OSError
|
||||
self.loader.get_data = raise_OSError
|
||||
with self.assertRaises(ImportError) as cm:
|
||||
self.loader.get_source(self.name)
|
||||
self.assertEqual(cm.exception.name, self.name)
|
||||
|
||||
def test_is_package(self):
|
||||
# Properly detect when loading a package.
|
||||
self.setUp(is_package=False)
|
||||
self.assertFalse(self.loader.is_package(self.name))
|
||||
self.setUp(is_package=True)
|
||||
self.assertTrue(self.loader.is_package(self.name))
|
||||
self.assertFalse(self.loader.is_package(self.name + '.__init__'))
|
||||
|
||||
def test_get_code(self):
|
||||
# Verify the code object is created.
|
||||
code_object = self.loader.get_code(self.name)
|
||||
self.verify_code(code_object)
|
||||
|
||||
def test_source_to_code(self):
|
||||
# Verify the compiled code object.
|
||||
code = self.loader.source_to_code(self.loader.source, self.path)
|
||||
self.verify_code(code)
|
||||
|
||||
def test_load_module(self):
|
||||
# Loading a module should set __name__, __loader__, __package__,
|
||||
# __path__ (for packages), __file__, and __cached__.
|
||||
# The module should also be put into sys.modules.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
with test_util.uncache(self.name):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
module = self.loader.load_module(self.name)
|
||||
self.verify_module(module)
|
||||
self.assertEqual(module.__path__, [os.path.dirname(self.path)])
|
||||
self.assertIn(self.name, sys.modules)
|
||||
|
||||
def test_package_settings(self):
|
||||
# __package__ needs to be set, while __path__ is set on if the module
|
||||
# is a package.
|
||||
# Testing the values for a package are covered by test_load_module.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
self.setUp(is_package=False)
|
||||
with test_util.uncache(self.name):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', DeprecationWarning)
|
||||
module = self.loader.load_module(self.name)
|
||||
self.verify_module(module)
|
||||
self.assertNotHasAttr(module, '__path__')
|
||||
|
||||
def test_get_source_encoding(self):
|
||||
# Source is considered encoded in UTF-8 by default unless otherwise
|
||||
# specified by an encoding line.
|
||||
source = "_ = 'ü'"
|
||||
self.loader.source = source.encode('utf-8')
|
||||
returned_source = self.loader.get_source(self.name)
|
||||
self.assertEqual(returned_source, source)
|
||||
source = "# coding: latin-1\n_ = ü"
|
||||
self.loader.source = source.encode('latin-1')
|
||||
returned_source = self.loader.get_source(self.name)
|
||||
self.assertEqual(returned_source, source)
|
||||
|
||||
|
||||
(Frozen_SourceOnlyLoaderTests,
|
||||
Source_SourceOnlyLoaderTests
|
||||
) = test_util.test_both(SourceOnlyLoaderTests, util=util,
|
||||
loader_mock=SPLIT_SOL)
|
||||
|
||||
|
||||
@unittest.skipIf(sys.dont_write_bytecode, "sys.dont_write_bytecode is true")
|
||||
class SourceLoaderBytecodeTests(SourceLoaderTestHarness):
|
||||
|
||||
"""Test importlib.abc.SourceLoader's use of bytecode.
|
||||
|
||||
Source-only testing handled by SourceOnlyLoaderTests.
|
||||
|
||||
"""
|
||||
|
||||
def verify_code(self, code_object, *, bytecode_written=False):
|
||||
super().verify_code(code_object)
|
||||
if bytecode_written:
|
||||
self.assertIn(self.cached, self.loader.written)
|
||||
data = bytearray(self.util.MAGIC_NUMBER)
|
||||
data.extend(self.init._pack_uint32(0))
|
||||
data.extend(self.init._pack_uint32(self.loader.source_mtime))
|
||||
data.extend(self.init._pack_uint32(self.loader.source_size))
|
||||
data.extend(marshal.dumps(code_object))
|
||||
self.assertEqual(self.loader.written[self.cached], bytes(data))
|
||||
|
||||
def test_code_with_everything(self):
|
||||
# When everything should work.
|
||||
code_object = self.loader.get_code(self.name)
|
||||
self.verify_code(code_object)
|
||||
|
||||
def test_no_bytecode(self):
|
||||
# If no bytecode exists then move on to the source.
|
||||
self.loader.bytecode_path = "<does not exist>"
|
||||
# Sanity check
|
||||
with self.assertRaises(OSError):
|
||||
bytecode_path = self.util.cache_from_source(self.path)
|
||||
self.loader.get_data(bytecode_path)
|
||||
code_object = self.loader.get_code(self.name)
|
||||
self.verify_code(code_object, bytecode_written=True)
|
||||
|
||||
def test_code_bad_timestamp(self):
|
||||
# Bytecode is only used when the timestamp matches the source EXACTLY.
|
||||
for source_mtime in (0, 2):
|
||||
assert source_mtime != self.loader.source_mtime
|
||||
original = self.loader.source_mtime
|
||||
self.loader.source_mtime = source_mtime
|
||||
# If bytecode is used then EOFError would be raised by marshal.
|
||||
self.loader.bytecode = self.loader.bytecode[8:]
|
||||
code_object = self.loader.get_code(self.name)
|
||||
self.verify_code(code_object, bytecode_written=True)
|
||||
self.loader.source_mtime = original
|
||||
|
||||
def test_code_bad_magic(self):
|
||||
# Skip over bytecode with a bad magic number.
|
||||
self.setUp(magic=b'0000')
|
||||
# If bytecode is used then EOFError would be raised by marshal.
|
||||
self.loader.bytecode = self.loader.bytecode[8:]
|
||||
code_object = self.loader.get_code(self.name)
|
||||
self.verify_code(code_object, bytecode_written=True)
|
||||
|
||||
def test_dont_write_bytecode(self):
|
||||
# Bytecode is not written if sys.dont_write_bytecode is true.
|
||||
# Can assume it is false already thanks to the skipIf class decorator.
|
||||
try:
|
||||
sys.dont_write_bytecode = True
|
||||
self.loader.bytecode_path = "<does not exist>"
|
||||
code_object = self.loader.get_code(self.name)
|
||||
self.assertNotIn(self.cached, self.loader.written)
|
||||
finally:
|
||||
sys.dont_write_bytecode = False
|
||||
|
||||
def test_no_set_data(self):
|
||||
# If set_data is not defined, one can still read bytecode.
|
||||
self.setUp(magic=b'0000')
|
||||
original_set_data = self.loader.__class__.mro()[1].set_data
|
||||
try:
|
||||
del self.loader.__class__.mro()[1].set_data
|
||||
code_object = self.loader.get_code(self.name)
|
||||
self.verify_code(code_object)
|
||||
finally:
|
||||
self.loader.__class__.mro()[1].set_data = original_set_data
|
||||
|
||||
def test_set_data_raises_exceptions(self):
|
||||
# Raising NotImplementedError or OSError is okay for set_data.
|
||||
def raise_exception(exc):
|
||||
def closure(*args, **kwargs):
|
||||
raise exc
|
||||
return closure
|
||||
|
||||
self.setUp(magic=b'0000')
|
||||
self.loader.set_data = raise_exception(NotImplementedError)
|
||||
code_object = self.loader.get_code(self.name)
|
||||
self.verify_code(code_object)
|
||||
|
||||
|
||||
(Frozen_SLBytecodeTests,
|
||||
SourceSLBytecodeTests
|
||||
) = test_util.test_both(SourceLoaderBytecodeTests, init=init, util=util,
|
||||
loader_mock=SPLIT_SL)
|
||||
|
||||
|
||||
class SourceLoaderGetSourceTests:
|
||||
|
||||
"""Tests for importlib.abc.SourceLoader.get_source()."""
|
||||
|
||||
def test_default_encoding(self):
|
||||
# Should have no problems with UTF-8 text.
|
||||
name = 'mod'
|
||||
mock = self.SourceOnlyLoaderMock('mod.file')
|
||||
source = 'x = "ü"'
|
||||
mock.source = source.encode('utf-8')
|
||||
returned_source = mock.get_source(name)
|
||||
self.assertEqual(returned_source, source)
|
||||
|
||||
def test_decoded_source(self):
|
||||
# Decoding should work.
|
||||
name = 'mod'
|
||||
mock = self.SourceOnlyLoaderMock("mod.file")
|
||||
source = "# coding: Latin-1\nx='ü'"
|
||||
assert source.encode('latin-1') != source.encode('utf-8')
|
||||
mock.source = source.encode('latin-1')
|
||||
returned_source = mock.get_source(name)
|
||||
self.assertEqual(returned_source, source)
|
||||
|
||||
def test_universal_newlines(self):
|
||||
# PEP 302 says universal newlines should be used.
|
||||
name = 'mod'
|
||||
mock = self.SourceOnlyLoaderMock('mod.file')
|
||||
source = "x = 42\r\ny = -13\r\n"
|
||||
mock.source = source.encode('utf-8')
|
||||
expect = io.IncrementalNewlineDecoder(None, True).decode(source)
|
||||
self.assertEqual(mock.get_source(name), expect)
|
||||
|
||||
|
||||
(Frozen_SourceOnlyLoaderGetSourceTests,
|
||||
Source_SourceOnlyLoaderGetSourceTests
|
||||
) = test_util.test_both(SourceLoaderGetSourceTests,
|
||||
SourceOnlyLoaderMock=SPLIT_SOL)
|
||||
|
||||
|
||||
class DeprecatedAttrsTests:
|
||||
|
||||
"""Test the deprecated attributes can be accessed."""
|
||||
|
||||
def test_deprecated_attr_ResourceReader(self):
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.abc.ResourceReader
|
||||
del self.abc.ResourceReader
|
||||
|
||||
def test_deprecated_attr_Traversable(self):
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.abc.Traversable
|
||||
del self.abc.Traversable
|
||||
|
||||
def test_deprecated_attr_TraversableResources(self):
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.abc.TraversableResources
|
||||
del self.abc.TraversableResources
|
||||
|
||||
|
||||
(Frozen_DeprecatedAttrsTests,
|
||||
Source_DeprecatedAttrsTests
|
||||
) = test_util.test_both(DeprecatedAttrsTests, abc=abc)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
456
Dependencies/Python/Lib/test/test_importlib/test_api.py
vendored
Normal file
456
Dependencies/Python/Lib/test/test_importlib/test_api.py
vendored
Normal file
@@ -0,0 +1,456 @@
|
||||
from test.test_importlib import util as test_util
|
||||
|
||||
init = test_util.import_importlib('importlib')
|
||||
util = test_util.import_importlib('importlib.util')
|
||||
machinery = test_util.import_importlib('importlib.machinery')
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
from test.support import import_helper
|
||||
from test.support import os_helper
|
||||
from test import support
|
||||
import traceback
|
||||
import types
|
||||
import unittest
|
||||
|
||||
|
||||
class ImportModuleTests:
|
||||
|
||||
"""Test importlib.import_module."""
|
||||
|
||||
def test_module_import(self):
|
||||
# Test importing a top-level module.
|
||||
with test_util.mock_spec('top_level') as mock:
|
||||
with test_util.import_state(meta_path=[mock]):
|
||||
module = self.init.import_module('top_level')
|
||||
self.assertEqual(module.__name__, 'top_level')
|
||||
|
||||
def test_absolute_package_import(self):
|
||||
# Test importing a module from a package with an absolute name.
|
||||
pkg_name = 'pkg'
|
||||
pkg_long_name = '{0}.__init__'.format(pkg_name)
|
||||
name = '{0}.mod'.format(pkg_name)
|
||||
with test_util.mock_spec(pkg_long_name, name) as mock:
|
||||
with test_util.import_state(meta_path=[mock]):
|
||||
module = self.init.import_module(name)
|
||||
self.assertEqual(module.__name__, name)
|
||||
|
||||
def test_shallow_relative_package_import(self):
|
||||
# Test importing a module from a package through a relative import.
|
||||
pkg_name = 'pkg'
|
||||
pkg_long_name = '{0}.__init__'.format(pkg_name)
|
||||
module_name = 'mod'
|
||||
absolute_name = '{0}.{1}'.format(pkg_name, module_name)
|
||||
relative_name = '.{0}'.format(module_name)
|
||||
with test_util.mock_spec(pkg_long_name, absolute_name) as mock:
|
||||
with test_util.import_state(meta_path=[mock]):
|
||||
self.init.import_module(pkg_name)
|
||||
module = self.init.import_module(relative_name, pkg_name)
|
||||
self.assertEqual(module.__name__, absolute_name)
|
||||
|
||||
def test_deep_relative_package_import(self):
|
||||
modules = ['a.__init__', 'a.b.__init__', 'a.c']
|
||||
with test_util.mock_spec(*modules) as mock:
|
||||
with test_util.import_state(meta_path=[mock]):
|
||||
self.init.import_module('a')
|
||||
self.init.import_module('a.b')
|
||||
module = self.init.import_module('..c', 'a.b')
|
||||
self.assertEqual(module.__name__, 'a.c')
|
||||
|
||||
def test_absolute_import_with_package(self):
|
||||
# Test importing a module from a package with an absolute name with
|
||||
# the 'package' argument given.
|
||||
pkg_name = 'pkg'
|
||||
pkg_long_name = '{0}.__init__'.format(pkg_name)
|
||||
name = '{0}.mod'.format(pkg_name)
|
||||
with test_util.mock_spec(pkg_long_name, name) as mock:
|
||||
with test_util.import_state(meta_path=[mock]):
|
||||
self.init.import_module(pkg_name)
|
||||
module = self.init.import_module(name, pkg_name)
|
||||
self.assertEqual(module.__name__, name)
|
||||
|
||||
def test_relative_import_wo_package(self):
|
||||
# Relative imports cannot happen without the 'package' argument being
|
||||
# set.
|
||||
with self.assertRaises(TypeError):
|
||||
self.init.import_module('.support')
|
||||
|
||||
|
||||
def test_loaded_once(self):
|
||||
# Issue #13591: Modules should only be loaded once when
|
||||
# initializing the parent package attempts to import the
|
||||
# module currently being imported.
|
||||
b_load_count = 0
|
||||
def load_a():
|
||||
self.init.import_module('a.b')
|
||||
def load_b():
|
||||
nonlocal b_load_count
|
||||
b_load_count += 1
|
||||
code = {'a': load_a, 'a.b': load_b}
|
||||
modules = ['a.__init__', 'a.b']
|
||||
with test_util.mock_spec(*modules, module_code=code) as mock:
|
||||
with test_util.import_state(meta_path=[mock]):
|
||||
self.init.import_module('a.b')
|
||||
self.assertEqual(b_load_count, 1)
|
||||
|
||||
|
||||
(Frozen_ImportModuleTests,
|
||||
Source_ImportModuleTests
|
||||
) = test_util.test_both(
|
||||
ImportModuleTests, init=init, util=util, machinery=machinery)
|
||||
|
||||
|
||||
class FindLoaderTests:
|
||||
|
||||
FakeMetaFinder = None
|
||||
|
||||
def test_sys_modules(self):
|
||||
# If a module with __spec__.loader is in sys.modules, then return it.
|
||||
name = 'some_mod'
|
||||
with test_util.uncache(name):
|
||||
module = types.ModuleType(name)
|
||||
loader = 'a loader!'
|
||||
module.__spec__ = self.machinery.ModuleSpec(name, loader)
|
||||
sys.modules[name] = module
|
||||
spec = self.util.find_spec(name)
|
||||
self.assertIsNotNone(spec)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
|
||||
def test_sys_modules_loader_is_None(self):
|
||||
# If sys.modules[name].__spec__.loader is None, raise ValueError.
|
||||
name = 'some_mod'
|
||||
with test_util.uncache(name):
|
||||
module = types.ModuleType(name)
|
||||
module.__loader__ = None
|
||||
sys.modules[name] = module
|
||||
with self.assertRaises(ValueError):
|
||||
self.util.find_spec(name)
|
||||
|
||||
def test_sys_modules_loader_is_not_set(self):
|
||||
# Should raise ValueError
|
||||
# Issue #17099
|
||||
name = 'some_mod'
|
||||
with test_util.uncache(name):
|
||||
module = types.ModuleType(name)
|
||||
try:
|
||||
del module.__spec__.loader
|
||||
except AttributeError:
|
||||
pass
|
||||
sys.modules[name] = module
|
||||
with self.assertRaises(ValueError):
|
||||
self.util.find_spec(name)
|
||||
|
||||
def test_success(self):
|
||||
# Return the loader found on sys.meta_path.
|
||||
name = 'some_mod'
|
||||
with test_util.uncache(name):
|
||||
with test_util.import_state(meta_path=[self.FakeMetaFinder]):
|
||||
spec = self.util.find_spec(name)
|
||||
self.assertEqual((name, (name, None)), (spec.name, spec.loader))
|
||||
|
||||
def test_success_path(self):
|
||||
# Searching on a path should work.
|
||||
name = 'some_mod'
|
||||
path = 'path to some place'
|
||||
with test_util.uncache(name):
|
||||
with test_util.import_state(meta_path=[self.FakeMetaFinder]):
|
||||
spec = self.util.find_spec(name, path)
|
||||
self.assertEqual(name, spec.name)
|
||||
|
||||
def test_nothing(self):
|
||||
# None is returned upon failure to find a loader.
|
||||
self.assertIsNone(self.util.find_spec('nevergoingtofindthismodule'))
|
||||
|
||||
|
||||
class FindLoaderPEP451Tests(FindLoaderTests):
|
||||
|
||||
class FakeMetaFinder:
|
||||
@staticmethod
|
||||
def find_spec(name, path=None, target=None):
|
||||
return machinery['Source'].ModuleSpec(name, (name, path))
|
||||
|
||||
|
||||
(Frozen_FindLoaderPEP451Tests,
|
||||
Source_FindLoaderPEP451Tests
|
||||
) = test_util.test_both(
|
||||
FindLoaderPEP451Tests, init=init, util=util, machinery=machinery)
|
||||
|
||||
|
||||
class ReloadTests:
|
||||
|
||||
def test_reload_modules(self):
|
||||
for mod in ('tokenize', 'time', 'marshal'):
|
||||
with self.subTest(module=mod):
|
||||
with import_helper.CleanImport(mod):
|
||||
module = self.init.import_module(mod)
|
||||
self.init.reload(module)
|
||||
|
||||
def test_module_replaced(self):
|
||||
def code():
|
||||
import sys
|
||||
module = type(sys)('top_level')
|
||||
module.spam = 3
|
||||
sys.modules['top_level'] = module
|
||||
mock = test_util.mock_spec('top_level',
|
||||
module_code={'top_level': code})
|
||||
with mock:
|
||||
with test_util.import_state(meta_path=[mock]):
|
||||
module = self.init.import_module('top_level')
|
||||
reloaded = self.init.reload(module)
|
||||
actual = sys.modules['top_level']
|
||||
self.assertEqual(actual.spam, 3)
|
||||
self.assertEqual(reloaded.spam, 3)
|
||||
|
||||
def test_reload_missing_loader(self):
|
||||
with import_helper.CleanImport('types'):
|
||||
import types
|
||||
loader = types.__loader__
|
||||
del types.__loader__
|
||||
reloaded = self.init.reload(types)
|
||||
|
||||
self.assertIs(reloaded, types)
|
||||
self.assertIs(sys.modules['types'], types)
|
||||
self.assertEqual(reloaded.__loader__.path, loader.path)
|
||||
|
||||
def test_reload_loader_replaced(self):
|
||||
with import_helper.CleanImport('types'):
|
||||
import types
|
||||
types.__loader__ = None
|
||||
self.init.invalidate_caches()
|
||||
reloaded = self.init.reload(types)
|
||||
|
||||
self.assertIsNot(reloaded.__loader__, None)
|
||||
self.assertIs(reloaded, types)
|
||||
self.assertIs(sys.modules['types'], types)
|
||||
|
||||
def test_reload_location_changed(self):
|
||||
name = 'spam'
|
||||
with os_helper.temp_cwd(None) as cwd:
|
||||
with test_util.uncache('spam'):
|
||||
with import_helper.DirsOnSysPath(cwd):
|
||||
# Start as a plain module.
|
||||
self.init.invalidate_caches()
|
||||
path = os.path.join(cwd, name + '.py')
|
||||
cached = self.util.cache_from_source(path)
|
||||
expected = {'__name__': name,
|
||||
'__package__': '',
|
||||
'__file__': path,
|
||||
'__cached__': cached,
|
||||
'__doc__': None,
|
||||
}
|
||||
os_helper.create_empty_file(path)
|
||||
module = self.init.import_module(name)
|
||||
ns = vars(module).copy()
|
||||
loader = ns.pop('__loader__')
|
||||
spec = ns.pop('__spec__')
|
||||
ns.pop('__builtins__', None) # An implementation detail.
|
||||
self.assertEqual(spec.name, name)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertEqual(loader.path, path)
|
||||
self.assertEqual(ns, expected)
|
||||
|
||||
# Change to a package.
|
||||
self.init.invalidate_caches()
|
||||
init_path = os.path.join(cwd, name, '__init__.py')
|
||||
cached = self.util.cache_from_source(init_path)
|
||||
expected = {'__name__': name,
|
||||
'__package__': name,
|
||||
'__file__': init_path,
|
||||
'__cached__': cached,
|
||||
'__path__': [os.path.dirname(init_path)],
|
||||
'__doc__': None,
|
||||
}
|
||||
os.mkdir(name)
|
||||
os.rename(path, init_path)
|
||||
reloaded = self.init.reload(module)
|
||||
ns = vars(reloaded).copy()
|
||||
loader = ns.pop('__loader__')
|
||||
spec = ns.pop('__spec__')
|
||||
ns.pop('__builtins__', None) # An implementation detail.
|
||||
self.assertEqual(spec.name, name)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertIs(reloaded, module)
|
||||
self.assertEqual(loader.path, init_path)
|
||||
self.maxDiff = None
|
||||
self.assertEqual(ns, expected)
|
||||
|
||||
def test_reload_namespace_changed(self):
|
||||
name = 'spam'
|
||||
with os_helper.temp_cwd(None) as cwd:
|
||||
with test_util.uncache('spam'):
|
||||
with test_util.import_state(path=[cwd]):
|
||||
self.init._bootstrap_external._install(self.init._bootstrap)
|
||||
# Start as a namespace package.
|
||||
self.init.invalidate_caches()
|
||||
bad_path = os.path.join(cwd, name, '__init.py')
|
||||
cached = self.util.cache_from_source(bad_path)
|
||||
expected = {'__name__': name,
|
||||
'__package__': name,
|
||||
'__doc__': None,
|
||||
'__file__': None,
|
||||
}
|
||||
os.mkdir(name)
|
||||
with open(bad_path, 'w', encoding='utf-8') as init_file:
|
||||
init_file.write('eggs = None')
|
||||
module = self.init.import_module(name)
|
||||
ns = vars(module).copy()
|
||||
loader = ns.pop('__loader__')
|
||||
path = ns.pop('__path__')
|
||||
spec = ns.pop('__spec__')
|
||||
ns.pop('__builtins__', None) # An implementation detail.
|
||||
self.assertEqual(spec.name, name)
|
||||
self.assertIsNotNone(spec.loader)
|
||||
self.assertIsNotNone(loader)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertEqual(set(path),
|
||||
set([os.path.dirname(bad_path)]))
|
||||
with self.assertRaises(AttributeError):
|
||||
# a NamespaceLoader
|
||||
loader.path
|
||||
self.assertEqual(ns, expected)
|
||||
|
||||
# Change to a regular package.
|
||||
self.init.invalidate_caches()
|
||||
init_path = os.path.join(cwd, name, '__init__.py')
|
||||
cached = self.util.cache_from_source(init_path)
|
||||
expected = {'__name__': name,
|
||||
'__package__': name,
|
||||
'__file__': init_path,
|
||||
'__cached__': cached,
|
||||
'__path__': [os.path.dirname(init_path)],
|
||||
'__doc__': None,
|
||||
'eggs': None,
|
||||
}
|
||||
os.rename(bad_path, init_path)
|
||||
reloaded = self.init.reload(module)
|
||||
ns = vars(reloaded).copy()
|
||||
loader = ns.pop('__loader__')
|
||||
spec = ns.pop('__spec__')
|
||||
ns.pop('__builtins__', None) # An implementation detail.
|
||||
self.assertEqual(spec.name, name)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertIs(reloaded, module)
|
||||
self.assertEqual(loader.path, init_path)
|
||||
self.assertEqual(ns, expected)
|
||||
|
||||
def test_reload_submodule(self):
|
||||
# See #19851.
|
||||
name = 'spam'
|
||||
subname = 'ham'
|
||||
with test_util.temp_module(name, pkg=True) as pkg_dir:
|
||||
fullname, _ = test_util.submodule(name, subname, pkg_dir)
|
||||
ham = self.init.import_module(fullname)
|
||||
reloaded = self.init.reload(ham)
|
||||
self.assertIs(reloaded, ham)
|
||||
|
||||
def test_module_missing_spec(self):
|
||||
#Test that reload() throws ModuleNotFounderror when reloading
|
||||
# a module whose missing a spec. (bpo-29851)
|
||||
name = 'spam'
|
||||
with test_util.uncache(name):
|
||||
module = sys.modules[name] = types.ModuleType(name)
|
||||
# Sanity check by attempting an import.
|
||||
module = self.init.import_module(name)
|
||||
self.assertIsNone(module.__spec__)
|
||||
with self.assertRaises(ModuleNotFoundError):
|
||||
self.init.reload(module)
|
||||
|
||||
def test_reload_traceback_with_non_str(self):
|
||||
# gh-125519
|
||||
with support.captured_stdout() as stdout:
|
||||
try:
|
||||
self.init.reload("typing")
|
||||
except TypeError as exc:
|
||||
traceback.print_exception(exc, file=stdout)
|
||||
else:
|
||||
self.fail("Expected TypeError to be raised")
|
||||
printed_traceback = stdout.getvalue()
|
||||
self.assertIn("TypeError", printed_traceback)
|
||||
self.assertNotIn("AttributeError", printed_traceback)
|
||||
self.assertNotIn("module.__spec__.name", printed_traceback)
|
||||
|
||||
|
||||
(Frozen_ReloadTests,
|
||||
Source_ReloadTests
|
||||
) = test_util.test_both(
|
||||
ReloadTests, init=init, util=util, machinery=machinery)
|
||||
|
||||
|
||||
class InvalidateCacheTests:
|
||||
|
||||
def test_method_called(self):
|
||||
# If defined the method should be called.
|
||||
class InvalidatingNullFinder:
|
||||
def __init__(self, *ignored):
|
||||
self.called = False
|
||||
def invalidate_caches(self):
|
||||
self.called = True
|
||||
|
||||
key = os.path.abspath('gobledeegook')
|
||||
meta_ins = InvalidatingNullFinder()
|
||||
path_ins = InvalidatingNullFinder()
|
||||
sys.meta_path.insert(0, meta_ins)
|
||||
self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
|
||||
sys.path_importer_cache[key] = path_ins
|
||||
self.addCleanup(lambda: sys.meta_path.remove(meta_ins))
|
||||
self.init.invalidate_caches()
|
||||
self.assertTrue(meta_ins.called)
|
||||
self.assertTrue(path_ins.called)
|
||||
|
||||
def test_method_lacking(self):
|
||||
# There should be no issues if the method is not defined.
|
||||
key = 'gobbledeegook'
|
||||
sys.path_importer_cache[key] = None
|
||||
self.addCleanup(lambda: sys.path_importer_cache.pop(key, None))
|
||||
self.init.invalidate_caches() # Shouldn't trigger an exception.
|
||||
|
||||
|
||||
(Frozen_InvalidateCacheTests,
|
||||
Source_InvalidateCacheTests
|
||||
) = test_util.test_both(
|
||||
InvalidateCacheTests, init=init, util=util, machinery=machinery)
|
||||
|
||||
|
||||
class FrozenImportlibTests(unittest.TestCase):
|
||||
|
||||
def test_no_frozen_importlib(self):
|
||||
# Should be able to import w/o _frozen_importlib being defined.
|
||||
# Can't do an isinstance() check since separate copies of importlib
|
||||
# may have been used for import, so just check the name is not for the
|
||||
# frozen loader.
|
||||
source_init = init['Source']
|
||||
self.assertNotEqual(source_init.__loader__.__class__.__name__,
|
||||
'FrozenImporter')
|
||||
|
||||
|
||||
class StartupTests:
|
||||
|
||||
def test_everyone_has___loader__(self):
|
||||
# Issue #17098: all modules should have __loader__ defined.
|
||||
for name, module in sys.modules.items():
|
||||
if isinstance(module, types.ModuleType):
|
||||
with self.subTest(name=name):
|
||||
self.assertHasAttr(module, '__loader__')
|
||||
if self.machinery.BuiltinImporter.find_spec(name):
|
||||
self.assertIsNot(module.__loader__, None)
|
||||
elif self.machinery.FrozenImporter.find_spec(name):
|
||||
self.assertIsNot(module.__loader__, None)
|
||||
|
||||
def test_everyone_has___spec__(self):
|
||||
for name, module in sys.modules.items():
|
||||
if isinstance(module, types.ModuleType):
|
||||
with self.subTest(name=name):
|
||||
self.assertHasAttr(module, '__spec__')
|
||||
if self.machinery.BuiltinImporter.find_spec(name):
|
||||
self.assertIsNot(module.__spec__, None)
|
||||
elif self.machinery.FrozenImporter.find_spec(name):
|
||||
self.assertIsNot(module.__spec__, None)
|
||||
|
||||
|
||||
(Frozen_StartupTests,
|
||||
Source_StartupTests
|
||||
) = test_util.test_both(StartupTests, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
230
Dependencies/Python/Lib/test/test_importlib/test_lazy.py
vendored
Normal file
230
Dependencies/Python/Lib/test/test_importlib/test_lazy.py
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
import importlib
|
||||
from importlib import abc
|
||||
from importlib import util
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
import types
|
||||
import unittest
|
||||
|
||||
from test.support import threading_helper
|
||||
from test.test_importlib import util as test_util
|
||||
from test.support.testcase import ExtraAssertions
|
||||
|
||||
|
||||
class CollectInit:
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
def exec_module(self, module):
|
||||
return self
|
||||
|
||||
|
||||
class LazyLoaderFactoryTests(unittest.TestCase):
|
||||
|
||||
def test_init(self):
|
||||
factory = util.LazyLoader.factory(CollectInit)
|
||||
# E.g. what importlib.machinery.FileFinder instantiates loaders with
|
||||
# plus keyword arguments.
|
||||
lazy_loader = factory('module name', 'module path', kw='kw')
|
||||
loader = lazy_loader.loader
|
||||
self.assertEqual(('module name', 'module path'), loader.args)
|
||||
self.assertEqual({'kw': 'kw'}, loader.kwargs)
|
||||
|
||||
def test_validation(self):
|
||||
# No exec_module(), no lazy loading.
|
||||
with self.assertRaises(TypeError):
|
||||
util.LazyLoader.factory(object)
|
||||
|
||||
|
||||
class TestingImporter(abc.MetaPathFinder, abc.Loader):
|
||||
|
||||
module_name = 'lazy_loader_test'
|
||||
mutated_name = 'changed'
|
||||
loaded = None
|
||||
load_count = 0
|
||||
source_code = 'attr = 42; __name__ = {!r}'.format(mutated_name)
|
||||
|
||||
def find_spec(self, name, path, target=None):
|
||||
if name != self.module_name:
|
||||
return None
|
||||
return util.spec_from_loader(name, util.LazyLoader(self))
|
||||
|
||||
def exec_module(self, module):
|
||||
time.sleep(0.01) # Simulate a slow load.
|
||||
exec(self.source_code, module.__dict__)
|
||||
self.loaded = module
|
||||
self.load_count += 1
|
||||
|
||||
|
||||
class LazyLoaderTests(unittest.TestCase, ExtraAssertions):
|
||||
|
||||
def test_init(self):
|
||||
with self.assertRaises(TypeError):
|
||||
# Classes that don't define exec_module() trigger TypeError.
|
||||
util.LazyLoader(object)
|
||||
|
||||
def new_module(self, source_code=None, loader=None):
|
||||
if loader is None:
|
||||
loader = TestingImporter()
|
||||
if source_code is not None:
|
||||
loader.source_code = source_code
|
||||
spec = util.spec_from_loader(TestingImporter.module_name,
|
||||
util.LazyLoader(loader))
|
||||
module = spec.loader.create_module(spec)
|
||||
if module is None:
|
||||
module = types.ModuleType(TestingImporter.module_name)
|
||||
module.__spec__ = spec
|
||||
module.__loader__ = spec.loader
|
||||
spec.loader.exec_module(module)
|
||||
# Module is now lazy.
|
||||
self.assertIsNone(loader.loaded)
|
||||
return module
|
||||
|
||||
def test_e2e(self):
|
||||
# End-to-end test to verify the load is in fact lazy.
|
||||
importer = TestingImporter()
|
||||
assert importer.loaded is None
|
||||
with test_util.uncache(importer.module_name):
|
||||
with test_util.import_state(meta_path=[importer]):
|
||||
module = importlib.import_module(importer.module_name)
|
||||
self.assertIsNone(importer.loaded)
|
||||
# Trigger load.
|
||||
self.assertEqual(module.__loader__, importer)
|
||||
self.assertIsNotNone(importer.loaded)
|
||||
self.assertEqual(module, importer.loaded)
|
||||
|
||||
def test_attr_unchanged(self):
|
||||
# An attribute only mutated as a side-effect of import should not be
|
||||
# changed needlessly.
|
||||
module = self.new_module()
|
||||
self.assertEqual(TestingImporter.mutated_name, module.__name__)
|
||||
|
||||
def test_new_attr(self):
|
||||
# A new attribute should persist.
|
||||
module = self.new_module()
|
||||
module.new_attr = 42
|
||||
self.assertEqual(42, module.new_attr)
|
||||
|
||||
def test_mutated_preexisting_attr(self):
|
||||
# Changing an attribute that already existed on the module --
|
||||
# e.g. __name__ -- should persist.
|
||||
module = self.new_module()
|
||||
module.__name__ = 'bogus'
|
||||
self.assertEqual('bogus', module.__name__)
|
||||
|
||||
def test_mutated_attr(self):
|
||||
# Changing an attribute that comes into existence after an import
|
||||
# should persist.
|
||||
module = self.new_module()
|
||||
module.attr = 6
|
||||
self.assertEqual(6, module.attr)
|
||||
|
||||
def test_delete_eventual_attr(self):
|
||||
# Deleting an attribute should stay deleted.
|
||||
module = self.new_module()
|
||||
del module.attr
|
||||
self.assertNotHasAttr(module, 'attr')
|
||||
|
||||
def test_delete_preexisting_attr(self):
|
||||
module = self.new_module()
|
||||
del module.__name__
|
||||
self.assertNotHasAttr(module, '__name__')
|
||||
|
||||
def test_module_substitution_error(self):
|
||||
with test_util.uncache(TestingImporter.module_name):
|
||||
fresh_module = types.ModuleType(TestingImporter.module_name)
|
||||
sys.modules[TestingImporter.module_name] = fresh_module
|
||||
module = self.new_module()
|
||||
with self.assertRaisesRegex(ValueError, "substituted"):
|
||||
module.__name__
|
||||
|
||||
def test_module_already_in_sys(self):
|
||||
with test_util.uncache(TestingImporter.module_name):
|
||||
module = self.new_module()
|
||||
sys.modules[TestingImporter.module_name] = module
|
||||
# Force the load; just care that no exception is raised.
|
||||
module.__name__
|
||||
|
||||
@threading_helper.requires_working_threading()
|
||||
def test_module_load_race(self):
|
||||
with test_util.uncache(TestingImporter.module_name):
|
||||
loader = TestingImporter()
|
||||
module = self.new_module(loader=loader)
|
||||
self.assertEqual(loader.load_count, 0)
|
||||
|
||||
class RaisingThread(threading.Thread):
|
||||
exc = None
|
||||
def run(self):
|
||||
try:
|
||||
super().run()
|
||||
except Exception as exc:
|
||||
self.exc = exc
|
||||
|
||||
def access_module():
|
||||
return module.attr
|
||||
|
||||
threads = []
|
||||
for _ in range(2):
|
||||
threads.append(thread := RaisingThread(target=access_module))
|
||||
thread.start()
|
||||
|
||||
# Races could cause errors
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
self.assertIsNone(thread.exc)
|
||||
|
||||
# Or multiple load attempts
|
||||
self.assertEqual(loader.load_count, 1)
|
||||
|
||||
def test_lazy_self_referential_modules(self):
|
||||
# Directory modules with submodules that reference the parent can attempt to access
|
||||
# the parent module during a load. Verify that this common pattern works with lazy loading.
|
||||
# json is a good example in the stdlib.
|
||||
json_modules = [name for name in sys.modules if name.startswith('json')]
|
||||
with test_util.uncache(*json_modules):
|
||||
# Standard lazy loading, unwrapped
|
||||
spec = util.find_spec('json')
|
||||
loader = util.LazyLoader(spec.loader)
|
||||
spec.loader = loader
|
||||
module = util.module_from_spec(spec)
|
||||
sys.modules['json'] = module
|
||||
loader.exec_module(module)
|
||||
|
||||
# Trigger load with attribute lookup, ensure expected behavior
|
||||
test_load = module.loads('{}')
|
||||
self.assertEqual(test_load, {})
|
||||
|
||||
def test_lazy_module_type_override(self):
|
||||
# Verify that lazy loading works with a module that modifies
|
||||
# its __class__ to be a custom type.
|
||||
|
||||
# Example module from PEP 726
|
||||
module = self.new_module(source_code="""\
|
||||
import sys
|
||||
from types import ModuleType
|
||||
|
||||
CONSTANT = 3.14
|
||||
|
||||
class ImmutableModule(ModuleType):
|
||||
def __setattr__(self, name, value):
|
||||
raise AttributeError('Read-only attribute!')
|
||||
|
||||
def __delattr__(self, name):
|
||||
raise AttributeError('Read-only attribute!')
|
||||
|
||||
sys.modules[__name__].__class__ = ImmutableModule
|
||||
""")
|
||||
sys.modules[TestingImporter.module_name] = module
|
||||
self.assertIsInstance(module, util._LazyModule)
|
||||
self.assertEqual(module.CONSTANT, 3.14)
|
||||
with self.assertRaises(AttributeError):
|
||||
module.CONSTANT = 2.71
|
||||
with self.assertRaises(AttributeError):
|
||||
del module.CONSTANT
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
160
Dependencies/Python/Lib/test/test_importlib/test_locks.py
vendored
Normal file
160
Dependencies/Python/Lib/test/test_importlib/test_locks.py
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
from test.test_importlib import util as test_util
|
||||
|
||||
init = test_util.import_importlib('importlib')
|
||||
|
||||
import sys
|
||||
import threading
|
||||
import unittest
|
||||
import weakref
|
||||
|
||||
from test import support
|
||||
from test.support import threading_helper
|
||||
from test import lock_tests
|
||||
|
||||
|
||||
threading_helper.requires_working_threading(module=True)
|
||||
|
||||
|
||||
class ModuleLockAsRLockTests:
|
||||
locktype = classmethod(lambda cls: cls.LockType("some_lock"))
|
||||
|
||||
# _is_owned() unsupported
|
||||
test__is_owned = None
|
||||
# acquire(blocking=False) unsupported
|
||||
test_try_acquire = None
|
||||
test_try_acquire_contended = None
|
||||
# `with` unsupported
|
||||
test_with = None
|
||||
# acquire(timeout=...) unsupported
|
||||
test_timeout = None
|
||||
# _release_save() unsupported
|
||||
test_release_save_unacquired = None
|
||||
# _recursion_count() unsupported
|
||||
test_recursion_count = None
|
||||
# lock status in repr unsupported
|
||||
test_repr = None
|
||||
test_locked_repr = None
|
||||
|
||||
def tearDown(self):
|
||||
for splitinit in init.values():
|
||||
splitinit._bootstrap._blocking_on.clear()
|
||||
|
||||
|
||||
LOCK_TYPES = {kind: splitinit._bootstrap._ModuleLock
|
||||
for kind, splitinit in init.items()}
|
||||
|
||||
(Frozen_ModuleLockAsRLockTests,
|
||||
Source_ModuleLockAsRLockTests
|
||||
) = test_util.test_both(ModuleLockAsRLockTests, lock_tests.RLockTests,
|
||||
LockType=LOCK_TYPES)
|
||||
|
||||
|
||||
class DeadlockAvoidanceTests:
|
||||
|
||||
def setUp(self):
|
||||
try:
|
||||
self.old_switchinterval = sys.getswitchinterval()
|
||||
support.setswitchinterval(0.000001)
|
||||
except AttributeError:
|
||||
self.old_switchinterval = None
|
||||
|
||||
def tearDown(self):
|
||||
if self.old_switchinterval is not None:
|
||||
sys.setswitchinterval(self.old_switchinterval)
|
||||
|
||||
def run_deadlock_avoidance_test(self, create_deadlock):
|
||||
NLOCKS = 10
|
||||
locks = [self.LockType(str(i)) for i in range(NLOCKS)]
|
||||
pairs = [(locks[i], locks[(i+1)%NLOCKS]) for i in range(NLOCKS)]
|
||||
if create_deadlock:
|
||||
NTHREADS = NLOCKS
|
||||
else:
|
||||
NTHREADS = NLOCKS - 1
|
||||
barrier = threading.Barrier(NTHREADS)
|
||||
results = []
|
||||
|
||||
def _acquire(lock):
|
||||
"""Try to acquire the lock. Return True on success,
|
||||
False on deadlock."""
|
||||
try:
|
||||
lock.acquire()
|
||||
except self.DeadlockError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def f():
|
||||
a, b = pairs.pop()
|
||||
ra = _acquire(a)
|
||||
barrier.wait()
|
||||
rb = _acquire(b)
|
||||
results.append((ra, rb))
|
||||
if rb:
|
||||
b.release()
|
||||
if ra:
|
||||
a.release()
|
||||
with lock_tests.Bunch(f, NTHREADS):
|
||||
pass
|
||||
self.assertEqual(len(results), NTHREADS)
|
||||
return results
|
||||
|
||||
def test_deadlock(self):
|
||||
results = self.run_deadlock_avoidance_test(True)
|
||||
# At least one of the threads detected a potential deadlock on its
|
||||
# second acquire() call. It may be several of them, because the
|
||||
# deadlock avoidance mechanism is conservative.
|
||||
nb_deadlocks = results.count((True, False))
|
||||
self.assertGreaterEqual(nb_deadlocks, 1)
|
||||
self.assertEqual(results.count((True, True)), len(results) - nb_deadlocks)
|
||||
|
||||
def test_no_deadlock(self):
|
||||
results = self.run_deadlock_avoidance_test(False)
|
||||
self.assertEqual(results.count((True, False)), 0)
|
||||
self.assertEqual(results.count((True, True)), len(results))
|
||||
|
||||
|
||||
DEADLOCK_ERRORS = {kind: splitinit._bootstrap._DeadlockError
|
||||
for kind, splitinit in init.items()}
|
||||
|
||||
(Frozen_DeadlockAvoidanceTests,
|
||||
Source_DeadlockAvoidanceTests
|
||||
) = test_util.test_both(DeadlockAvoidanceTests,
|
||||
LockType=LOCK_TYPES,
|
||||
DeadlockError=DEADLOCK_ERRORS)
|
||||
|
||||
|
||||
class LifetimeTests:
|
||||
|
||||
@property
|
||||
def bootstrap(self):
|
||||
return self.init._bootstrap
|
||||
|
||||
def test_lock_lifetime(self):
|
||||
name = "xyzzy"
|
||||
self.assertNotIn(name, self.bootstrap._module_locks)
|
||||
lock = self.bootstrap._get_module_lock(name)
|
||||
self.assertIn(name, self.bootstrap._module_locks)
|
||||
wr = weakref.ref(lock)
|
||||
del lock
|
||||
support.gc_collect()
|
||||
self.assertNotIn(name, self.bootstrap._module_locks)
|
||||
self.assertIsNone(wr())
|
||||
|
||||
def test_all_locks(self):
|
||||
support.gc_collect()
|
||||
self.assertEqual(0, len(self.bootstrap._module_locks),
|
||||
self.bootstrap._module_locks)
|
||||
|
||||
|
||||
(Frozen_LifetimeTests,
|
||||
Source_LifetimeTests
|
||||
) = test_util.test_both(LifetimeTests, init=init)
|
||||
|
||||
|
||||
def setUpModule():
|
||||
thread_info = threading_helper.threading_setup()
|
||||
unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
381
Dependencies/Python/Lib/test/test_importlib/test_namespace_pkgs.py
vendored
Normal file
381
Dependencies/Python/Lib/test/test_importlib/test_namespace_pkgs.py
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
import contextlib
|
||||
import importlib
|
||||
import importlib.abc
|
||||
import importlib.machinery
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from test.test_importlib import util
|
||||
from test.support.testcase import ExtraAssertions
|
||||
|
||||
# needed tests:
|
||||
#
|
||||
# need to test when nested, so that the top-level path isn't sys.path
|
||||
# need to test dynamic path detection, both at top-level and nested
|
||||
# with dynamic path, check when a loader is returned on path reload (that is,
|
||||
# trying to switch from a namespace package to a regular package)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def sys_modules_context():
|
||||
"""
|
||||
Make sure sys.modules is the same object and has the same content
|
||||
when exiting the context as when entering.
|
||||
|
||||
Similar to importlib.test.util.uncache, but doesn't require explicit
|
||||
names.
|
||||
"""
|
||||
sys_modules_saved = sys.modules
|
||||
sys_modules_copy = sys.modules.copy()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
sys.modules = sys_modules_saved
|
||||
sys.modules.clear()
|
||||
sys.modules.update(sys_modules_copy)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def namespace_tree_context(**kwargs):
|
||||
"""
|
||||
Save import state and sys.modules cache and restore it on exit.
|
||||
Typical usage:
|
||||
|
||||
>>> with namespace_tree_context(path=['/tmp/xxyy/portion1',
|
||||
... '/tmp/xxyy/portion2']):
|
||||
... pass
|
||||
"""
|
||||
# use default meta_path and path_hooks unless specified otherwise
|
||||
kwargs.setdefault('meta_path', sys.meta_path)
|
||||
kwargs.setdefault('path_hooks', sys.path_hooks)
|
||||
import_context = util.import_state(**kwargs)
|
||||
with import_context, sys_modules_context():
|
||||
yield
|
||||
|
||||
class NamespacePackageTest(unittest.TestCase, ExtraAssertions):
|
||||
"""
|
||||
Subclasses should define self.root and self.paths (under that root)
|
||||
to be added to sys.path.
|
||||
"""
|
||||
root = os.path.join(os.path.dirname(__file__), 'namespace_pkgs')
|
||||
|
||||
def setUp(self):
|
||||
self.resolved_paths = [
|
||||
os.path.join(self.root, path) for path in self.paths
|
||||
]
|
||||
self.enterContext(namespace_tree_context(path=self.resolved_paths))
|
||||
|
||||
|
||||
class SingleNamespacePackage(NamespacePackageTest):
|
||||
paths = ['portion1']
|
||||
|
||||
def test_simple_package(self):
|
||||
import foo.one
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
|
||||
def test_cant_import_other(self):
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.two
|
||||
|
||||
def test_simple_repr(self):
|
||||
import foo.one
|
||||
self.assertStartsWith(repr(foo), "<module 'foo' (namespace) from [")
|
||||
|
||||
|
||||
class DynamicPathNamespacePackage(NamespacePackageTest):
|
||||
paths = ['portion1']
|
||||
|
||||
def test_dynamic_path(self):
|
||||
# Make sure only 'foo.one' can be imported
|
||||
import foo.one
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.two
|
||||
|
||||
# Now modify sys.path
|
||||
sys.path.append(os.path.join(self.root, 'portion2'))
|
||||
|
||||
# And make sure foo.two is now importable
|
||||
import foo.two
|
||||
self.assertEqual(foo.two.attr, 'portion2 foo two')
|
||||
|
||||
|
||||
class CombinedNamespacePackages(NamespacePackageTest):
|
||||
paths = ['both_portions']
|
||||
|
||||
def test_imports(self):
|
||||
import foo.one
|
||||
import foo.two
|
||||
self.assertEqual(foo.one.attr, 'both_portions foo one')
|
||||
self.assertEqual(foo.two.attr, 'both_portions foo two')
|
||||
|
||||
|
||||
class SeparatedNamespacePackages(NamespacePackageTest):
|
||||
paths = ['portion1', 'portion2']
|
||||
|
||||
def test_imports(self):
|
||||
import foo.one
|
||||
import foo.two
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
self.assertEqual(foo.two.attr, 'portion2 foo two')
|
||||
|
||||
|
||||
class SeparatedNamespacePackagesCreatedWhileRunning(NamespacePackageTest):
|
||||
paths = ['portion1']
|
||||
|
||||
def test_invalidate_caches(self):
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
# we manipulate sys.path before anything is imported to avoid
|
||||
# accidental cache invalidation when changing it
|
||||
sys.path.append(temp_dir)
|
||||
|
||||
import foo.one
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
|
||||
# the module does not exist, so it cannot be imported
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.just_created
|
||||
|
||||
# util.create_modules() manipulates sys.path
|
||||
# so we must create the modules manually instead
|
||||
namespace_path = os.path.join(temp_dir, 'foo')
|
||||
os.mkdir(namespace_path)
|
||||
module_path = os.path.join(namespace_path, 'just_created.py')
|
||||
with open(module_path, 'w', encoding='utf-8') as file:
|
||||
file.write('attr = "just_created foo"')
|
||||
|
||||
# the module is not known, so it cannot be imported yet
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.just_created
|
||||
|
||||
# but after explicit cache invalidation, it is importable
|
||||
importlib.invalidate_caches()
|
||||
import foo.just_created
|
||||
self.assertEqual(foo.just_created.attr, 'just_created foo')
|
||||
|
||||
|
||||
class SeparatedOverlappingNamespacePackages(NamespacePackageTest):
|
||||
paths = ['portion1', 'both_portions']
|
||||
|
||||
def test_first_path_wins(self):
|
||||
import foo.one
|
||||
import foo.two
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
self.assertEqual(foo.two.attr, 'both_portions foo two')
|
||||
|
||||
def test_first_path_wins_again(self):
|
||||
sys.path.reverse()
|
||||
import foo.one
|
||||
import foo.two
|
||||
self.assertEqual(foo.one.attr, 'both_portions foo one')
|
||||
self.assertEqual(foo.two.attr, 'both_portions foo two')
|
||||
|
||||
def test_first_path_wins_importing_second_first(self):
|
||||
import foo.two
|
||||
import foo.one
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
self.assertEqual(foo.two.attr, 'both_portions foo two')
|
||||
|
||||
|
||||
class SingleZipNamespacePackage(NamespacePackageTest):
|
||||
paths = ['top_level_portion1.zip']
|
||||
|
||||
def test_simple_package(self):
|
||||
import foo.one
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
|
||||
def test_cant_import_other(self):
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.two
|
||||
|
||||
|
||||
class SeparatedZipNamespacePackages(NamespacePackageTest):
|
||||
paths = ['top_level_portion1.zip', 'portion2']
|
||||
|
||||
def test_imports(self):
|
||||
import foo.one
|
||||
import foo.two
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
self.assertEqual(foo.two.attr, 'portion2 foo two')
|
||||
self.assertIn('top_level_portion1.zip', foo.one.__file__)
|
||||
self.assertNotIn('.zip', foo.two.__file__)
|
||||
|
||||
|
||||
class SingleNestedZipNamespacePackage(NamespacePackageTest):
|
||||
paths = ['nested_portion1.zip/nested_portion1']
|
||||
|
||||
def test_simple_package(self):
|
||||
import foo.one
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
|
||||
def test_cant_import_other(self):
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.two
|
||||
|
||||
|
||||
class SeparatedNestedZipNamespacePackages(NamespacePackageTest):
|
||||
paths = ['nested_portion1.zip/nested_portion1', 'portion2']
|
||||
|
||||
def test_imports(self):
|
||||
import foo.one
|
||||
import foo.two
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
self.assertEqual(foo.two.attr, 'portion2 foo two')
|
||||
fn = os.path.join('nested_portion1.zip', 'nested_portion1')
|
||||
self.assertIn(fn, foo.one.__file__)
|
||||
self.assertNotIn('.zip', foo.two.__file__)
|
||||
|
||||
|
||||
class LegacySupport(NamespacePackageTest):
|
||||
paths = ['not_a_namespace_pkg', 'portion1', 'portion2', 'both_portions']
|
||||
|
||||
def test_non_namespace_package_takes_precedence(self):
|
||||
import foo.one
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.two
|
||||
self.assertIn('__init__', foo.__file__)
|
||||
self.assertNotIn('namespace', str(foo.__loader__).lower())
|
||||
|
||||
|
||||
class DynamicPathCalculation(NamespacePackageTest):
|
||||
paths = ['project1', 'project2']
|
||||
|
||||
def test_project3_fails(self):
|
||||
import parent.child.one
|
||||
self.assertEqual(len(parent.__path__), 2)
|
||||
self.assertEqual(len(parent.child.__path__), 2)
|
||||
import parent.child.two
|
||||
self.assertEqual(len(parent.__path__), 2)
|
||||
self.assertEqual(len(parent.child.__path__), 2)
|
||||
|
||||
self.assertEqual(parent.child.one.attr, 'parent child one')
|
||||
self.assertEqual(parent.child.two.attr, 'parent child two')
|
||||
|
||||
with self.assertRaises(ImportError):
|
||||
import parent.child.three
|
||||
|
||||
self.assertEqual(len(parent.__path__), 2)
|
||||
self.assertEqual(len(parent.child.__path__), 2)
|
||||
|
||||
def test_project3_succeeds(self):
|
||||
import parent.child.one
|
||||
self.assertEqual(len(parent.__path__), 2)
|
||||
self.assertEqual(len(parent.child.__path__), 2)
|
||||
import parent.child.two
|
||||
self.assertEqual(len(parent.__path__), 2)
|
||||
self.assertEqual(len(parent.child.__path__), 2)
|
||||
|
||||
self.assertEqual(parent.child.one.attr, 'parent child one')
|
||||
self.assertEqual(parent.child.two.attr, 'parent child two')
|
||||
|
||||
with self.assertRaises(ImportError):
|
||||
import parent.child.three
|
||||
|
||||
# now add project3
|
||||
sys.path.append(os.path.join(self.root, 'project3'))
|
||||
import parent.child.three
|
||||
|
||||
# the paths dynamically get longer, to include the new directories
|
||||
self.assertEqual(len(parent.__path__), 3)
|
||||
self.assertEqual(len(parent.child.__path__), 3)
|
||||
|
||||
self.assertEqual(parent.child.three.attr, 'parent child three')
|
||||
|
||||
|
||||
class ZipWithMissingDirectory(NamespacePackageTest):
|
||||
paths = ['missing_directory.zip']
|
||||
|
||||
@unittest.expectedFailure
|
||||
def test_missing_directory(self):
|
||||
# This will fail because missing_directory.zip contains:
|
||||
# Length Date Time Name
|
||||
# --------- ---------- ----- ----
|
||||
# 29 2012-05-03 18:13 foo/one.py
|
||||
# 0 2012-05-03 20:57 bar/
|
||||
# 38 2012-05-03 20:57 bar/two.py
|
||||
# --------- -------
|
||||
# 67 3 files
|
||||
|
||||
# Because there is no 'foo/', the zipimporter currently doesn't
|
||||
# know that foo is a namespace package
|
||||
|
||||
import foo.one
|
||||
|
||||
def test_present_directory(self):
|
||||
# This succeeds because there is a "bar/" in the zip file
|
||||
import bar.two
|
||||
self.assertEqual(bar.two.attr, 'missing_directory foo two')
|
||||
|
||||
|
||||
class ModuleAndNamespacePackageInSameDir(NamespacePackageTest):
|
||||
paths = ['module_and_namespace_package']
|
||||
|
||||
def test_module_before_namespace_package(self):
|
||||
# Make sure we find the module in preference to the
|
||||
# namespace package.
|
||||
import a_test
|
||||
self.assertEqual(a_test.attr, 'in module')
|
||||
|
||||
|
||||
class ReloadTests(NamespacePackageTest):
|
||||
paths = ['portion1']
|
||||
|
||||
def test_simple_package(self):
|
||||
import foo.one
|
||||
foo = importlib.reload(foo)
|
||||
self.assertEqual(foo.one.attr, 'portion1 foo one')
|
||||
|
||||
def test_cant_import_other(self):
|
||||
import foo
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.two
|
||||
foo = importlib.reload(foo)
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.two
|
||||
|
||||
def test_dynamic_path(self):
|
||||
import foo.one
|
||||
with self.assertRaises(ImportError):
|
||||
import foo.two
|
||||
|
||||
# Now modify sys.path and reload.
|
||||
sys.path.append(os.path.join(self.root, 'portion2'))
|
||||
foo = importlib.reload(foo)
|
||||
|
||||
# And make sure foo.two is now importable
|
||||
import foo.two
|
||||
self.assertEqual(foo.two.attr, 'portion2 foo two')
|
||||
|
||||
|
||||
class LoaderTests(NamespacePackageTest):
|
||||
paths = ['portion1']
|
||||
|
||||
def test_namespace_loader_consistency(self):
|
||||
# bpo-32303
|
||||
import foo
|
||||
self.assertEqual(foo.__loader__, foo.__spec__.loader)
|
||||
self.assertIsNotNone(foo.__loader__)
|
||||
|
||||
def test_namespace_origin_consistency(self):
|
||||
# bpo-32305
|
||||
import foo
|
||||
self.assertIsNone(foo.__spec__.origin)
|
||||
self.assertIsNone(foo.__file__)
|
||||
|
||||
def test_path_indexable(self):
|
||||
# bpo-35843
|
||||
import foo
|
||||
expected_path = os.path.join(self.root, 'portion1', 'foo')
|
||||
self.assertEqual(foo.__path__[0], expected_path)
|
||||
|
||||
def test_loader_abc(self):
|
||||
import foo
|
||||
self.assertTrue(isinstance(foo.__loader__, importlib.abc.Loader))
|
||||
self.assertTrue(isinstance(foo.__loader__, importlib.machinery.NamespaceLoader))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
81
Dependencies/Python/Lib/test/test_importlib/test_pkg_import.py
vendored
Normal file
81
Dependencies/Python/Lib/test/test_importlib/test_pkg_import.py
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import string
|
||||
import random
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from importlib.util import cache_from_source
|
||||
from test.support.os_helper import create_empty_file
|
||||
from test.support.testcase import ExtraAssertions
|
||||
|
||||
class TestImport(unittest.TestCase, ExtraAssertions):
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
self.package_name = 'PACKAGE_'
|
||||
while self.package_name in sys.modules:
|
||||
self.package_name += random.choice(string.ascii_letters)
|
||||
self.module_name = self.package_name + '.foo'
|
||||
unittest.TestCase.__init__(self, *args, **kw)
|
||||
|
||||
def remove_modules(self):
|
||||
for module_name in (self.package_name, self.module_name):
|
||||
if module_name in sys.modules:
|
||||
del sys.modules[module_name]
|
||||
|
||||
def setUp(self):
|
||||
self.test_dir = tempfile.mkdtemp()
|
||||
sys.path.append(self.test_dir)
|
||||
self.package_dir = os.path.join(self.test_dir,
|
||||
self.package_name)
|
||||
os.mkdir(self.package_dir)
|
||||
create_empty_file(os.path.join(self.package_dir, '__init__.py'))
|
||||
self.module_path = os.path.join(self.package_dir, 'foo.py')
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.test_dir)
|
||||
self.assertNotEqual(sys.path.count(self.test_dir), 0)
|
||||
sys.path.remove(self.test_dir)
|
||||
self.remove_modules()
|
||||
|
||||
def rewrite_file(self, contents):
|
||||
compiled_path = cache_from_source(self.module_path)
|
||||
if os.path.exists(compiled_path):
|
||||
os.remove(compiled_path)
|
||||
with open(self.module_path, 'w', encoding='utf-8') as f:
|
||||
f.write(contents)
|
||||
|
||||
def test_package_import__semantics(self):
|
||||
|
||||
# Generate a couple of broken modules to try importing.
|
||||
|
||||
# ...try loading the module when there's a SyntaxError
|
||||
self.rewrite_file('for')
|
||||
try: __import__(self.module_name)
|
||||
except SyntaxError: pass
|
||||
else: raise RuntimeError('Failed to induce SyntaxError') # self.fail()?
|
||||
self.assertNotIn(self.module_name, sys.modules)
|
||||
self.assertNotHasAttr(sys.modules[self.package_name], 'foo')
|
||||
|
||||
# ...make up a variable name that isn't bound in __builtins__
|
||||
var = 'a'
|
||||
while var in dir(__builtins__):
|
||||
var += random.choice(string.ascii_letters)
|
||||
|
||||
# ...make a module that just contains that
|
||||
self.rewrite_file(var)
|
||||
|
||||
try: __import__(self.module_name)
|
||||
except NameError: pass
|
||||
else: raise RuntimeError('Failed to induce NameError.')
|
||||
|
||||
# ...now change the module so that the NameError doesn't
|
||||
# happen
|
||||
self.rewrite_file('%s = 1' % var)
|
||||
module = __import__(self.module_name).foo
|
||||
self.assertEqual(getattr(module, var), 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
698
Dependencies/Python/Lib/test/test_importlib/test_spec.py
vendored
Normal file
698
Dependencies/Python/Lib/test/test_importlib/test_spec.py
vendored
Normal file
@@ -0,0 +1,698 @@
|
||||
from test.test_importlib import util as test_util
|
||||
|
||||
init = test_util.import_importlib('importlib')
|
||||
machinery = test_util.import_importlib('importlib.machinery')
|
||||
util = test_util.import_importlib('importlib.util')
|
||||
|
||||
import os.path
|
||||
import pathlib
|
||||
from test.support.import_helper import CleanImport
|
||||
import unittest
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
|
||||
|
||||
class TestLoader:
|
||||
|
||||
def __init__(self, path=None, is_package=None):
|
||||
self.path = path
|
||||
self.package = is_package
|
||||
|
||||
def __repr__(self):
|
||||
return '<TestLoader object>'
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name == 'get_filename' and self.path is not None:
|
||||
return self._get_filename
|
||||
if name == 'is_package':
|
||||
return self._is_package
|
||||
raise AttributeError(name)
|
||||
|
||||
def _get_filename(self, name):
|
||||
return self.path
|
||||
|
||||
def _is_package(self, name):
|
||||
return self.package
|
||||
|
||||
def create_module(self, spec):
|
||||
return None
|
||||
|
||||
|
||||
class NewLoader(TestLoader):
|
||||
|
||||
EGGS = 1
|
||||
|
||||
def exec_module(self, module):
|
||||
module.eggs = self.EGGS
|
||||
|
||||
|
||||
class ModuleSpecTests:
|
||||
|
||||
def setUp(self):
|
||||
self.name = 'spam'
|
||||
self.path = 'spam.py'
|
||||
self.cached = self.util.cache_from_source(self.path)
|
||||
self.loader = TestLoader()
|
||||
self.spec = self.machinery.ModuleSpec(self.name, self.loader)
|
||||
self.loc_spec = self.machinery.ModuleSpec(self.name, self.loader,
|
||||
origin=self.path)
|
||||
self.loc_spec._set_fileattr = True
|
||||
|
||||
def test_default(self):
|
||||
spec = self.machinery.ModuleSpec(self.name, self.loader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.loader)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_default_no_loader(self):
|
||||
spec = self.machinery.ModuleSpec(self.name, None)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertIs(spec.loader, None)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_default_is_package_false(self):
|
||||
spec = self.machinery.ModuleSpec(self.name, self.loader,
|
||||
is_package=False)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.loader)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_default_is_package_true(self):
|
||||
spec = self.machinery.ModuleSpec(self.name, self.loader,
|
||||
is_package=True)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.loader)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertEqual(spec.submodule_search_locations, [])
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_has_location_setter(self):
|
||||
spec = self.machinery.ModuleSpec(self.name, self.loader,
|
||||
origin='somewhere')
|
||||
self.assertFalse(spec.has_location)
|
||||
spec.has_location = True
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_equality(self):
|
||||
other = type(sys.implementation)(name=self.name,
|
||||
loader=self.loader,
|
||||
origin=None,
|
||||
submodule_search_locations=None,
|
||||
has_location=False,
|
||||
cached=None,
|
||||
)
|
||||
|
||||
self.assertTrue(self.spec == other)
|
||||
|
||||
def test_equality_location(self):
|
||||
other = type(sys.implementation)(name=self.name,
|
||||
loader=self.loader,
|
||||
origin=self.path,
|
||||
submodule_search_locations=None,
|
||||
has_location=True,
|
||||
cached=self.cached,
|
||||
)
|
||||
|
||||
self.assertEqual(self.loc_spec, other)
|
||||
|
||||
def test_inequality(self):
|
||||
other = type(sys.implementation)(name='ham',
|
||||
loader=self.loader,
|
||||
origin=None,
|
||||
submodule_search_locations=None,
|
||||
has_location=False,
|
||||
cached=None,
|
||||
)
|
||||
|
||||
self.assertNotEqual(self.spec, other)
|
||||
|
||||
def test_inequality_incomplete(self):
|
||||
other = type(sys.implementation)(name=self.name,
|
||||
loader=self.loader,
|
||||
)
|
||||
|
||||
self.assertNotEqual(self.spec, other)
|
||||
|
||||
def test_package(self):
|
||||
spec = self.machinery.ModuleSpec('spam.eggs', self.loader)
|
||||
|
||||
self.assertEqual(spec.parent, 'spam')
|
||||
|
||||
def test_package_is_package(self):
|
||||
spec = self.machinery.ModuleSpec('spam.eggs', self.loader,
|
||||
is_package=True)
|
||||
|
||||
self.assertEqual(spec.parent, 'spam.eggs')
|
||||
|
||||
# cached
|
||||
|
||||
def test_cached_set(self):
|
||||
before = self.spec.cached
|
||||
self.spec.cached = 'there'
|
||||
after = self.spec.cached
|
||||
|
||||
self.assertIs(before, None)
|
||||
self.assertEqual(after, 'there')
|
||||
|
||||
def test_cached_no_origin(self):
|
||||
spec = self.machinery.ModuleSpec(self.name, self.loader)
|
||||
|
||||
self.assertIs(spec.cached, None)
|
||||
|
||||
def test_cached_with_origin_not_location(self):
|
||||
spec = self.machinery.ModuleSpec(self.name, self.loader,
|
||||
origin=self.path)
|
||||
|
||||
self.assertIs(spec.cached, None)
|
||||
|
||||
def test_cached_source(self):
|
||||
expected = self.util.cache_from_source(self.path)
|
||||
|
||||
self.assertEqual(self.loc_spec.cached, expected)
|
||||
|
||||
def test_cached_source_unknown_suffix(self):
|
||||
self.loc_spec.origin = 'spam.spamspamspam'
|
||||
|
||||
self.assertIs(self.loc_spec.cached, None)
|
||||
|
||||
def test_cached_source_missing_cache_tag(self):
|
||||
original = sys.implementation.cache_tag
|
||||
sys.implementation.cache_tag = None
|
||||
try:
|
||||
cached = self.loc_spec.cached
|
||||
finally:
|
||||
sys.implementation.cache_tag = original
|
||||
|
||||
self.assertIs(cached, None)
|
||||
|
||||
def test_cached_sourceless(self):
|
||||
self.loc_spec.origin = 'spam.pyc'
|
||||
|
||||
self.assertEqual(self.loc_spec.cached, 'spam.pyc')
|
||||
|
||||
|
||||
(Frozen_ModuleSpecTests,
|
||||
Source_ModuleSpecTests
|
||||
) = test_util.test_both(ModuleSpecTests, util=util, machinery=machinery)
|
||||
|
||||
|
||||
class ModuleSpecMethodsTests:
|
||||
|
||||
@property
|
||||
def bootstrap(self):
|
||||
return self.init._bootstrap
|
||||
|
||||
def setUp(self):
|
||||
self.name = 'spam'
|
||||
self.path = 'spam.py'
|
||||
self.cached = self.util.cache_from_source(self.path)
|
||||
self.loader = TestLoader()
|
||||
self.spec = self.machinery.ModuleSpec(self.name, self.loader)
|
||||
self.loc_spec = self.machinery.ModuleSpec(self.name, self.loader,
|
||||
origin=self.path)
|
||||
self.loc_spec._set_fileattr = True
|
||||
|
||||
# exec()
|
||||
|
||||
def test_exec(self):
|
||||
self.spec.loader = NewLoader()
|
||||
module = self.util.module_from_spec(self.spec)
|
||||
sys.modules[self.name] = module
|
||||
self.assertNotHasAttr(module, 'eggs')
|
||||
self.bootstrap._exec(self.spec, module)
|
||||
|
||||
self.assertEqual(module.eggs, 1)
|
||||
|
||||
# load()
|
||||
|
||||
def test_load(self):
|
||||
self.spec.loader = NewLoader()
|
||||
with CleanImport(self.spec.name):
|
||||
loaded = self.bootstrap._load(self.spec)
|
||||
installed = sys.modules[self.spec.name]
|
||||
|
||||
self.assertEqual(loaded.eggs, 1)
|
||||
self.assertIs(loaded, installed)
|
||||
|
||||
def test_load_replaced(self):
|
||||
replacement = object()
|
||||
class ReplacingLoader(TestLoader):
|
||||
def exec_module(self, module):
|
||||
sys.modules[module.__name__] = replacement
|
||||
self.spec.loader = ReplacingLoader()
|
||||
with CleanImport(self.spec.name):
|
||||
loaded = self.bootstrap._load(self.spec)
|
||||
installed = sys.modules[self.spec.name]
|
||||
|
||||
self.assertIs(loaded, replacement)
|
||||
self.assertIs(installed, replacement)
|
||||
|
||||
def test_load_failed(self):
|
||||
class FailedLoader(TestLoader):
|
||||
def exec_module(self, module):
|
||||
raise RuntimeError
|
||||
self.spec.loader = FailedLoader()
|
||||
with CleanImport(self.spec.name):
|
||||
with self.assertRaises(RuntimeError):
|
||||
loaded = self.bootstrap._load(self.spec)
|
||||
self.assertNotIn(self.spec.name, sys.modules)
|
||||
|
||||
def test_load_failed_removed(self):
|
||||
class FailedLoader(TestLoader):
|
||||
def exec_module(self, module):
|
||||
del sys.modules[module.__name__]
|
||||
raise RuntimeError
|
||||
self.spec.loader = FailedLoader()
|
||||
with CleanImport(self.spec.name):
|
||||
with self.assertRaises(RuntimeError):
|
||||
loaded = self.bootstrap._load(self.spec)
|
||||
self.assertNotIn(self.spec.name, sys.modules)
|
||||
|
||||
def test_load_legacy_attributes_immutable(self):
|
||||
module = object()
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", ImportWarning)
|
||||
class ImmutableLoader(TestLoader):
|
||||
def load_module(self, name):
|
||||
sys.modules[name] = module
|
||||
return module
|
||||
self.spec.loader = ImmutableLoader()
|
||||
with CleanImport(self.spec.name):
|
||||
loaded = self.bootstrap._load(self.spec)
|
||||
|
||||
self.assertIs(sys.modules[self.spec.name], module)
|
||||
|
||||
# reload()
|
||||
|
||||
def test_reload(self):
|
||||
self.spec.loader = NewLoader()
|
||||
with CleanImport(self.spec.name):
|
||||
loaded = self.bootstrap._load(self.spec)
|
||||
reloaded = self.bootstrap._exec(self.spec, loaded)
|
||||
installed = sys.modules[self.spec.name]
|
||||
|
||||
self.assertEqual(loaded.eggs, 1)
|
||||
self.assertIs(reloaded, loaded)
|
||||
self.assertIs(installed, loaded)
|
||||
|
||||
def test_reload_modified(self):
|
||||
self.spec.loader = NewLoader()
|
||||
with CleanImport(self.spec.name):
|
||||
loaded = self.bootstrap._load(self.spec)
|
||||
loaded.eggs = 2
|
||||
reloaded = self.bootstrap._exec(self.spec, loaded)
|
||||
|
||||
self.assertEqual(loaded.eggs, 1)
|
||||
self.assertIs(reloaded, loaded)
|
||||
|
||||
def test_reload_extra_attributes(self):
|
||||
self.spec.loader = NewLoader()
|
||||
with CleanImport(self.spec.name):
|
||||
loaded = self.bootstrap._load(self.spec)
|
||||
loaded.available = False
|
||||
reloaded = self.bootstrap._exec(self.spec, loaded)
|
||||
|
||||
self.assertFalse(loaded.available)
|
||||
self.assertIs(reloaded, loaded)
|
||||
|
||||
def test_reload_init_module_attrs(self):
|
||||
self.spec.loader = NewLoader()
|
||||
with CleanImport(self.spec.name):
|
||||
loaded = self.bootstrap._load(self.spec)
|
||||
loaded.__name__ = 'ham'
|
||||
del loaded.__loader__
|
||||
del loaded.__package__
|
||||
del loaded.__spec__
|
||||
self.bootstrap._exec(self.spec, loaded)
|
||||
|
||||
self.assertEqual(loaded.__name__, self.spec.name)
|
||||
self.assertIs(loaded.__loader__, self.spec.loader)
|
||||
self.assertEqual(loaded.__package__, self.spec.parent)
|
||||
self.assertIs(loaded.__spec__, self.spec)
|
||||
self.assertNotHasAttr(loaded, '__path__')
|
||||
self.assertNotHasAttr(loaded, '__file__')
|
||||
self.assertNotHasAttr(loaded, '__cached__')
|
||||
|
||||
|
||||
(Frozen_ModuleSpecMethodsTests,
|
||||
Source_ModuleSpecMethodsTests
|
||||
) = test_util.test_both(ModuleSpecMethodsTests, init=init, util=util,
|
||||
machinery=machinery)
|
||||
|
||||
|
||||
class FactoryTests:
|
||||
|
||||
def setUp(self):
|
||||
self.name = 'spam'
|
||||
self.path = os.path.abspath('spam.py')
|
||||
self.cached = self.util.cache_from_source(self.path)
|
||||
self.loader = TestLoader()
|
||||
self.fileloader = TestLoader(self.path)
|
||||
self.pkgloader = TestLoader(self.path, True)
|
||||
|
||||
# spec_from_loader()
|
||||
|
||||
def test_spec_from_loader_default(self):
|
||||
spec = self.util.spec_from_loader(self.name, self.loader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.loader)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_default_with_bad_is_package(self):
|
||||
class Loader:
|
||||
def is_package(self, name):
|
||||
raise ImportError
|
||||
loader = Loader()
|
||||
spec = self.util.spec_from_loader(self.name, loader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_origin(self):
|
||||
origin = 'somewhere over the rainbow'
|
||||
spec = self.util.spec_from_loader(self.name, self.loader,
|
||||
origin=origin)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.loader)
|
||||
self.assertIs(spec.origin, origin)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_is_package_false(self):
|
||||
spec = self.util.spec_from_loader(self.name, self.loader,
|
||||
is_package=False)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.loader)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_is_package_true(self):
|
||||
spec = self.util.spec_from_loader(self.name, self.loader,
|
||||
is_package=True)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.loader)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertEqual(spec.submodule_search_locations, [])
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_origin_and_is_package(self):
|
||||
origin = 'where the streets have no name'
|
||||
spec = self.util.spec_from_loader(self.name, self.loader,
|
||||
origin=origin, is_package=True)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.loader)
|
||||
self.assertIs(spec.origin, origin)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertEqual(spec.submodule_search_locations, [])
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_is_package_with_loader_false(self):
|
||||
loader = TestLoader(is_package=False)
|
||||
spec = self.util.spec_from_loader(self.name, loader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_is_package_with_loader_true(self):
|
||||
loader = TestLoader(is_package=True)
|
||||
spec = self.util.spec_from_loader(self.name, loader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertIs(spec.origin, None)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertEqual(spec.submodule_search_locations, [])
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertFalse(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_default_with_file_loader(self):
|
||||
spec = self.util.spec_from_loader(self.name, self.fileloader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.fileloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_is_package_false_with_fileloader(self):
|
||||
spec = self.util.spec_from_loader(self.name, self.fileloader,
|
||||
is_package=False)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.fileloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_loader_is_package_true_with_fileloader(self):
|
||||
spec = self.util.spec_from_loader(self.name, self.fileloader,
|
||||
is_package=True)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.fileloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
location = cwd if (cwd := os.getcwd()) != '/' else ''
|
||||
self.assertEqual(spec.submodule_search_locations, [location])
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
# spec_from_file_location()
|
||||
|
||||
def test_spec_from_file_location_default(self):
|
||||
spec = self.util.spec_from_file_location(self.name, self.path)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
# Need to use a circuitous route to get at importlib.machinery to make
|
||||
# sure the same class object is used in the isinstance() check as
|
||||
# would have been used to create the loader.
|
||||
SourceFileLoader = self.util.spec_from_file_location.__globals__['SourceFileLoader']
|
||||
self.assertIsInstance(spec.loader, SourceFileLoader)
|
||||
self.assertEqual(spec.loader.name, self.name)
|
||||
self.assertEqual(spec.loader.path, self.path)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
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)
|
||||
|
||||
self.assertIs(spec, None)
|
||||
|
||||
def test_spec_from_file_location_default_bad_suffix(self):
|
||||
spec = self.util.spec_from_file_location(self.name, 'spam.eggs')
|
||||
|
||||
self.assertIs(spec, None)
|
||||
|
||||
def test_spec_from_file_location_loader_no_location(self):
|
||||
spec = self.util.spec_from_file_location(self.name,
|
||||
loader=self.fileloader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.fileloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_loader_no_location_no_get_filename(self):
|
||||
spec = self.util.spec_from_file_location(self.name,
|
||||
loader=self.loader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.loader)
|
||||
self.assertEqual(spec.origin, '<unknown>')
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_loader_no_location_bad_get_filename(self):
|
||||
class Loader:
|
||||
def get_filename(self, name):
|
||||
raise ImportError
|
||||
loader = Loader()
|
||||
spec = self.util.spec_from_file_location(self.name, loader=loader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertEqual(spec.origin, '<unknown>')
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertIs(spec.cached, None)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_smsl_none(self):
|
||||
spec = self.util.spec_from_file_location(self.name, self.path,
|
||||
loader=self.fileloader,
|
||||
submodule_search_locations=None)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.fileloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_smsl_empty(self):
|
||||
spec = self.util.spec_from_file_location(self.name, self.path,
|
||||
loader=self.fileloader,
|
||||
submodule_search_locations=[])
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.fileloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
location = cwd if (cwd := os.getcwd()) != '/' else ''
|
||||
self.assertEqual(spec.submodule_search_locations, [location])
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_smsl_not_empty(self):
|
||||
spec = self.util.spec_from_file_location(self.name, self.path,
|
||||
loader=self.fileloader,
|
||||
submodule_search_locations=['eggs'])
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.fileloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertEqual(spec.submodule_search_locations, ['eggs'])
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_smsl_default(self):
|
||||
spec = self.util.spec_from_file_location(self.name, self.path,
|
||||
loader=self.pkgloader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.pkgloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
location = cwd if (cwd := os.getcwd()) != '/' else ''
|
||||
self.assertEqual(spec.submodule_search_locations, [location])
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_smsl_default_not_package(self):
|
||||
class Loader:
|
||||
def is_package(self, name):
|
||||
return False
|
||||
loader = Loader()
|
||||
spec = self.util.spec_from_file_location(self.name, self.path,
|
||||
loader=loader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_smsl_default_no_is_package(self):
|
||||
spec = self.util.spec_from_file_location(self.name, self.path,
|
||||
loader=self.fileloader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.fileloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_smsl_default_bad_is_package(self):
|
||||
class Loader:
|
||||
def is_package(self, name):
|
||||
raise ImportError
|
||||
loader = Loader()
|
||||
spec = self.util.spec_from_file_location(self.name, self.path,
|
||||
loader=loader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, loader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
def test_spec_from_file_location_relative_path(self):
|
||||
spec = self.util.spec_from_file_location(self.name,
|
||||
os.path.basename(self.path), loader=self.fileloader)
|
||||
|
||||
self.assertEqual(spec.name, self.name)
|
||||
self.assertEqual(spec.loader, self.fileloader)
|
||||
self.assertEqual(spec.origin, self.path)
|
||||
self.assertIs(spec.loader_state, None)
|
||||
self.assertIs(spec.submodule_search_locations, None)
|
||||
self.assertEqual(spec.cached, self.cached)
|
||||
self.assertTrue(spec.has_location)
|
||||
|
||||
(Frozen_FactoryTests,
|
||||
Source_FactoryTests
|
||||
) = test_util.test_both(FactoryTests, util=util, machinery=machinery)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
270
Dependencies/Python/Lib/test/test_importlib/test_threaded_import.py
vendored
Normal file
270
Dependencies/Python/Lib/test/test_importlib/test_threaded_import.py
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
# This is a variant of the very old (early 90's) file
|
||||
# Demo/threads/bug.py. It simply provokes a number of threads into
|
||||
# trying to import the same module "at the same time".
|
||||
# There are no pleasant failure modes -- most likely is that Python
|
||||
# complains several times about module random having no attribute
|
||||
# randrange, and then Python hangs.
|
||||
|
||||
import _imp as imp
|
||||
import os
|
||||
import importlib
|
||||
import sys
|
||||
import time
|
||||
import shutil
|
||||
import threading
|
||||
import unittest
|
||||
from test import support
|
||||
from test.support import verbose
|
||||
from test.support.import_helper import forget, mock_register_at_fork
|
||||
from test.support.os_helper import (TESTFN, unlink, rmtree)
|
||||
from test.support import script_helper, threading_helper
|
||||
|
||||
threading_helper.requires_working_threading(module=True)
|
||||
|
||||
def task(N, done, done_tasks, errors):
|
||||
try:
|
||||
# We don't use modulefinder but still import it in order to stress
|
||||
# importing of different modules from several threads.
|
||||
if len(done_tasks) % 2:
|
||||
import modulefinder
|
||||
import random
|
||||
else:
|
||||
import random
|
||||
import modulefinder
|
||||
# This will fail if random is not completely initialized
|
||||
x = random.randrange(1, 3)
|
||||
except Exception as e:
|
||||
errors.append(e.with_traceback(None))
|
||||
finally:
|
||||
done_tasks.append(threading.get_ident())
|
||||
finished = len(done_tasks) == N
|
||||
if finished:
|
||||
done.set()
|
||||
|
||||
# Create a circular import structure: A -> C -> B -> D -> A
|
||||
# NOTE: `time` is already loaded and therefore doesn't threaten to deadlock.
|
||||
|
||||
circular_imports_modules = {
|
||||
'A': """if 1:
|
||||
import time
|
||||
time.sleep(%(delay)s)
|
||||
x = 'a'
|
||||
import C
|
||||
""",
|
||||
'B': """if 1:
|
||||
import time
|
||||
time.sleep(%(delay)s)
|
||||
x = 'b'
|
||||
import D
|
||||
""",
|
||||
'C': """import B""",
|
||||
'D': """import A""",
|
||||
}
|
||||
|
||||
class Finder:
|
||||
"""A dummy finder to detect concurrent access to its find_spec()
|
||||
method."""
|
||||
|
||||
def __init__(self):
|
||||
self.numcalls = 0
|
||||
self.x = 0
|
||||
self.lock = threading.Lock()
|
||||
|
||||
def find_spec(self, name, path=None, target=None):
|
||||
# Simulate some thread-unsafe behaviour. If calls to find_spec()
|
||||
# are properly serialized, `x` will end up the same as `numcalls`.
|
||||
# Otherwise not.
|
||||
assert imp.lock_held()
|
||||
with self.lock:
|
||||
self.numcalls += 1
|
||||
x = self.x
|
||||
time.sleep(0.01)
|
||||
self.x = x + 1
|
||||
|
||||
class FlushingFinder:
|
||||
"""A dummy finder which flushes sys.path_importer_cache when it gets
|
||||
called."""
|
||||
|
||||
def find_spec(self, name, path=None, target=None):
|
||||
sys.path_importer_cache.clear()
|
||||
|
||||
|
||||
class ThreadedImportTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.old_random = sys.modules.pop('random', None)
|
||||
|
||||
def tearDown(self):
|
||||
# If the `random` module was already initialized, we restore the
|
||||
# old module at the end so that pickling tests don't fail.
|
||||
# See http://bugs.python.org/issue3657#msg110461
|
||||
if self.old_random is not None:
|
||||
sys.modules['random'] = self.old_random
|
||||
|
||||
@mock_register_at_fork
|
||||
def check_parallel_module_init(self, mock_os):
|
||||
if imp.lock_held():
|
||||
# This triggers on, e.g., from test import autotest.
|
||||
raise unittest.SkipTest("can't run when import lock is held")
|
||||
|
||||
done = threading.Event()
|
||||
for N in (20, 50) * 3:
|
||||
if verbose:
|
||||
print("Trying", N, "threads ...", end=' ')
|
||||
# Make sure that random and modulefinder get reimported freshly
|
||||
for modname in ['random', 'modulefinder']:
|
||||
try:
|
||||
del sys.modules[modname]
|
||||
except KeyError:
|
||||
pass
|
||||
errors = []
|
||||
done_tasks = []
|
||||
done.clear()
|
||||
t0 = time.monotonic()
|
||||
with threading_helper.start_threads(
|
||||
threading.Thread(target=task, args=(N, done, done_tasks, errors,))
|
||||
for i in range(N)):
|
||||
pass
|
||||
completed = done.wait(10 * 60)
|
||||
dt = time.monotonic() - t0
|
||||
if verbose:
|
||||
print("%.1f ms" % (dt*1e3), flush=True, end=" ")
|
||||
dbg_info = 'done: %s/%s' % (len(done_tasks), N)
|
||||
self.assertFalse(errors, dbg_info)
|
||||
self.assertTrue(completed, dbg_info)
|
||||
if verbose:
|
||||
print("OK.")
|
||||
|
||||
def test_parallel_module_init(self):
|
||||
self.check_parallel_module_init()
|
||||
|
||||
def test_parallel_meta_path(self):
|
||||
finder = Finder()
|
||||
sys.meta_path.insert(0, finder)
|
||||
try:
|
||||
self.check_parallel_module_init()
|
||||
self.assertGreater(finder.numcalls, 0)
|
||||
self.assertEqual(finder.x, finder.numcalls)
|
||||
finally:
|
||||
sys.meta_path.remove(finder)
|
||||
|
||||
def test_parallel_path_hooks(self):
|
||||
# Here the Finder instance is only used to check concurrent calls
|
||||
# to path_hook().
|
||||
finder = Finder()
|
||||
# In order for our path hook to be called at each import, we need
|
||||
# to flush the path_importer_cache, which we do by registering a
|
||||
# dedicated meta_path entry.
|
||||
flushing_finder = FlushingFinder()
|
||||
def path_hook(path):
|
||||
finder.find_spec('')
|
||||
raise ImportError
|
||||
sys.path_hooks.insert(0, path_hook)
|
||||
sys.meta_path.append(flushing_finder)
|
||||
try:
|
||||
# Flush the cache a first time
|
||||
flushing_finder.find_spec('')
|
||||
numtests = self.check_parallel_module_init()
|
||||
self.assertGreater(finder.numcalls, 0)
|
||||
self.assertEqual(finder.x, finder.numcalls)
|
||||
finally:
|
||||
sys.meta_path.remove(flushing_finder)
|
||||
sys.path_hooks.remove(path_hook)
|
||||
|
||||
def test_import_hangers(self):
|
||||
# In case this test is run again, make sure the helper module
|
||||
# gets loaded from scratch again.
|
||||
try:
|
||||
del sys.modules['test.test_importlib.threaded_import_hangers']
|
||||
except KeyError:
|
||||
pass
|
||||
import test.test_importlib.threaded_import_hangers
|
||||
self.assertFalse(test.test_importlib.threaded_import_hangers.errors)
|
||||
|
||||
def test_circular_imports(self):
|
||||
# The goal of this test is to exercise implementations of the import
|
||||
# lock which use a per-module lock, rather than a global lock.
|
||||
# In these implementations, there is a possible deadlock with
|
||||
# circular imports, for example:
|
||||
# - thread 1 imports A (grabbing the lock for A) which imports B
|
||||
# - thread 2 imports B (grabbing the lock for B) which imports A
|
||||
# Such implementations should be able to detect such situations and
|
||||
# resolve them one way or the other, without freezing.
|
||||
# NOTE: our test constructs a slightly less trivial import cycle,
|
||||
# in order to better stress the deadlock avoidance mechanism.
|
||||
delay = 0.5
|
||||
os.mkdir(TESTFN)
|
||||
self.addCleanup(shutil.rmtree, TESTFN)
|
||||
sys.path.insert(0, TESTFN)
|
||||
self.addCleanup(sys.path.remove, TESTFN)
|
||||
for name, contents in circular_imports_modules.items():
|
||||
contents = contents % {'delay': delay}
|
||||
with open(os.path.join(TESTFN, name + ".py"), "wb") as f:
|
||||
f.write(contents.encode('utf-8'))
|
||||
self.addCleanup(forget, name)
|
||||
|
||||
importlib.invalidate_caches()
|
||||
results = []
|
||||
def import_ab():
|
||||
import A
|
||||
results.append(getattr(A, 'x', None))
|
||||
def import_ba():
|
||||
import B
|
||||
results.append(getattr(B, 'x', None))
|
||||
t1 = threading.Thread(target=import_ab)
|
||||
t2 = threading.Thread(target=import_ba)
|
||||
t1.start()
|
||||
t2.start()
|
||||
t1.join()
|
||||
t2.join()
|
||||
self.assertEqual(set(results), {'a', 'b'})
|
||||
|
||||
@mock_register_at_fork
|
||||
def test_side_effect_import(self, mock_os):
|
||||
code = """if 1:
|
||||
import threading
|
||||
def target():
|
||||
import random
|
||||
t = threading.Thread(target=target)
|
||||
t.start()
|
||||
t.join()
|
||||
t = None"""
|
||||
sys.path.insert(0, os.curdir)
|
||||
self.addCleanup(sys.path.remove, os.curdir)
|
||||
filename = TESTFN + ".py"
|
||||
with open(filename, "wb") as f:
|
||||
f.write(code.encode('utf-8'))
|
||||
self.addCleanup(unlink, filename)
|
||||
self.addCleanup(forget, TESTFN)
|
||||
self.addCleanup(rmtree, '__pycache__')
|
||||
importlib.invalidate_caches()
|
||||
with threading_helper.wait_threads_exit():
|
||||
__import__(TESTFN)
|
||||
del sys.modules[TESTFN]
|
||||
|
||||
def test_concurrent_futures_circular_import(self):
|
||||
# Regression test for bpo-43515
|
||||
fn = os.path.join(os.path.dirname(__file__),
|
||||
'partial', 'cfimport.py')
|
||||
script_helper.assert_python_ok(fn)
|
||||
|
||||
def test_multiprocessing_pool_circular_import(self):
|
||||
# Regression test for bpo-41567
|
||||
fn = os.path.join(os.path.dirname(__file__),
|
||||
'partial', 'pool_in_threads.py')
|
||||
script_helper.assert_python_ok(fn)
|
||||
|
||||
|
||||
def setUpModule():
|
||||
thread_info = threading_helper.threading_setup()
|
||||
unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info)
|
||||
try:
|
||||
old_switchinterval = sys.getswitchinterval()
|
||||
unittest.addModuleCleanup(sys.setswitchinterval, old_switchinterval)
|
||||
support.setswitchinterval(1e-5)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
811
Dependencies/Python/Lib/test/test_importlib/test_util.py
vendored
Normal file
811
Dependencies/Python/Lib/test/test_importlib/test_util.py
vendored
Normal file
@@ -0,0 +1,811 @@
|
||||
from test.test_importlib import util
|
||||
|
||||
abc = util.import_importlib('importlib.abc')
|
||||
init = util.import_importlib('importlib')
|
||||
machinery = util.import_importlib('importlib.machinery')
|
||||
importlib_util = util.import_importlib('importlib.util')
|
||||
|
||||
import importlib.util
|
||||
from importlib import _bootstrap_external
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
from test import support
|
||||
from test.support import os_helper
|
||||
import textwrap
|
||||
import types
|
||||
import unittest
|
||||
import unittest.mock
|
||||
import warnings
|
||||
|
||||
try:
|
||||
import _testsinglephase
|
||||
except ImportError:
|
||||
_testsinglephase = None
|
||||
try:
|
||||
import _testmultiphase
|
||||
except ImportError:
|
||||
_testmultiphase = None
|
||||
try:
|
||||
import _interpreters
|
||||
except ModuleNotFoundError:
|
||||
_interpreters = None
|
||||
|
||||
|
||||
class DecodeSourceBytesTests:
|
||||
|
||||
source = "string ='ü'"
|
||||
|
||||
def test_ut8_default(self):
|
||||
source_bytes = self.source.encode('utf-8')
|
||||
self.assertEqual(self.util.decode_source(source_bytes), self.source)
|
||||
|
||||
def test_specified_encoding(self):
|
||||
source = '# coding=latin-1\n' + self.source
|
||||
source_bytes = source.encode('latin-1')
|
||||
assert source_bytes != source.encode('utf-8')
|
||||
self.assertEqual(self.util.decode_source(source_bytes), source)
|
||||
|
||||
def test_universal_newlines(self):
|
||||
source = '\r\n'.join([self.source, self.source])
|
||||
source_bytes = source.encode('utf-8')
|
||||
self.assertEqual(self.util.decode_source(source_bytes),
|
||||
'\n'.join([self.source, self.source]))
|
||||
|
||||
|
||||
(Frozen_DecodeSourceBytesTests,
|
||||
Source_DecodeSourceBytesTests
|
||||
) = util.test_both(DecodeSourceBytesTests, util=importlib_util)
|
||||
|
||||
|
||||
class ModuleFromSpecTests:
|
||||
|
||||
def test_no_create_module(self):
|
||||
class Loader:
|
||||
def exec_module(self, module):
|
||||
pass
|
||||
spec = self.machinery.ModuleSpec('test', Loader())
|
||||
with self.assertRaises(ImportError):
|
||||
module = self.util.module_from_spec(spec)
|
||||
|
||||
def test_create_module_returns_None(self):
|
||||
class Loader(self.abc.Loader):
|
||||
def create_module(self, spec):
|
||||
return None
|
||||
spec = self.machinery.ModuleSpec('test', Loader())
|
||||
module = self.util.module_from_spec(spec)
|
||||
self.assertIsInstance(module, types.ModuleType)
|
||||
self.assertEqual(module.__name__, spec.name)
|
||||
|
||||
def test_create_module(self):
|
||||
name = 'already set'
|
||||
class CustomModule(types.ModuleType):
|
||||
pass
|
||||
class Loader(self.abc.Loader):
|
||||
def create_module(self, spec):
|
||||
module = CustomModule(spec.name)
|
||||
module.__name__ = name
|
||||
return module
|
||||
spec = self.machinery.ModuleSpec('test', Loader())
|
||||
module = self.util.module_from_spec(spec)
|
||||
self.assertIsInstance(module, CustomModule)
|
||||
self.assertEqual(module.__name__, name)
|
||||
|
||||
def test___name__(self):
|
||||
spec = self.machinery.ModuleSpec('test', object())
|
||||
module = self.util.module_from_spec(spec)
|
||||
self.assertEqual(module.__name__, spec.name)
|
||||
|
||||
def test___spec__(self):
|
||||
spec = self.machinery.ModuleSpec('test', object())
|
||||
module = self.util.module_from_spec(spec)
|
||||
self.assertEqual(module.__spec__, spec)
|
||||
|
||||
def test___loader__(self):
|
||||
loader = object()
|
||||
spec = self.machinery.ModuleSpec('test', loader)
|
||||
module = self.util.module_from_spec(spec)
|
||||
self.assertIs(module.__loader__, loader)
|
||||
|
||||
def test___package__(self):
|
||||
spec = self.machinery.ModuleSpec('test.pkg', object())
|
||||
module = self.util.module_from_spec(spec)
|
||||
self.assertEqual(module.__package__, spec.parent)
|
||||
|
||||
def test___path__(self):
|
||||
spec = self.machinery.ModuleSpec('test', object(), is_package=True)
|
||||
module = self.util.module_from_spec(spec)
|
||||
self.assertEqual(module.__path__, spec.submodule_search_locations)
|
||||
|
||||
def test___file__(self):
|
||||
spec = self.machinery.ModuleSpec('test', object(), origin='some/path')
|
||||
spec.has_location = True
|
||||
module = self.util.module_from_spec(spec)
|
||||
self.assertEqual(module.__file__, spec.origin)
|
||||
|
||||
def test___cached__(self):
|
||||
spec = self.machinery.ModuleSpec('test', object())
|
||||
spec.cached = 'some/path'
|
||||
spec.has_location = True
|
||||
module = self.util.module_from_spec(spec)
|
||||
self.assertEqual(module.__cached__, spec.cached)
|
||||
|
||||
(Frozen_ModuleFromSpecTests,
|
||||
Source_ModuleFromSpecTests
|
||||
) = util.test_both(ModuleFromSpecTests, abc=abc, machinery=machinery,
|
||||
util=importlib_util)
|
||||
|
||||
|
||||
class ResolveNameTests:
|
||||
|
||||
"""Tests importlib.util.resolve_name()."""
|
||||
|
||||
def test_absolute(self):
|
||||
# bacon
|
||||
self.assertEqual('bacon', self.util.resolve_name('bacon', None))
|
||||
|
||||
def test_absolute_within_package(self):
|
||||
# bacon in spam
|
||||
self.assertEqual('bacon', self.util.resolve_name('bacon', 'spam'))
|
||||
|
||||
def test_no_package(self):
|
||||
# .bacon in ''
|
||||
with self.assertRaises(ImportError):
|
||||
self.util.resolve_name('.bacon', '')
|
||||
|
||||
def test_in_package(self):
|
||||
# .bacon in spam
|
||||
self.assertEqual('spam.eggs.bacon',
|
||||
self.util.resolve_name('.bacon', 'spam.eggs'))
|
||||
|
||||
def test_other_package(self):
|
||||
# ..bacon in spam.bacon
|
||||
self.assertEqual('spam.bacon',
|
||||
self.util.resolve_name('..bacon', 'spam.eggs'))
|
||||
|
||||
def test_escape(self):
|
||||
# ..bacon in spam
|
||||
with self.assertRaises(ImportError):
|
||||
self.util.resolve_name('..bacon', 'spam')
|
||||
|
||||
|
||||
(Frozen_ResolveNameTests,
|
||||
Source_ResolveNameTests
|
||||
) = util.test_both(ResolveNameTests, util=importlib_util)
|
||||
|
||||
|
||||
class FindSpecTests:
|
||||
|
||||
class FakeMetaFinder:
|
||||
@staticmethod
|
||||
def find_spec(name, path=None, target=None): return name, path, target
|
||||
|
||||
def test_sys_modules(self):
|
||||
name = 'some_mod'
|
||||
with util.uncache(name):
|
||||
module = types.ModuleType(name)
|
||||
loader = 'a loader!'
|
||||
spec = self.machinery.ModuleSpec(name, loader)
|
||||
module.__loader__ = loader
|
||||
module.__spec__ = spec
|
||||
sys.modules[name] = module
|
||||
found = self.util.find_spec(name)
|
||||
self.assertEqual(found, spec)
|
||||
|
||||
def test_sys_modules_without___loader__(self):
|
||||
name = 'some_mod'
|
||||
with util.uncache(name):
|
||||
module = types.ModuleType(name)
|
||||
del module.__loader__
|
||||
loader = 'a loader!'
|
||||
spec = self.machinery.ModuleSpec(name, loader)
|
||||
module.__spec__ = spec
|
||||
sys.modules[name] = module
|
||||
found = self.util.find_spec(name)
|
||||
self.assertEqual(found, spec)
|
||||
|
||||
def test_sys_modules_spec_is_None(self):
|
||||
name = 'some_mod'
|
||||
with util.uncache(name):
|
||||
module = types.ModuleType(name)
|
||||
module.__spec__ = None
|
||||
sys.modules[name] = module
|
||||
with self.assertRaises(ValueError):
|
||||
self.util.find_spec(name)
|
||||
|
||||
def test_sys_modules_loader_is_None(self):
|
||||
name = 'some_mod'
|
||||
with util.uncache(name):
|
||||
module = types.ModuleType(name)
|
||||
spec = self.machinery.ModuleSpec(name, None)
|
||||
module.__spec__ = spec
|
||||
sys.modules[name] = module
|
||||
found = self.util.find_spec(name)
|
||||
self.assertEqual(found, spec)
|
||||
|
||||
def test_sys_modules_spec_is_not_set(self):
|
||||
name = 'some_mod'
|
||||
with util.uncache(name):
|
||||
module = types.ModuleType(name)
|
||||
try:
|
||||
del module.__spec__
|
||||
except AttributeError:
|
||||
pass
|
||||
sys.modules[name] = module
|
||||
with self.assertRaises(ValueError):
|
||||
self.util.find_spec(name)
|
||||
|
||||
def test_success(self):
|
||||
name = 'some_mod'
|
||||
with util.uncache(name):
|
||||
with util.import_state(meta_path=[self.FakeMetaFinder]):
|
||||
self.assertEqual((name, None, None),
|
||||
self.util.find_spec(name))
|
||||
|
||||
def test_nothing(self):
|
||||
# None is returned upon failure to find a loader.
|
||||
self.assertIsNone(self.util.find_spec('nevergoingtofindthismodule'))
|
||||
|
||||
def test_find_submodule(self):
|
||||
name = 'spam'
|
||||
subname = 'ham'
|
||||
with util.temp_module(name, pkg=True) as pkg_dir:
|
||||
fullname, _ = util.submodule(name, subname, pkg_dir)
|
||||
spec = self.util.find_spec(fullname)
|
||||
self.assertIsNot(spec, None)
|
||||
self.assertIn(name, sorted(sys.modules))
|
||||
self.assertNotIn(fullname, sorted(sys.modules))
|
||||
# Ensure successive calls behave the same.
|
||||
spec_again = self.util.find_spec(fullname)
|
||||
self.assertEqual(spec_again, spec)
|
||||
|
||||
def test_find_submodule_parent_already_imported(self):
|
||||
name = 'spam'
|
||||
subname = 'ham'
|
||||
with util.temp_module(name, pkg=True) as pkg_dir:
|
||||
self.init.import_module(name)
|
||||
fullname, _ = util.submodule(name, subname, pkg_dir)
|
||||
spec = self.util.find_spec(fullname)
|
||||
self.assertIsNot(spec, None)
|
||||
self.assertIn(name, sorted(sys.modules))
|
||||
self.assertNotIn(fullname, sorted(sys.modules))
|
||||
# Ensure successive calls behave the same.
|
||||
spec_again = self.util.find_spec(fullname)
|
||||
self.assertEqual(spec_again, spec)
|
||||
|
||||
def test_find_relative_module(self):
|
||||
name = 'spam'
|
||||
subname = 'ham'
|
||||
with util.temp_module(name, pkg=True) as pkg_dir:
|
||||
fullname, _ = util.submodule(name, subname, pkg_dir)
|
||||
relname = '.' + subname
|
||||
spec = self.util.find_spec(relname, name)
|
||||
self.assertIsNot(spec, None)
|
||||
self.assertIn(name, sorted(sys.modules))
|
||||
self.assertNotIn(fullname, sorted(sys.modules))
|
||||
# Ensure successive calls behave the same.
|
||||
spec_again = self.util.find_spec(fullname)
|
||||
self.assertEqual(spec_again, spec)
|
||||
|
||||
def test_find_relative_module_missing_package(self):
|
||||
name = 'spam'
|
||||
subname = 'ham'
|
||||
with util.temp_module(name, pkg=True) as pkg_dir:
|
||||
fullname, _ = util.submodule(name, subname, pkg_dir)
|
||||
relname = '.' + subname
|
||||
with self.assertRaises(ImportError):
|
||||
self.util.find_spec(relname)
|
||||
self.assertNotIn(name, sorted(sys.modules))
|
||||
self.assertNotIn(fullname, sorted(sys.modules))
|
||||
|
||||
def test_find_submodule_in_module(self):
|
||||
# ModuleNotFoundError raised when a module is specified as
|
||||
# a parent instead of a package.
|
||||
with self.assertRaises(ModuleNotFoundError):
|
||||
self.util.find_spec('module.name')
|
||||
|
||||
|
||||
(Frozen_FindSpecTests,
|
||||
Source_FindSpecTests
|
||||
) = util.test_both(FindSpecTests, init=init, util=importlib_util,
|
||||
machinery=machinery)
|
||||
|
||||
|
||||
class MagicNumberTests:
|
||||
|
||||
def test_length(self):
|
||||
# Should be 4 bytes.
|
||||
self.assertEqual(len(self.util.MAGIC_NUMBER), 4)
|
||||
|
||||
def test_incorporates_rn(self):
|
||||
# The magic number uses \r\n to come out wrong when splitting on lines.
|
||||
self.assertEndsWith(self.util.MAGIC_NUMBER, b'\r\n')
|
||||
|
||||
|
||||
(Frozen_MagicNumberTests,
|
||||
Source_MagicNumberTests
|
||||
) = util.test_both(MagicNumberTests, util=importlib_util)
|
||||
|
||||
|
||||
class PEP3147Tests:
|
||||
|
||||
"""Tests of PEP 3147-related functions: cache_from_source and source_from_cache."""
|
||||
|
||||
tag = sys.implementation.cache_tag
|
||||
|
||||
@unittest.skipIf(sys.implementation.cache_tag is 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(self.util.cache_from_source(path, optimization=''),
|
||||
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):
|
||||
self.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(self.util.cache_from_source(path, optimization=''),
|
||||
expect)
|
||||
|
||||
def test_cache_from_source_debug_override(self):
|
||||
# Given the path to a .py file, return the path to its PEP 3147/PEP 488
|
||||
# defined .pyc file (i.e. under __pycache__).
|
||||
path = os.path.join('foo', 'bar', 'baz', 'qux.py')
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore')
|
||||
self.assertEqual(self.util.cache_from_source(path, False),
|
||||
self.util.cache_from_source(path, optimization=1))
|
||||
self.assertEqual(self.util.cache_from_source(path, True),
|
||||
self.util.cache_from_source(path, optimization=''))
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('error')
|
||||
with self.assertRaises(DeprecationWarning):
|
||||
self.util.cache_from_source(path, False)
|
||||
with self.assertRaises(DeprecationWarning):
|
||||
self.util.cache_from_source(path, True)
|
||||
|
||||
def test_cache_from_source_cwd(self):
|
||||
path = 'foo.py'
|
||||
expect = os.path.join('__pycache__', 'foo.{}.pyc'.format(self.tag))
|
||||
self.assertEqual(self.util.cache_from_source(path, optimization=''),
|
||||
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')
|
||||
# However if the bool-ishness can't be determined, the exception
|
||||
# propagates.
|
||||
class Bearish:
|
||||
def __bool__(self): raise RuntimeError
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore')
|
||||
self.assertEqual(self.util.cache_from_source(path, []),
|
||||
self.util.cache_from_source(path, optimization=1))
|
||||
self.assertEqual(self.util.cache_from_source(path, [17]),
|
||||
self.util.cache_from_source(path, optimization=''))
|
||||
with self.assertRaises(RuntimeError):
|
||||
self.util.cache_from_source('/foo/bar/baz.py', Bearish())
|
||||
|
||||
|
||||
def test_cache_from_source_optimization_empty_string(self):
|
||||
# Setting 'optimization' to '' leads to no optimization tag (PEP 488).
|
||||
path = 'foo.py'
|
||||
expect = os.path.join('__pycache__', 'foo.{}.pyc'.format(self.tag))
|
||||
self.assertEqual(self.util.cache_from_source(path, optimization=''),
|
||||
expect)
|
||||
|
||||
def test_cache_from_source_optimization_None(self):
|
||||
# Setting 'optimization' to None uses the interpreter's optimization.
|
||||
# (PEP 488)
|
||||
path = 'foo.py'
|
||||
optimization_level = sys.flags.optimize
|
||||
almost_expect = os.path.join('__pycache__', 'foo.{}'.format(self.tag))
|
||||
if optimization_level == 0:
|
||||
expect = almost_expect + '.pyc'
|
||||
elif optimization_level <= 2:
|
||||
expect = almost_expect + '.opt-{}.pyc'.format(optimization_level)
|
||||
else:
|
||||
msg = '{!r} is a non-standard optimization level'.format(optimization_level)
|
||||
self.skipTest(msg)
|
||||
self.assertEqual(self.util.cache_from_source(path, optimization=None),
|
||||
expect)
|
||||
|
||||
def test_cache_from_source_optimization_set(self):
|
||||
# The 'optimization' parameter accepts anything that has a string repr
|
||||
# that passes str.alnum().
|
||||
path = 'foo.py'
|
||||
valid_characters = string.ascii_letters + string.digits
|
||||
almost_expect = os.path.join('__pycache__', 'foo.{}'.format(self.tag))
|
||||
got = self.util.cache_from_source(path, optimization=valid_characters)
|
||||
# Test all valid characters are accepted.
|
||||
self.assertEqual(got,
|
||||
almost_expect + '.opt-{}.pyc'.format(valid_characters))
|
||||
# str() should be called on argument.
|
||||
self.assertEqual(self.util.cache_from_source(path, optimization=42),
|
||||
almost_expect + '.opt-42.pyc')
|
||||
# Invalid characters raise ValueError.
|
||||
with self.assertRaises(ValueError):
|
||||
self.util.cache_from_source(path, optimization='path/is/bad')
|
||||
|
||||
def test_cache_from_source_debug_override_optimization_both_set(self):
|
||||
# Can only set one of the optimization-related parameters.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore')
|
||||
with self.assertRaises(TypeError):
|
||||
self.util.cache_from_source('foo.py', False, optimization='')
|
||||
|
||||
@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(
|
||||
self.util.cache_from_source('\\foo\\bar\\baz/qux.py', optimization=''),
|
||||
'\\foo\\bar\\baz\\__pycache__\\qux.{}.pyc'.format(self.tag))
|
||||
|
||||
@unittest.skipIf(sys.implementation.cache_tag is None,
|
||||
'requires sys.implementation.cache_tag not be None')
|
||||
def test_cache_from_source_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.skipIf(sys.implementation.cache_tag is 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(self.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):
|
||||
self.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, self.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, self.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, self.util.source_from_cache, '__pycache__/foo.pyc')
|
||||
|
||||
def test_source_from_cache_too_many_dots(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.util.source_from_cache(
|
||||
'__pycache__/foo.cpython-32.opt-1.foo.pyc')
|
||||
|
||||
def test_source_from_cache_not_opt(self):
|
||||
# Non-`opt-` path component -> ValueError
|
||||
self.assertRaises(
|
||||
ValueError, self.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, self.util.source_from_cache,
|
||||
'/foo/bar/foo.cpython-32.foo.pyc')
|
||||
|
||||
def test_source_from_cache_optimized_bytecode(self):
|
||||
# Optimized bytecode is not an issue.
|
||||
path = os.path.join('__pycache__', 'foo.{}.opt-1.pyc'.format(self.tag))
|
||||
self.assertEqual(self.util.source_from_cache(path), 'foo.py')
|
||||
|
||||
def test_source_from_cache_missing_optimization(self):
|
||||
# An empty optimization level is a no-no.
|
||||
path = os.path.join('__pycache__', 'foo.{}.opt-.pyc'.format(self.tag))
|
||||
with self.assertRaises(ValueError):
|
||||
self.util.source_from_cache(path)
|
||||
|
||||
@unittest.skipIf(sys.implementation.cache_tag is 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)
|
||||
|
||||
@unittest.skipIf(sys.implementation.cache_tag is None,
|
||||
'requires sys.implementation.cache_tag to not be None')
|
||||
def test_cache_from_source_respects_pycache_prefix(self):
|
||||
# If pycache_prefix is set, cache_from_source will return a bytecode
|
||||
# path inside that directory (in a subdirectory mirroring the .py file's
|
||||
# path) rather than in a __pycache__ dir next to the py file.
|
||||
pycache_prefixes = [
|
||||
os.path.join(os.path.sep, 'tmp', 'bytecode'),
|
||||
os.path.join(os.path.sep, 'tmp', '\u2603'), # non-ASCII in path!
|
||||
os.path.join(os.path.sep, 'tmp', 'trailing-slash') + os.path.sep,
|
||||
]
|
||||
drive = ''
|
||||
if os.name == 'nt':
|
||||
drive = 'C:'
|
||||
pycache_prefixes = [
|
||||
f'{drive}{prefix}' for prefix in pycache_prefixes]
|
||||
pycache_prefixes += [r'\\?\C:\foo', r'\\localhost\c$\bar']
|
||||
for pycache_prefix in pycache_prefixes:
|
||||
with self.subTest(path=pycache_prefix):
|
||||
path = drive + os.path.join(
|
||||
os.path.sep, 'foo', 'bar', 'baz', 'qux.py')
|
||||
expect = os.path.join(
|
||||
pycache_prefix, 'foo', 'bar', 'baz',
|
||||
'qux.{}.pyc'.format(self.tag))
|
||||
with util.temporary_pycache_prefix(pycache_prefix):
|
||||
self.assertEqual(
|
||||
self.util.cache_from_source(path, optimization=''),
|
||||
expect)
|
||||
|
||||
@unittest.skipIf(sys.implementation.cache_tag is None,
|
||||
'requires sys.implementation.cache_tag to not be None')
|
||||
def test_cache_from_source_respects_pycache_prefix_relative(self):
|
||||
# If the .py path we are given is relative, we will resolve to an
|
||||
# absolute path before prefixing with pycache_prefix, to avoid any
|
||||
# possible ambiguity.
|
||||
pycache_prefix = os.path.join(os.path.sep, 'tmp', 'bytecode')
|
||||
path = os.path.join('foo', 'bar', 'baz', 'qux.py')
|
||||
root = os.path.splitdrive(os.getcwd())[0] + os.path.sep
|
||||
expect = os.path.join(
|
||||
pycache_prefix,
|
||||
os.path.relpath(os.getcwd(), root),
|
||||
'foo', 'bar', 'baz', f'qux.{self.tag}.pyc')
|
||||
with util.temporary_pycache_prefix(pycache_prefix):
|
||||
self.assertEqual(
|
||||
self.util.cache_from_source(path, optimization=''),
|
||||
os.path.normpath(expect))
|
||||
|
||||
@unittest.skipIf(sys.implementation.cache_tag is None,
|
||||
'requires sys.implementation.cache_tag to not be None')
|
||||
def test_source_from_cache_inside_pycache_prefix(self):
|
||||
# If pycache_prefix is set and the cache path we get is inside it,
|
||||
# we return an absolute path to the py file based on the remainder of
|
||||
# the path within pycache_prefix.
|
||||
pycache_prefix = os.path.join(os.path.sep, 'tmp', 'bytecode')
|
||||
path = os.path.join(pycache_prefix, 'foo', 'bar', 'baz',
|
||||
f'qux.{self.tag}.pyc')
|
||||
expect = os.path.join(os.path.sep, 'foo', 'bar', 'baz', 'qux.py')
|
||||
with util.temporary_pycache_prefix(pycache_prefix):
|
||||
self.assertEqual(self.util.source_from_cache(path), expect)
|
||||
|
||||
@unittest.skipIf(sys.implementation.cache_tag is None,
|
||||
'requires sys.implementation.cache_tag to not be None')
|
||||
def test_source_from_cache_outside_pycache_prefix(self):
|
||||
# If pycache_prefix is set but the cache path we get is not inside
|
||||
# it, just ignore it and handle the cache path according to the default
|
||||
# behavior.
|
||||
pycache_prefix = os.path.join(os.path.sep, 'tmp', 'bytecode')
|
||||
path = os.path.join('foo', 'bar', 'baz', '__pycache__',
|
||||
f'qux.{self.tag}.pyc')
|
||||
expect = os.path.join('foo', 'bar', 'baz', 'qux.py')
|
||||
with util.temporary_pycache_prefix(pycache_prefix):
|
||||
self.assertEqual(self.util.source_from_cache(path), expect)
|
||||
|
||||
|
||||
(Frozen_PEP3147Tests,
|
||||
Source_PEP3147Tests
|
||||
) = util.test_both(PEP3147Tests, util=importlib_util)
|
||||
|
||||
|
||||
class MagicNumberTests(unittest.TestCase):
|
||||
"""
|
||||
Test release compatibility issues relating to importlib
|
||||
"""
|
||||
@unittest.skipUnless(
|
||||
sys.version_info.releaselevel in ('candidate', 'final'),
|
||||
'only applies to candidate or final python release levels'
|
||||
)
|
||||
def test_magic_number(self):
|
||||
# Each python minor release should generally have a MAGIC_NUMBER
|
||||
# that does not change once the release reaches candidate status.
|
||||
|
||||
# Once a release reaches candidate status, the value of the constant
|
||||
# EXPECTED_MAGIC_NUMBER in this test should be changed.
|
||||
# This test will then check that the actual MAGIC_NUMBER matches
|
||||
# the expected value for the release.
|
||||
|
||||
# In exceptional cases, it may be required to change the MAGIC_NUMBER
|
||||
# for a maintenance release. In this case the change should be
|
||||
# discussed in python-dev. If a change is required, community
|
||||
# stakeholders such as OS package maintainers must be notified
|
||||
# in advance. Such exceptional releases will then require an
|
||||
# adjustment to this test case.
|
||||
EXPECTED_MAGIC_NUMBER = 3571
|
||||
actual = int.from_bytes(importlib.util.MAGIC_NUMBER[:2], 'little')
|
||||
|
||||
msg = (
|
||||
"To avoid breaking backwards compatibility with cached bytecode "
|
||||
"files that can't be automatically regenerated by the current "
|
||||
"user, candidate and final releases require the current "
|
||||
"importlib.util.MAGIC_NUMBER to match the expected "
|
||||
"magic number in this test. Set the expected "
|
||||
"magic number in this test to the current MAGIC_NUMBER to "
|
||||
"continue with the release.\n\n"
|
||||
"Changing the MAGIC_NUMBER for a maintenance release "
|
||||
"requires discussion in python-dev and notification of "
|
||||
"community stakeholders."
|
||||
)
|
||||
self.assertEqual(EXPECTED_MAGIC_NUMBER, actual, msg)
|
||||
|
||||
|
||||
@unittest.skipIf(_interpreters is None, 'subinterpreters required')
|
||||
class IncompatibleExtensionModuleRestrictionsTests(unittest.TestCase):
|
||||
|
||||
def run_with_own_gil(self, script):
|
||||
interpid = _interpreters.create('isolated')
|
||||
def ensure_destroyed():
|
||||
try:
|
||||
_interpreters.destroy(interpid)
|
||||
except _interpreters.InterpreterNotFoundError:
|
||||
pass
|
||||
self.addCleanup(ensure_destroyed)
|
||||
excsnap = _interpreters.exec(interpid, script)
|
||||
if excsnap is not None:
|
||||
if excsnap.type.__name__ == 'ImportError':
|
||||
raise ImportError(excsnap.msg)
|
||||
|
||||
def run_with_shared_gil(self, script):
|
||||
interpid = _interpreters.create('legacy')
|
||||
def ensure_destroyed():
|
||||
try:
|
||||
_interpreters.destroy(interpid)
|
||||
except _interpreters.InterpreterNotFoundError:
|
||||
pass
|
||||
self.addCleanup(ensure_destroyed)
|
||||
excsnap = _interpreters.exec(interpid, script)
|
||||
if excsnap is not None:
|
||||
if excsnap.type.__name__ == 'ImportError':
|
||||
raise ImportError(excsnap.msg)
|
||||
|
||||
@unittest.skipIf(_testsinglephase is None, "test requires _testsinglephase module")
|
||||
# gh-117649: single-phase init modules are not currently supported in
|
||||
# subinterpreters in the free-threaded build
|
||||
@support.expected_failure_if_gil_disabled()
|
||||
def test_single_phase_init_module(self):
|
||||
script = textwrap.dedent('''
|
||||
from importlib.util import _incompatible_extension_module_restrictions
|
||||
with _incompatible_extension_module_restrictions(disable_check=True):
|
||||
import _testsinglephase
|
||||
''')
|
||||
with self.subTest('check disabled, shared GIL'):
|
||||
self.run_with_shared_gil(script)
|
||||
with self.subTest('check disabled, per-interpreter GIL'):
|
||||
self.run_with_own_gil(script)
|
||||
|
||||
script = textwrap.dedent(f'''
|
||||
from importlib.util import _incompatible_extension_module_restrictions
|
||||
with _incompatible_extension_module_restrictions(disable_check=False):
|
||||
import _testsinglephase
|
||||
''')
|
||||
with self.subTest('check enabled, shared GIL'):
|
||||
with self.assertRaises(ImportError):
|
||||
self.run_with_shared_gil(script)
|
||||
with self.subTest('check enabled, per-interpreter GIL'):
|
||||
with self.assertRaises(ImportError):
|
||||
self.run_with_own_gil(script)
|
||||
|
||||
@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
|
||||
@support.requires_gil_enabled("gh-117649: not supported in free-threaded build")
|
||||
def test_incomplete_multi_phase_init_module(self):
|
||||
# Apple extensions must be distributed as frameworks. This requires
|
||||
# a specialist loader.
|
||||
if support.is_apple_mobile:
|
||||
loader = "AppleFrameworkLoader"
|
||||
else:
|
||||
loader = "ExtensionFileLoader"
|
||||
|
||||
prescript = textwrap.dedent(f'''
|
||||
from importlib.util import spec_from_loader, module_from_spec
|
||||
from importlib.machinery import {loader}
|
||||
|
||||
name = '_test_shared_gil_only'
|
||||
filename = {_testmultiphase.__file__!r}
|
||||
loader = {loader}(name, filename)
|
||||
spec = spec_from_loader(name, loader)
|
||||
|
||||
''')
|
||||
|
||||
script = prescript + textwrap.dedent('''
|
||||
from importlib.util import _incompatible_extension_module_restrictions
|
||||
with _incompatible_extension_module_restrictions(disable_check=True):
|
||||
module = module_from_spec(spec)
|
||||
loader.exec_module(module)
|
||||
''')
|
||||
with self.subTest('check disabled, shared GIL'):
|
||||
self.run_with_shared_gil(script)
|
||||
with self.subTest('check disabled, per-interpreter GIL'):
|
||||
self.run_with_own_gil(script)
|
||||
|
||||
script = prescript + textwrap.dedent('''
|
||||
from importlib.util import _incompatible_extension_module_restrictions
|
||||
with _incompatible_extension_module_restrictions(disable_check=False):
|
||||
module = module_from_spec(spec)
|
||||
loader.exec_module(module)
|
||||
''')
|
||||
with self.subTest('check enabled, shared GIL'):
|
||||
self.run_with_shared_gil(script)
|
||||
with self.subTest('check enabled, per-interpreter GIL'):
|
||||
with self.assertRaises(ImportError):
|
||||
self.run_with_own_gil(script)
|
||||
|
||||
@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
|
||||
def test_complete_multi_phase_init_module(self):
|
||||
script = textwrap.dedent('''
|
||||
from importlib.util import _incompatible_extension_module_restrictions
|
||||
with _incompatible_extension_module_restrictions(disable_check=True):
|
||||
import _testmultiphase
|
||||
''')
|
||||
with self.subTest('check disabled, shared GIL'):
|
||||
self.run_with_shared_gil(script)
|
||||
with self.subTest('check disabled, per-interpreter GIL'):
|
||||
self.run_with_own_gil(script)
|
||||
|
||||
script = textwrap.dedent(f'''
|
||||
from importlib.util import _incompatible_extension_module_restrictions
|
||||
with _incompatible_extension_module_restrictions(disable_check=False):
|
||||
import _testmultiphase
|
||||
''')
|
||||
with self.subTest('check enabled, shared GIL'):
|
||||
self.run_with_shared_gil(script)
|
||||
with self.subTest('check enabled, per-interpreter GIL'):
|
||||
self.run_with_own_gil(script)
|
||||
|
||||
|
||||
class MiscTests(unittest.TestCase):
|
||||
def test_atomic_write_should_notice_incomplete_writes(self):
|
||||
import _pyio
|
||||
|
||||
oldwrite = os.write
|
||||
seen_write = False
|
||||
|
||||
truncate_at_length = 100
|
||||
|
||||
# Emulate an os.write that only writes partial data.
|
||||
def write(fd, data):
|
||||
nonlocal seen_write
|
||||
seen_write = True
|
||||
return oldwrite(fd, data[:truncate_at_length])
|
||||
|
||||
# Need to patch _io to be _pyio, so that io.FileIO is affected by the
|
||||
# os.write patch.
|
||||
with (support.swap_attr(_bootstrap_external, '_io', _pyio),
|
||||
support.swap_attr(os, 'write', write)):
|
||||
with self.assertRaises(OSError):
|
||||
# Make sure we write something longer than the point where we
|
||||
# truncate.
|
||||
content = b'x' * (truncate_at_length * 2)
|
||||
_bootstrap_external._write_atomic(os_helper.TESTFN, content)
|
||||
assert seen_write
|
||||
|
||||
with self.assertRaises(OSError):
|
||||
os.stat(support.os_helper.TESTFN) # Check that the file did not get written.
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
181
Dependencies/Python/Lib/test/test_importlib/test_windows.py
vendored
Normal file
181
Dependencies/Python/Lib/test/test_importlib/test_windows.py
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
from test.test_importlib import util as test_util
|
||||
machinery = test_util.import_importlib('importlib.machinery')
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import unittest
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
from contextlib import contextmanager
|
||||
from test.test_importlib.util import temp_module
|
||||
|
||||
import_helper.import_module('winreg', required_on=['win'])
|
||||
from winreg import (
|
||||
CreateKey, HKEY_CURRENT_USER,
|
||||
SetValue, REG_SZ, KEY_ALL_ACCESS,
|
||||
EnumKey, CloseKey, DeleteKey, OpenKey
|
||||
)
|
||||
|
||||
def get_platform():
|
||||
# Port of distutils.util.get_platform().
|
||||
TARGET_TO_PLAT = {
|
||||
'x86' : 'win32',
|
||||
'x64' : 'win-amd64',
|
||||
'arm' : 'win-arm32',
|
||||
}
|
||||
if ('VSCMD_ARG_TGT_ARCH' in os.environ and
|
||||
os.environ['VSCMD_ARG_TGT_ARCH'] in TARGET_TO_PLAT):
|
||||
return TARGET_TO_PLAT[os.environ['VSCMD_ARG_TGT_ARCH']]
|
||||
elif 'amd64' in sys.version.lower():
|
||||
return 'win-amd64'
|
||||
elif '(arm)' in sys.version.lower():
|
||||
return 'win-arm32'
|
||||
elif '(arm64)' in sys.version.lower():
|
||||
return 'win-arm64'
|
||||
else:
|
||||
return sys.platform
|
||||
|
||||
def delete_registry_tree(root, subkey):
|
||||
try:
|
||||
hkey = OpenKey(root, subkey, access=KEY_ALL_ACCESS)
|
||||
except OSError:
|
||||
# subkey does not exist
|
||||
return
|
||||
while True:
|
||||
try:
|
||||
subsubkey = EnumKey(hkey, 0)
|
||||
except OSError:
|
||||
# no more subkeys
|
||||
break
|
||||
delete_registry_tree(hkey, subsubkey)
|
||||
CloseKey(hkey)
|
||||
DeleteKey(root, subkey)
|
||||
|
||||
@contextmanager
|
||||
def setup_module(machinery, name, path=None):
|
||||
if machinery.WindowsRegistryFinder.DEBUG_BUILD:
|
||||
root = machinery.WindowsRegistryFinder.REGISTRY_KEY_DEBUG
|
||||
else:
|
||||
root = machinery.WindowsRegistryFinder.REGISTRY_KEY
|
||||
key = root.format(fullname=name,
|
||||
sys_version='%d.%d' % sys.version_info[:2])
|
||||
base_key = "Software\\Python\\PythonCore\\{}.{}".format(
|
||||
sys.version_info.major, sys.version_info.minor)
|
||||
assert key.casefold().startswith(base_key.casefold()), (
|
||||
"expected key '{}' to start with '{}'".format(key, base_key))
|
||||
try:
|
||||
with temp_module(name, "a = 1") as location:
|
||||
try:
|
||||
OpenKey(HKEY_CURRENT_USER, base_key)
|
||||
if machinery.WindowsRegistryFinder.DEBUG_BUILD:
|
||||
delete_key = os.path.dirname(key)
|
||||
else:
|
||||
delete_key = key
|
||||
except OSError:
|
||||
delete_key = base_key
|
||||
subkey = CreateKey(HKEY_CURRENT_USER, key)
|
||||
if path is None:
|
||||
path = location + ".py"
|
||||
SetValue(subkey, "", REG_SZ, path)
|
||||
yield
|
||||
finally:
|
||||
if delete_key:
|
||||
delete_registry_tree(HKEY_CURRENT_USER, delete_key)
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform.startswith('win'), 'requires Windows')
|
||||
class WindowsRegistryFinderTests:
|
||||
# The module name is process-specific, allowing for
|
||||
# simultaneous runs of the same test on a single machine.
|
||||
test_module = "spamham{}".format(os.getpid())
|
||||
|
||||
def test_find_spec_missing(self):
|
||||
spec = self.machinery.WindowsRegistryFinder.find_spec('spam')
|
||||
self.assertIsNone(spec)
|
||||
|
||||
def test_module_found(self):
|
||||
with setup_module(self.machinery, self.test_module):
|
||||
spec = self.machinery.WindowsRegistryFinder.find_spec(self.test_module)
|
||||
self.assertIsNotNone(spec)
|
||||
|
||||
def test_module_not_found(self):
|
||||
with setup_module(self.machinery, self.test_module, path="."):
|
||||
spec = self.machinery.WindowsRegistryFinder.find_spec(self.test_module)
|
||||
self.assertIsNone(spec)
|
||||
|
||||
(Frozen_WindowsRegistryFinderTests,
|
||||
Source_WindowsRegistryFinderTests
|
||||
) = test_util.test_both(WindowsRegistryFinderTests, machinery=machinery)
|
||||
|
||||
@unittest.skipUnless(sys.platform.startswith('win'), 'requires Windows')
|
||||
class WindowsExtensionSuffixTests:
|
||||
def test_tagged_suffix(self):
|
||||
suffixes = self.machinery.EXTENSION_SUFFIXES
|
||||
abi_flags = "t" if support.Py_GIL_DISABLED else ""
|
||||
ver = sys.version_info
|
||||
platform = re.sub('[^a-zA-Z0-9]', '_', get_platform())
|
||||
expected_tag = f".cp{ver.major}{ver.minor}{abi_flags}-{platform}.pyd"
|
||||
try:
|
||||
untagged_i = suffixes.index(".pyd")
|
||||
except ValueError:
|
||||
untagged_i = suffixes.index("_d.pyd")
|
||||
expected_tag = "_d" + expected_tag
|
||||
|
||||
self.assertIn(expected_tag, suffixes)
|
||||
|
||||
# Ensure the tags are in the correct order.
|
||||
tagged_i = suffixes.index(expected_tag)
|
||||
self.assertLess(tagged_i, untagged_i)
|
||||
|
||||
(Frozen_WindowsExtensionSuffixTests,
|
||||
Source_WindowsExtensionSuffixTests
|
||||
) = test_util.test_both(WindowsExtensionSuffixTests, machinery=machinery)
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform.startswith('win'), 'requires Windows')
|
||||
class WindowsBootstrapPathTests(unittest.TestCase):
|
||||
def check_join(self, expected, *inputs):
|
||||
from importlib._bootstrap_external import _path_join
|
||||
actual = _path_join(*inputs)
|
||||
if expected.casefold() == actual.casefold():
|
||||
return
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_path_join(self):
|
||||
self.check_join(r"C:\A\B", "C:\\", "A", "B")
|
||||
self.check_join(r"C:\A\B", "D:\\", "D", "C:\\", "A", "B")
|
||||
self.check_join(r"C:\A\B", "C:\\", "A", "C:B")
|
||||
self.check_join(r"C:\A\B", "C:\\", "A\\B")
|
||||
self.check_join(r"C:\A\B", r"C:\A\B")
|
||||
|
||||
self.check_join("D:A", r"D:", "A")
|
||||
self.check_join("D:A", r"C:\B\C", "D:", "A")
|
||||
self.check_join("D:A", r"C:\B\C", r"D:A")
|
||||
|
||||
self.check_join(r"A\B\C", "A", "B", "C")
|
||||
self.check_join(r"A\B\C", "A", r"B\C")
|
||||
self.check_join(r"A\B/C", "A", "B/C")
|
||||
self.check_join(r"A\B\C", "A/", "B\\", "C")
|
||||
|
||||
# Dots are not normalised by this function
|
||||
self.check_join(r"A\../C", "A", "../C")
|
||||
self.check_join(r"A.\.\B", "A.", ".", "B")
|
||||
|
||||
self.check_join(r"\\Server\Share\A\B\C", r"\\Server\Share", "A", "B", "C")
|
||||
self.check_join(r"\\Server\Share\A\B\C", r"\\Server\Share", "D", r"\A", "B", "C")
|
||||
self.check_join(r"\\Server\Share\A\B\C", r"\\Server2\Share2", "D",
|
||||
r"\\Server\Share", "A", "B", "C")
|
||||
self.check_join(r"\\Server\Share\A\B\C", r"\\Server", r"\Share", "A", "B", "C")
|
||||
self.check_join(r"\\Server\Share", r"\\Server\Share")
|
||||
self.check_join(r"\\Server\Share\\", r"\\Server\Share\\")
|
||||
|
||||
# Handle edge cases with empty segments
|
||||
self.check_join("C:\\A", "C:/A", "")
|
||||
self.check_join("C:\\", "C:/", "")
|
||||
self.check_join("C:", "C:", "")
|
||||
self.check_join("//Server/Share\\", "//Server/Share/", "")
|
||||
self.check_join("//Server/Share\\", "//Server/Share", "")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
45
Dependencies/Python/Lib/test/test_importlib/threaded_import_hangers.py
vendored
Normal file
45
Dependencies/Python/Lib/test/test_importlib/threaded_import_hangers.py
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
# This is a helper module for test_threaded_import. The test imports this
|
||||
# module, and this module tries to run various Python library functions in
|
||||
# their own thread, as a side effect of being imported. If the spawned
|
||||
# thread doesn't complete in TIMEOUT seconds, an "appeared to hang" message
|
||||
# is appended to the module-global `errors` list. That list remains empty
|
||||
# if (and only if) all functions tested complete.
|
||||
|
||||
TIMEOUT = 10
|
||||
|
||||
import threading
|
||||
|
||||
import tempfile
|
||||
import os.path
|
||||
|
||||
errors = []
|
||||
|
||||
# This class merely runs a function in its own thread T. The thread importing
|
||||
# this module holds the import lock, so if the function called by T tries
|
||||
# to do its own imports it will block waiting for this module's import
|
||||
# to complete.
|
||||
class Worker(threading.Thread):
|
||||
def __init__(self, function, args):
|
||||
threading.Thread.__init__(self)
|
||||
self.function = function
|
||||
self.args = args
|
||||
|
||||
def run(self):
|
||||
self.function(*self.args)
|
||||
|
||||
for name, func, args in [
|
||||
# Bug 147376: TemporaryFile hung on Windows, starting in Python 2.4.
|
||||
("tempfile.TemporaryFile", lambda: tempfile.TemporaryFile().close(), ()),
|
||||
|
||||
# The real cause for bug 147376: ntpath.abspath() caused the hang.
|
||||
("os.path.abspath", os.path.abspath, ('.',)),
|
||||
]:
|
||||
|
||||
try:
|
||||
t = Worker(func, args)
|
||||
t.start()
|
||||
t.join(TIMEOUT)
|
||||
if t.is_alive():
|
||||
errors.append("%s appeared to hang" % name)
|
||||
finally:
|
||||
del t
|
||||
403
Dependencies/Python/Lib/test/test_importlib/util.py
vendored
Normal file
403
Dependencies/Python/Lib/test/test_importlib/util.py
vendored
Normal file
@@ -0,0 +1,403 @@
|
||||
import builtins
|
||||
import contextlib
|
||||
import errno
|
||||
import functools
|
||||
from importlib import machinery, util, invalidate_caches
|
||||
import marshal
|
||||
import os
|
||||
import os.path
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
from test.support import is_apple_mobile
|
||||
from test.support import os_helper
|
||||
from test.support.testcase import ExtraAssertions
|
||||
import unittest
|
||||
import sys
|
||||
import tempfile
|
||||
import types
|
||||
|
||||
_testsinglephase = import_helper.import_module("_testsinglephase")
|
||||
|
||||
|
||||
BUILTINS = types.SimpleNamespace()
|
||||
BUILTINS.good_name = None
|
||||
BUILTINS.bad_name = None
|
||||
if 'errno' in sys.builtin_module_names:
|
||||
BUILTINS.good_name = 'errno'
|
||||
if 'importlib' not in sys.builtin_module_names:
|
||||
BUILTINS.bad_name = 'importlib'
|
||||
|
||||
if support.is_wasi:
|
||||
# dlopen() is a shim for WASI as of WASI SDK which fails by default.
|
||||
# We don't provide an implementation, so tests will fail.
|
||||
# But we also don't want to turn off dynamic loading for those that provide
|
||||
# a working implementation.
|
||||
def _extension_details():
|
||||
global EXTENSIONS
|
||||
EXTENSIONS = None
|
||||
else:
|
||||
EXTENSIONS = types.SimpleNamespace()
|
||||
EXTENSIONS.path = None
|
||||
EXTENSIONS.ext = None
|
||||
EXTENSIONS.filename = None
|
||||
EXTENSIONS.file_path = None
|
||||
EXTENSIONS.name = '_testsinglephase'
|
||||
|
||||
def _extension_details():
|
||||
global EXTENSIONS
|
||||
for path in sys.path:
|
||||
for ext in machinery.EXTENSION_SUFFIXES:
|
||||
# Apple mobile platforms mechanically load .so files,
|
||||
# but the findable files are labelled .fwork
|
||||
if is_apple_mobile:
|
||||
ext = ext.replace(".so", ".fwork")
|
||||
|
||||
filename = EXTENSIONS.name + ext
|
||||
file_path = os.path.join(path, filename)
|
||||
if os.path.exists(file_path):
|
||||
EXTENSIONS.path = path
|
||||
EXTENSIONS.ext = ext
|
||||
EXTENSIONS.filename = filename
|
||||
EXTENSIONS.file_path = file_path
|
||||
return
|
||||
|
||||
_extension_details()
|
||||
|
||||
|
||||
def import_importlib(module_name):
|
||||
"""Import a module from importlib both w/ and w/o _frozen_importlib."""
|
||||
fresh = ('importlib',) if '.' in module_name else ()
|
||||
frozen = import_helper.import_fresh_module(module_name)
|
||||
source = import_helper.import_fresh_module(module_name, fresh=fresh,
|
||||
blocked=('_frozen_importlib', '_frozen_importlib_external'))
|
||||
return {'Frozen': frozen, 'Source': source}
|
||||
|
||||
|
||||
def specialize_class(cls, kind, base=None, **kwargs):
|
||||
# XXX Support passing in submodule names--load (and cache) them?
|
||||
# That would clean up the test modules a bit more.
|
||||
if base is None:
|
||||
base = unittest.TestCase
|
||||
elif not isinstance(base, type):
|
||||
base = base[kind]
|
||||
name = '{}_{}'.format(kind, cls.__name__)
|
||||
bases = (cls, base, ExtraAssertions)
|
||||
specialized = types.new_class(name, bases)
|
||||
specialized.__module__ = cls.__module__
|
||||
specialized._NAME = cls.__name__
|
||||
specialized._KIND = kind
|
||||
for attr, values in kwargs.items():
|
||||
value = values[kind]
|
||||
setattr(specialized, attr, value)
|
||||
return specialized
|
||||
|
||||
|
||||
def split_frozen(cls, base=None, **kwargs):
|
||||
frozen = specialize_class(cls, 'Frozen', base, **kwargs)
|
||||
source = specialize_class(cls, 'Source', base, **kwargs)
|
||||
return frozen, source
|
||||
|
||||
|
||||
def test_both(test_class, base=None, **kwargs):
|
||||
return split_frozen(test_class, base, **kwargs)
|
||||
|
||||
|
||||
CASE_INSENSITIVE_FS = True
|
||||
# Windows is the only OS that is *always* case-insensitive
|
||||
# (OS X *can* be case-sensitive).
|
||||
if sys.platform not in ('win32', 'cygwin'):
|
||||
changed_name = __file__.upper()
|
||||
if changed_name == __file__:
|
||||
changed_name = __file__.lower()
|
||||
if not os.path.exists(changed_name):
|
||||
CASE_INSENSITIVE_FS = False
|
||||
|
||||
source_importlib = import_importlib('importlib')['Source']
|
||||
__import__ = {'Frozen': staticmethod(builtins.__import__),
|
||||
'Source': staticmethod(source_importlib.__import__)}
|
||||
|
||||
|
||||
def case_insensitive_tests(test):
|
||||
"""Class decorator that nullifies tests requiring a case-insensitive
|
||||
file system."""
|
||||
return unittest.skipIf(not CASE_INSENSITIVE_FS,
|
||||
"requires a case-insensitive filesystem")(test)
|
||||
|
||||
|
||||
def submodule(parent, name, pkg_dir, content=''):
|
||||
path = os.path.join(pkg_dir, name + '.py')
|
||||
with open(path, 'w', encoding='utf-8') as subfile:
|
||||
subfile.write(content)
|
||||
return '{}.{}'.format(parent, name), path
|
||||
|
||||
|
||||
def get_code_from_pyc(pyc_path):
|
||||
"""Reads a pyc file and returns the unmarshalled code object within.
|
||||
|
||||
No header validation is performed.
|
||||
"""
|
||||
with open(pyc_path, 'rb') as pyc_f:
|
||||
pyc_f.seek(16)
|
||||
return marshal.load(pyc_f)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def uncache(*names):
|
||||
"""Uncache a module from sys.modules.
|
||||
|
||||
A basic sanity check is performed to prevent uncaching modules that either
|
||||
cannot/shouldn't be uncached.
|
||||
|
||||
"""
|
||||
for name in names:
|
||||
if name in ('sys', 'marshal'):
|
||||
raise ValueError("cannot uncache {}".format(name))
|
||||
try:
|
||||
del sys.modules[name]
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
for name in names:
|
||||
try:
|
||||
del sys.modules[name]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def temp_module(name, content='', *, pkg=False):
|
||||
conflicts = [n for n in sys.modules if n.partition('.')[0] == name]
|
||||
with os_helper.temp_cwd(None) as cwd:
|
||||
with uncache(name, *conflicts):
|
||||
with import_helper.DirsOnSysPath(cwd):
|
||||
invalidate_caches()
|
||||
|
||||
location = os.path.join(cwd, name)
|
||||
if pkg:
|
||||
modpath = os.path.join(location, '__init__.py')
|
||||
os.mkdir(name)
|
||||
else:
|
||||
modpath = location + '.py'
|
||||
if content is None:
|
||||
# Make sure the module file gets created.
|
||||
content = ''
|
||||
if content is not None:
|
||||
# not a namespace package
|
||||
with open(modpath, 'w', encoding='utf-8') as modfile:
|
||||
modfile.write(content)
|
||||
yield location
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def import_state(**kwargs):
|
||||
"""Context manager to manage the various importers and stored state in the
|
||||
sys module.
|
||||
|
||||
The 'modules' attribute is not supported as the interpreter state stores a
|
||||
pointer to the dict that the interpreter uses internally;
|
||||
reassigning to sys.modules does not have the desired effect.
|
||||
|
||||
"""
|
||||
originals = {}
|
||||
try:
|
||||
for attr, default in (('meta_path', []), ('path', []),
|
||||
('path_hooks', []),
|
||||
('path_importer_cache', {})):
|
||||
originals[attr] = getattr(sys, attr)
|
||||
if attr in kwargs:
|
||||
new_value = kwargs[attr]
|
||||
del kwargs[attr]
|
||||
else:
|
||||
new_value = default
|
||||
setattr(sys, attr, new_value)
|
||||
if len(kwargs):
|
||||
raise ValueError('unrecognized arguments: {}'.format(kwargs))
|
||||
yield
|
||||
finally:
|
||||
for attr, value in originals.items():
|
||||
setattr(sys, attr, value)
|
||||
|
||||
|
||||
class _ImporterMock:
|
||||
|
||||
"""Base class to help with creating importer mocks."""
|
||||
|
||||
def __init__(self, *names, module_code={}):
|
||||
self.modules = {}
|
||||
self.module_code = {}
|
||||
for name in names:
|
||||
if not name.endswith('.__init__'):
|
||||
import_name = name
|
||||
else:
|
||||
import_name = name[:-len('.__init__')]
|
||||
if '.' not in name:
|
||||
package = None
|
||||
elif import_name == name:
|
||||
package = name.rsplit('.', 1)[0]
|
||||
else:
|
||||
package = import_name
|
||||
module = types.ModuleType(import_name)
|
||||
module.__loader__ = self
|
||||
module.__file__ = '<mock __file__>'
|
||||
module.__package__ = package
|
||||
module.attr = name
|
||||
if import_name != name:
|
||||
module.__path__ = ['<mock __path__>']
|
||||
self.modules[import_name] = module
|
||||
if import_name in module_code:
|
||||
self.module_code[import_name] = module_code[import_name]
|
||||
|
||||
def __getitem__(self, name):
|
||||
return self.modules[name]
|
||||
|
||||
def __enter__(self):
|
||||
self._uncache = uncache(*self.modules.keys())
|
||||
self._uncache.__enter__()
|
||||
return self
|
||||
|
||||
def __exit__(self, *exc_info):
|
||||
self._uncache.__exit__(None, None, None)
|
||||
|
||||
|
||||
class mock_spec(_ImporterMock):
|
||||
|
||||
"""Importer mock using PEP 451 APIs."""
|
||||
|
||||
def find_spec(self, fullname, path=None, parent=None):
|
||||
try:
|
||||
module = self.modules[fullname]
|
||||
except KeyError:
|
||||
return None
|
||||
spec = util.spec_from_file_location(
|
||||
fullname, module.__file__, loader=self,
|
||||
submodule_search_locations=getattr(module, '__path__', None))
|
||||
return spec
|
||||
|
||||
def create_module(self, spec):
|
||||
if spec.name not in self.modules:
|
||||
raise ImportError
|
||||
return self.modules[spec.name]
|
||||
|
||||
def exec_module(self, module):
|
||||
try:
|
||||
self.module_code[module.__spec__.name]()
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
def writes_bytecode_files(fxn):
|
||||
"""Decorator to protect sys.dont_write_bytecode from mutation and to skip
|
||||
tests that require it to be set to False."""
|
||||
if sys.dont_write_bytecode:
|
||||
return unittest.skip("relies on writing bytecode")(fxn)
|
||||
@functools.wraps(fxn)
|
||||
def wrapper(*args, **kwargs):
|
||||
original = sys.dont_write_bytecode
|
||||
sys.dont_write_bytecode = False
|
||||
try:
|
||||
to_return = fxn(*args, **kwargs)
|
||||
finally:
|
||||
sys.dont_write_bytecode = original
|
||||
return to_return
|
||||
return wrapper
|
||||
|
||||
|
||||
def ensure_bytecode_path(bytecode_path):
|
||||
"""Ensure that the __pycache__ directory for PEP 3147 pyc file exists.
|
||||
|
||||
:param bytecode_path: File system path to PEP 3147 pyc file.
|
||||
"""
|
||||
try:
|
||||
os.mkdir(os.path.dirname(bytecode_path))
|
||||
except OSError as error:
|
||||
if error.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def temporary_pycache_prefix(prefix):
|
||||
"""Adjust and restore sys.pycache_prefix."""
|
||||
_orig_prefix = sys.pycache_prefix
|
||||
sys.pycache_prefix = prefix
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
sys.pycache_prefix = _orig_prefix
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def create_modules(*names):
|
||||
"""Temporarily create each named module with an attribute (named 'attr')
|
||||
that contains the name passed into the context manager that caused the
|
||||
creation of the module.
|
||||
|
||||
All files are created in a temporary directory returned by
|
||||
tempfile.mkdtemp(). This directory is inserted at the beginning of
|
||||
sys.path. When the context manager exits all created files (source and
|
||||
bytecode) are explicitly deleted.
|
||||
|
||||
No magic is performed when creating packages! This means that if you create
|
||||
a module within a package you must also create the package's __init__ as
|
||||
well.
|
||||
|
||||
"""
|
||||
source = 'attr = {0!r}'
|
||||
created_paths = []
|
||||
mapping = {}
|
||||
state_manager = None
|
||||
uncache_manager = None
|
||||
try:
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
mapping['.root'] = temp_dir
|
||||
import_names = set()
|
||||
for name in names:
|
||||
if not name.endswith('__init__'):
|
||||
import_name = name
|
||||
else:
|
||||
import_name = name[:-len('.__init__')]
|
||||
import_names.add(import_name)
|
||||
if import_name in sys.modules:
|
||||
del sys.modules[import_name]
|
||||
name_parts = name.split('.')
|
||||
file_path = temp_dir
|
||||
for directory in name_parts[:-1]:
|
||||
file_path = os.path.join(file_path, directory)
|
||||
if not os.path.exists(file_path):
|
||||
os.mkdir(file_path)
|
||||
created_paths.append(file_path)
|
||||
file_path = os.path.join(file_path, name_parts[-1] + '.py')
|
||||
with open(file_path, 'w', encoding='utf-8') as file:
|
||||
file.write(source.format(name))
|
||||
created_paths.append(file_path)
|
||||
mapping[name] = file_path
|
||||
uncache_manager = uncache(*import_names)
|
||||
uncache_manager.__enter__()
|
||||
state_manager = import_state(path=[temp_dir])
|
||||
state_manager.__enter__()
|
||||
yield mapping
|
||||
finally:
|
||||
if state_manager is not None:
|
||||
state_manager.__exit__(None, None, None)
|
||||
if uncache_manager is not None:
|
||||
uncache_manager.__exit__(None, None, None)
|
||||
os_helper.rmtree(temp_dir)
|
||||
|
||||
|
||||
def mock_path_hook(*entries, importer):
|
||||
"""A mock sys.path_hooks entry."""
|
||||
def hook(entry):
|
||||
if entry not in entries:
|
||||
raise ImportError
|
||||
return importer
|
||||
return hook
|
||||
|
||||
|
||||
class CASEOKTestBase:
|
||||
|
||||
def caseok_env_changed(self, *, should_exist):
|
||||
possibilities = b'PYTHONCASEOK', 'PYTHONCASEOK'
|
||||
if any(x in self.importlib._bootstrap_external._os.environ
|
||||
for x in possibilities) != should_exist:
|
||||
self.skipTest('os.environ changes not reflected in _os.environ')
|
||||
Reference in New Issue
Block a user