Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/virtualenv/discovery/windows/pep514.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:32:28 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:d30785e31577 | 1:56ad4e20f292 |
---|---|
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 return company, major, minor, arch, exe, args | |
77 | |
78 | |
79 def load_exe(hive_name, company, company_key, tag): | |
80 key_path = "{}/{}/{}".format(hive_name, company, tag) | |
81 try: | |
82 with winreg.OpenKeyEx(company_key, r"{}\InstallPath".format(tag)) as ip_key: | |
83 with ip_key: | |
84 exe = get_value(ip_key, "ExecutablePath") | |
85 if exe is None: | |
86 ip = get_value(ip_key, None) | |
87 if ip is None: | |
88 msg(key_path, "no ExecutablePath or default for it") | |
89 | |
90 else: | |
91 exe = os.path.join(ip, str("python.exe")) | |
92 if exe is not None and os.path.exists(exe): | |
93 args = get_value(ip_key, "ExecutableArguments") | |
94 return exe, args | |
95 else: | |
96 msg(key_path, "could not load exe with value {}".format(exe)) | |
97 except OSError: | |
98 msg("{}/{}".format(key_path, "InstallPath"), "missing") | |
99 return None | |
100 | |
101 | |
102 def load_arch_data(hive_name, company, tag, tag_key, default_arch): | |
103 arch_str = get_value(tag_key, "SysArchitecture") | |
104 if arch_str is not None: | |
105 key_path = "{}/{}/{}/SysArchitecture".format(hive_name, company, tag) | |
106 try: | |
107 return parse_arch(arch_str) | |
108 except ValueError as sys_arch: | |
109 msg(key_path, sys_arch) | |
110 return default_arch | |
111 | |
112 | |
113 def parse_arch(arch_str): | |
114 if isinstance(arch_str, six.string_types): | |
115 match = re.match(r"^(\d+)bit$", arch_str) | |
116 if match: | |
117 return int(next(iter(match.groups()))) | |
118 error = "invalid format {}".format(arch_str) | |
119 else: | |
120 error = "arch is not string: {}".format(repr(arch_str)) | |
121 raise ValueError(error) | |
122 | |
123 | |
124 def load_version_data(hive_name, company, tag, tag_key): | |
125 for candidate, key_path in [ | |
126 (get_value(tag_key, "SysVersion"), "{}/{}/{}/SysVersion".format(hive_name, company, tag)), | |
127 (tag, "{}/{}/{}".format(hive_name, company, tag)), | |
128 ]: | |
129 if candidate is not None: | |
130 try: | |
131 return parse_version(candidate) | |
132 except ValueError as sys_version: | |
133 msg(key_path, sys_version) | |
134 return None | |
135 | |
136 | |
137 def parse_version(version_str): | |
138 if isinstance(version_str, six.string_types): | |
139 match = re.match(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?$", version_str) | |
140 if match: | |
141 return tuple(int(i) if i is not None else None for i in match.groups()) | |
142 error = "invalid format {}".format(version_str) | |
143 else: | |
144 error = "version is not string: {}".format(repr(version_str)) | |
145 raise ValueError(error) | |
146 | |
147 | |
148 def msg(path, what): | |
149 LOGGER.warning("PEP-514 violation in Windows Registry at {} error: {}".format(path, what)) | |
150 | |
151 | |
152 def _run(): | |
153 basicConfig() | |
154 interpreters = [] | |
155 for spec in discover_pythons(): | |
156 interpreters.append(repr(spec)) | |
157 print("\n".join(sorted(interpreters))) | |
158 | |
159 | |
160 if __name__ == "__main__": | |
161 _run() |