Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/virtualenv/discovery/windows/pep514.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
| author | shellac |
|---|---|
| date | Sat, 02 May 2020 07:14:21 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:26e78fe6e8c4 |
|---|---|
| 1 """Implement https://www.python.org/dev/peps/pep-0514/ to discover interpreters - Windows only""" | |
| 2 from __future__ import absolute_import, print_function, unicode_literals | |
| 3 | |
| 4 import os | |
| 5 import re | |
| 6 from logging import basicConfig, getLogger | |
| 7 | |
| 8 import six | |
| 9 | |
| 10 if six.PY3: | |
| 11 import winreg | |
| 12 else: | |
| 13 # noinspection PyUnresolvedReferences | |
| 14 import _winreg as winreg | |
| 15 | |
| 16 LOGGER = getLogger(__name__) | |
| 17 | |
| 18 | |
| 19 def enum_keys(key): | |
| 20 at = 0 | |
| 21 while True: | |
| 22 try: | |
| 23 yield winreg.EnumKey(key, at) | |
| 24 except OSError: | |
| 25 break | |
| 26 at += 1 | |
| 27 | |
| 28 | |
| 29 def get_value(key, value_name): | |
| 30 try: | |
| 31 return winreg.QueryValueEx(key, value_name)[0] | |
| 32 except OSError: | |
| 33 return None | |
| 34 | |
| 35 | |
| 36 def discover_pythons(): | |
| 37 for hive, hive_name, key, flags, default_arch in [ | |
| 38 (winreg.HKEY_CURRENT_USER, "HKEY_CURRENT_USER", r"Software\Python", 0, 64), | |
| 39 (winreg.HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", r"Software\Python", winreg.KEY_WOW64_64KEY, 64), | |
| 40 (winreg.HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", r"Software\Python", winreg.KEY_WOW64_32KEY, 32), | |
| 41 ]: | |
| 42 for spec in process_set(hive, hive_name, key, flags, default_arch): | |
| 43 yield spec | |
| 44 | |
| 45 | |
| 46 def process_set(hive, hive_name, key, flags, default_arch): | |
| 47 try: | |
| 48 with winreg.OpenKeyEx(hive, key, 0, winreg.KEY_READ | flags) as root_key: | |
| 49 for company in enum_keys(root_key): | |
| 50 if company == "PyLauncher": # reserved | |
| 51 continue | |
| 52 for spec in process_company(hive_name, company, root_key, default_arch): | |
| 53 yield spec | |
| 54 except OSError: | |
| 55 pass | |
| 56 | |
| 57 | |
| 58 def process_company(hive_name, company, root_key, default_arch): | |
| 59 with winreg.OpenKeyEx(root_key, company) as company_key: | |
| 60 for tag in enum_keys(company_key): | |
| 61 spec = process_tag(hive_name, company, company_key, tag, default_arch) | |
| 62 if spec is not None: | |
| 63 yield spec | |
| 64 | |
| 65 | |
| 66 def process_tag(hive_name, company, company_key, tag, default_arch): | |
| 67 with winreg.OpenKeyEx(company_key, tag) as tag_key: | |
| 68 version = load_version_data(hive_name, company, tag, tag_key) | |
| 69 if version is not None: # if failed to get version bail | |
| 70 major, minor, _ = version | |
| 71 arch = load_arch_data(hive_name, company, tag, tag_key, default_arch) | |
| 72 if arch is not None: | |
| 73 exe_data = load_exe(hive_name, company, company_key, tag) | |
| 74 if exe_data is not None: | |
| 75 exe, args = exe_data | |
| 76 name = str("python") if company == "PythonCore" else company | |
| 77 return name, major, minor, arch, exe, args | |
| 78 | |
| 79 | |
| 80 def load_exe(hive_name, company, company_key, tag): | |
| 81 key_path = "{}/{}/{}".format(hive_name, company, tag) | |
| 82 try: | |
| 83 with winreg.OpenKeyEx(company_key, r"{}\InstallPath".format(tag)) as ip_key: | |
| 84 with ip_key: | |
| 85 exe = get_value(ip_key, "ExecutablePath") | |
| 86 if exe is None: | |
| 87 ip = get_value(ip_key, None) | |
| 88 if ip is None: | |
| 89 msg(key_path, "no ExecutablePath or default for it") | |
| 90 | |
| 91 else: | |
| 92 exe = os.path.join(ip, str("python.exe")) | |
| 93 if exe is not None and os.path.exists(exe): | |
| 94 args = get_value(ip_key, "ExecutableArguments") | |
| 95 return exe, args | |
| 96 else: | |
| 97 msg(key_path, "exe does not exists {}".format(key_path, exe)) | |
| 98 except OSError: | |
| 99 msg("{}/{}".format(key_path, "InstallPath"), "missing") | |
| 100 return None | |
| 101 | |
| 102 | |
| 103 def load_arch_data(hive_name, company, tag, tag_key, default_arch): | |
| 104 arch_str = get_value(tag_key, "SysArchitecture") | |
| 105 if arch_str is not None: | |
| 106 key_path = "{}/{}/{}/SysArchitecture".format(hive_name, company, tag) | |
| 107 try: | |
| 108 return parse_arch(arch_str) | |
| 109 except ValueError as sys_arch: | |
| 110 msg(key_path, sys_arch) | |
| 111 return default_arch | |
| 112 | |
| 113 | |
| 114 def parse_arch(arch_str): | |
| 115 if isinstance(arch_str, six.string_types): | |
| 116 match = re.match(r"^(\d+)bit$", arch_str) | |
| 117 if match: | |
| 118 return int(next(iter(match.groups()))) | |
| 119 error = "invalid format {}".format(arch_str) | |
| 120 else: | |
| 121 error = "arch is not string: {}".format(repr(arch_str)) | |
| 122 raise ValueError(error) | |
| 123 | |
| 124 | |
| 125 def load_version_data(hive_name, company, tag, tag_key): | |
| 126 for candidate, key_path in [ | |
| 127 (get_value(tag_key, "SysVersion"), "{}/{}/{}/SysVersion".format(hive_name, company, tag)), | |
| 128 (tag, "{}/{}/{}".format(hive_name, company, tag)), | |
| 129 ]: | |
| 130 if candidate is not None: | |
| 131 try: | |
| 132 return parse_version(candidate) | |
| 133 except ValueError as sys_version: | |
| 134 msg(key_path, sys_version) | |
| 135 return None | |
| 136 | |
| 137 | |
| 138 def parse_version(version_str): | |
| 139 if isinstance(version_str, six.string_types): | |
| 140 match = re.match(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?$", version_str) | |
| 141 if match: | |
| 142 return tuple(int(i) if i is not None else None for i in match.groups()) | |
| 143 error = "invalid format {}".format(version_str) | |
| 144 else: | |
| 145 error = "version is not string: {}".format(repr(version_str)) | |
| 146 raise ValueError(error) | |
| 147 | |
| 148 | |
| 149 def msg(path, what): | |
| 150 LOGGER.warning("PEP-514 violation in Windows Registry at {} error: {}".format(path, what)) | |
| 151 | |
| 152 | |
| 153 def _run(): | |
| 154 basicConfig() | |
| 155 interpreters = [] | |
| 156 for spec in discover_pythons(): | |
| 157 interpreters.append(repr(spec)) | |
| 158 print("\n".join(sorted(interpreters))) | |
| 159 | |
| 160 | |
| 161 if __name__ == "__main__": | |
| 162 _run() |
