| from test.test_importlib import util as test_util | |
| machinery = test_util.import_importlib('importlib.machinery') | |
| import os | |
| import re | |
| import sys | |
| import sysconfig | |
| 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 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): | |
| with self.assertWarnsRegex( | |
| DeprecationWarning, | |
| r"importlib\.machinery\.WindowsRegistryFinder is deprecated; " | |
| r"use site configuration instead\. Future versions of Python may " | |
| r"not enable this finder by default\." | |
| ): | |
| spec = self.machinery.WindowsRegistryFinder.find_spec('spam') | |
| self.assertIsNone(spec) | |
| def test_module_found(self): | |
| with setup_module(self.machinery, self.test_module): | |
| with self.assertWarnsRegex( | |
| DeprecationWarning, | |
| r"importlib\.machinery\.WindowsRegistryFinder is deprecated; " | |
| r"use site configuration instead\. Future versions of Python may " | |
| r"not enable this finder by default\." | |
| ): | |
| 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="."): | |
| with self.assertWarnsRegex( | |
| DeprecationWarning, | |
| r"importlib\.machinery\.WindowsRegistryFinder is deprecated; " | |
| r"use site configuration instead\. Future versions of Python may " | |
| r"not enable this finder by default\." | |
| ): | |
| spec = self.machinery.WindowsRegistryFinder.find_spec(self.test_module) | |
| self.assertIsNone(spec) | |
| def test_raises_deprecation_warning(self): | |
| # WindowsRegistryFinder is not meant to be instantiated, so the | |
| # deprecation warning is raised in the 'find_spec' method instead. | |
| with self.assertWarnsRegex( | |
| DeprecationWarning, | |
| r"importlib\.machinery\.WindowsRegistryFinder is deprecated; " | |
| r"use site configuration instead\. Future versions of Python may " | |
| r"not enable this finder by default\." | |
| ): | |
| self.machinery.WindowsRegistryFinder.find_spec('spam') | |
| (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]', '_', sysconfig.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() |