Buckets:
MisterAI/LocalAI_Demo_backends / cpu-diffusers.upgrade-tmp /python /lib /python3.10 /site-packages /setuptools /msvc.py
| """ | |
| Environment info about Microsoft Compilers. | |
| getfixture('windows_only') | |
| ei = EnvironmentInfo('amd64') | |
| """ | |
| from __future__ import annotations | |
| import contextlib | |
| import itertools | |
| import json | |
| import os | |
| import os.path | |
| import platform | |
| from typing import TYPE_CHECKING, TypedDict | |
| from more_itertools import unique_everseen | |
| import distutils.errors | |
| if TYPE_CHECKING: | |
| from typing_extensions import LiteralString, NotRequired | |
| # https://github.com/python/mypy/issues/8166 | |
| if not TYPE_CHECKING and platform.system() == 'Windows': | |
| import winreg | |
| from os import environ | |
| else: | |
| # Mock winreg and environ so the module can be imported on this platform. | |
| class winreg: | |
| HKEY_USERS = None | |
| HKEY_CURRENT_USER = None | |
| HKEY_LOCAL_MACHINE = None | |
| HKEY_CLASSES_ROOT = None | |
| environ: dict[str, str] = dict() | |
| class PlatformInfo: | |
| """ | |
| Current and Target Architectures information. | |
| Parameters | |
| ---------- | |
| arch: str | |
| Target architecture. | |
| """ | |
| current_cpu = environ.get('processor_architecture', '').lower() | |
| def __init__(self, arch) -> None: | |
| self.arch = arch.lower().replace('x64', 'amd64') | |
| def target_cpu(self): | |
| """ | |
| Return Target CPU architecture. | |
| Return | |
| ------ | |
| str | |
| Target CPU | |
| """ | |
| return self.arch[self.arch.find('_') + 1 :] | |
| def target_is_x86(self): | |
| """ | |
| Return True if target CPU is x86 32 bits.. | |
| Return | |
| ------ | |
| bool | |
| CPU is x86 32 bits | |
| """ | |
| return self.target_cpu == 'x86' | |
| def current_is_x86(self): | |
| """ | |
| Return True if current CPU is x86 32 bits.. | |
| Return | |
| ------ | |
| bool | |
| CPU is x86 32 bits | |
| """ | |
| return self.current_cpu == 'x86' | |
| def current_dir(self, hidex86=False, x64=False) -> str: | |
| """ | |
| Current platform specific subfolder. | |
| Parameters | |
| ---------- | |
| hidex86: bool | |
| return '' and not '\x86' if architecture is x86. | |
| x64: bool | |
| return '\x64' and not '\amd64' if architecture is amd64. | |
| Return | |
| ------ | |
| str | |
| subfolder: '\target', or '' (see hidex86 parameter) | |
| """ | |
| return ( | |
| '' | |
| if (self.current_cpu == 'x86' and hidex86) | |
| else r'\x64' | |
| if (self.current_cpu == 'amd64' and x64) | |
| else rf'\{self.current_cpu}' | |
| ) | |
| def target_dir(self, hidex86=False, x64=False) -> str: | |
| r""" | |
| Target platform specific subfolder. | |
| Parameters | |
| ---------- | |
| hidex86: bool | |
| return '' and not '\x86' if architecture is x86. | |
| x64: bool | |
| return '\x64' and not '\amd64' if architecture is amd64. | |
| Return | |
| ------ | |
| str | |
| subfolder: '\current', or '' (see hidex86 parameter) | |
| """ | |
| return ( | |
| '' | |
| if (self.target_cpu == 'x86' and hidex86) | |
| else r'\x64' | |
| if (self.target_cpu == 'amd64' and x64) | |
| else rf'\{self.target_cpu}' | |
| ) | |
| def cross_dir(self, forcex86=False): | |
| r""" | |
| Cross platform specific subfolder. | |
| Parameters | |
| ---------- | |
| forcex86: bool | |
| Use 'x86' as current architecture even if current architecture is | |
| not x86. | |
| Return | |
| ------ | |
| str | |
| subfolder: '' if target architecture is current architecture, | |
| '\current_target' if not. | |
| """ | |
| current = 'x86' if forcex86 else self.current_cpu | |
| return ( | |
| '' | |
| if self.target_cpu == current | |
| else self.target_dir().replace('\\', f'\\{current}_') | |
| ) | |
| class RegistryInfo: | |
| """ | |
| Microsoft Visual Studio related registry information. | |
| Parameters | |
| ---------- | |
| platform_info: PlatformInfo | |
| "PlatformInfo" instance. | |
| """ | |
| HKEYS = ( | |
| winreg.HKEY_USERS, | |
| winreg.HKEY_CURRENT_USER, | |
| winreg.HKEY_LOCAL_MACHINE, | |
| winreg.HKEY_CLASSES_ROOT, | |
| ) | |
| def __init__(self, platform_info) -> None: | |
| self.pi = platform_info | |
| def visualstudio(self) -> str: | |
| """ | |
| Microsoft Visual Studio root registry key. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| return 'VisualStudio' | |
| def sxs(self): | |
| """ | |
| Microsoft Visual Studio SxS registry key. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| return os.path.join(self.visualstudio, 'SxS') | |
| def vc(self): | |
| """ | |
| Microsoft Visual C++ VC7 registry key. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| return os.path.join(self.sxs, 'VC7') | |
| def vs(self): | |
| """ | |
| Microsoft Visual Studio VS7 registry key. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| return os.path.join(self.sxs, 'VS7') | |
| def vc_for_python(self) -> str: | |
| """ | |
| Microsoft Visual C++ for Python registry key. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| return r'DevDiv\VCForPython' | |
| def microsoft_sdk(self) -> str: | |
| """ | |
| Microsoft SDK registry key. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| return 'Microsoft SDKs' | |
| def windows_sdk(self): | |
| """ | |
| Microsoft Windows/Platform SDK registry key. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| return os.path.join(self.microsoft_sdk, 'Windows') | |
| def netfx_sdk(self): | |
| """ | |
| Microsoft .NET Framework SDK registry key. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| return os.path.join(self.microsoft_sdk, 'NETFXSDK') | |
| def windows_kits_roots(self) -> str: | |
| """ | |
| Microsoft Windows Kits Roots registry key. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| return r'Windows Kits\Installed Roots' | |
| def microsoft(self, key, x86=False): | |
| """ | |
| Return key in Microsoft software registry. | |
| Parameters | |
| ---------- | |
| key: str | |
| Registry key path where look. | |
| x86: str | |
| Force x86 software registry. | |
| Return | |
| ------ | |
| str | |
| Registry key | |
| """ | |
| node64 = '' if self.pi.current_is_x86() or x86 else 'Wow6432Node' | |
| return os.path.join('Software', node64, 'Microsoft', key) | |
| def lookup(self, key, name): | |
| """ | |
| Look for values in registry in Microsoft software registry. | |
| Parameters | |
| ---------- | |
| key: str | |
| Registry key path where look. | |
| name: str | |
| Value name to find. | |
| Return | |
| ------ | |
| str | |
| value | |
| """ | |
| key_read = winreg.KEY_READ | |
| openkey = winreg.OpenKey | |
| closekey = winreg.CloseKey | |
| ms = self.microsoft | |
| for hkey in self.HKEYS: | |
| bkey = None | |
| try: | |
| bkey = openkey(hkey, ms(key), 0, key_read) | |
| except OSError: | |
| if not self.pi.current_is_x86(): | |
| try: | |
| bkey = openkey(hkey, ms(key, True), 0, key_read) | |
| except OSError: | |
| continue | |
| else: | |
| continue | |
| try: | |
| return winreg.QueryValueEx(bkey, name)[0] | |
| except OSError: | |
| pass | |
| finally: | |
| if bkey: | |
| closekey(bkey) | |
| return None | |
| class SystemInfo: | |
| """ | |
| Microsoft Windows and Visual Studio related system information. | |
| Parameters | |
| ---------- | |
| registry_info: RegistryInfo | |
| "RegistryInfo" instance. | |
| vc_ver: float | |
| Required Microsoft Visual C++ version. | |
| """ | |
| # Variables and properties in this class use originals CamelCase variables | |
| # names from Microsoft source files for more easy comparison. | |
| WinDir = environ.get('WinDir', '') | |
| ProgramFiles = environ.get('ProgramFiles', '') | |
| ProgramFilesx86 = environ.get('ProgramFiles(x86)', ProgramFiles) | |
| def __init__(self, registry_info, vc_ver=None) -> None: | |
| self.ri = registry_info | |
| self.pi = self.ri.pi | |
| self.known_vs_paths = self.find_programdata_vs_vers() | |
| # Except for VS15+, VC version is aligned with VS version | |
| self.vs_ver = self.vc_ver = vc_ver or self._find_latest_available_vs_ver() | |
| def _find_latest_available_vs_ver(self): | |
| """ | |
| Find the latest VC version | |
| Return | |
| ------ | |
| float | |
| version | |
| """ | |
| reg_vc_vers = self.find_reg_vs_vers() | |
| if not (reg_vc_vers or self.known_vs_paths): | |
| raise distutils.errors.DistutilsPlatformError( | |
| 'No Microsoft Visual C++ version found' | |
| ) | |
| vc_vers = set(reg_vc_vers) | |
| vc_vers.update(self.known_vs_paths) | |
| return sorted(vc_vers)[-1] | |
| def find_reg_vs_vers(self): | |
| """ | |
| Find Microsoft Visual Studio versions available in registry. | |
| Return | |
| ------ | |
| list of float | |
| Versions | |
| """ | |
| ms = self.ri.microsoft | |
| vckeys = (self.ri.vc, self.ri.vc_for_python, self.ri.vs) | |
| vs_vers = [] | |
| for hkey, key in itertools.product(self.ri.HKEYS, vckeys): | |
| try: | |
| bkey = winreg.OpenKey(hkey, ms(key), 0, winreg.KEY_READ) | |
| except OSError: | |
| continue | |
| with bkey: | |
| subkeys, values, _ = winreg.QueryInfoKey(bkey) | |
| for i in range(values): | |
| with contextlib.suppress(ValueError): | |
| ver = float(winreg.EnumValue(bkey, i)[0]) | |
| if ver not in vs_vers: | |
| vs_vers.append(ver) | |
| for i in range(subkeys): | |
| with contextlib.suppress(ValueError): | |
| ver = float(winreg.EnumKey(bkey, i)) | |
| if ver not in vs_vers: | |
| vs_vers.append(ver) | |
| return sorted(vs_vers) | |
| def find_programdata_vs_vers(self) -> dict[float, str]: | |
| r""" | |
| Find Visual studio 2017+ versions from information in | |
| "C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances". | |
| Return | |
| ------ | |
| dict | |
| float version as key, path as value. | |
| """ | |
| vs_versions: dict[float, str] = {} | |
| instances_dir = r'C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances' | |
| try: | |
| hashed_names = os.listdir(instances_dir) | |
| except OSError: | |
| # Directory not exists with all Visual Studio versions | |
| return vs_versions | |
| for name in hashed_names: | |
| try: | |
| # Get VS installation path from "state.json" file | |
| state_path = os.path.join(instances_dir, name, 'state.json') | |
| with open(state_path, 'rt', encoding='utf-8') as state_file: | |
| state = json.load(state_file) | |
| vs_path = state['installationPath'] | |
| # Raises OSError if this VS installation does not contain VC | |
| os.listdir(os.path.join(vs_path, r'VC\Tools\MSVC')) | |
| # Store version and path | |
| vs_versions[self._as_float_version(state['installationVersion'])] = ( | |
| vs_path | |
| ) | |
| except (OSError, KeyError): | |
| # Skip if "state.json" file is missing or bad format | |
| continue | |
| return vs_versions | |
| def _as_float_version(version): | |
| """ | |
| Return a string version as a simplified float version (major.minor) | |
| Parameters | |
| ---------- | |
| version: str | |
| Version. | |
| Return | |
| ------ | |
| float | |
| version | |
| """ | |
| return float('.'.join(version.split('.')[:2])) | |
| def VSInstallDir(self): | |
| """ | |
| Microsoft Visual Studio directory. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| # Default path | |
| default = os.path.join( | |
| self.ProgramFilesx86, f'Microsoft Visual Studio {self.vs_ver:0.1f}' | |
| ) | |
| # Try to get path from registry, if fail use default path | |
| return self.ri.lookup(self.ri.vs, f'{self.vs_ver:0.1f}') or default | |
| def VCInstallDir(self): | |
| """ | |
| Microsoft Visual C++ directory. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| path = self._guess_vc() or self._guess_vc_legacy() | |
| if not os.path.isdir(path): | |
| msg = 'Microsoft Visual C++ directory not found' | |
| raise distutils.errors.DistutilsPlatformError(msg) | |
| return path | |
| def _guess_vc(self): | |
| """ | |
| Locate Visual C++ for VS2017+. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| if self.vs_ver <= 14.0: | |
| return '' | |
| try: | |
| # First search in known VS paths | |
| vs_dir = self.known_vs_paths[self.vs_ver] | |
| except KeyError: | |
| # Else, search with path from registry | |
| vs_dir = self.VSInstallDir | |
| guess_vc = os.path.join(vs_dir, r'VC\Tools\MSVC') | |
| # Subdir with VC exact version as name | |
| try: | |
| # Update the VC version with real one instead of VS version | |
| vc_ver = os.listdir(guess_vc)[-1] | |
| self.vc_ver = self._as_float_version(vc_ver) | |
| return os.path.join(guess_vc, vc_ver) | |
| except (OSError, IndexError): | |
| return '' | |
| def _guess_vc_legacy(self): | |
| """ | |
| Locate Visual C++ for versions prior to 2017. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| default = os.path.join( | |
| self.ProgramFilesx86, | |
| rf'Microsoft Visual Studio {self.vs_ver:0.1f}\VC', | |
| ) | |
| # Try to get "VC++ for Python" path from registry as default path | |
| reg_path = os.path.join(self.ri.vc_for_python, f'{self.vs_ver:0.1f}') | |
| python_vc = self.ri.lookup(reg_path, 'installdir') | |
| default_vc = os.path.join(python_vc, 'VC') if python_vc else default | |
| # Try to get path from registry, if fail use default path | |
| return self.ri.lookup(self.ri.vc, f'{self.vs_ver:0.1f}') or default_vc | |
| def WindowsSdkVersion(self) -> tuple[LiteralString, ...]: | |
| """ | |
| Microsoft Windows SDK versions for specified MSVC++ version. | |
| Return | |
| ------ | |
| tuple of str | |
| versions | |
| """ | |
| if self.vs_ver <= 9.0: | |
| return '7.0', '6.1', '6.0a' | |
| elif self.vs_ver == 10.0: | |
| return '7.1', '7.0a' | |
| elif self.vs_ver == 11.0: | |
| return '8.0', '8.0a' | |
| elif self.vs_ver == 12.0: | |
| return '8.1', '8.1a' | |
| elif self.vs_ver >= 14.0: | |
| return '10.0', '8.1' | |
| return () | |
| def WindowsSdkLastVersion(self): | |
| """ | |
| Microsoft Windows SDK last version. | |
| Return | |
| ------ | |
| str | |
| version | |
| """ | |
| return self._use_last_dir_name(os.path.join(self.WindowsSdkDir, 'lib')) | |
| def WindowsSdkDir(self) -> str | None: # noqa: C901 # is too complex (12) # FIXME | |
| """ | |
| Microsoft Windows SDK directory. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| sdkdir: str | None = '' | |
| for ver in self.WindowsSdkVersion: | |
| # Try to get it from registry | |
| loc = os.path.join(self.ri.windows_sdk, f'v{ver}') | |
| sdkdir = self.ri.lookup(loc, 'installationfolder') | |
| if sdkdir: | |
| break | |
| if not sdkdir or not os.path.isdir(sdkdir): | |
| # Try to get "VC++ for Python" version from registry | |
| path = os.path.join(self.ri.vc_for_python, f'{self.vc_ver:0.1f}') | |
| install_base = self.ri.lookup(path, 'installdir') | |
| if install_base: | |
| sdkdir = os.path.join(install_base, 'WinSDK') | |
| if not sdkdir or not os.path.isdir(sdkdir): | |
| # If fail, use default new path | |
| for ver in self.WindowsSdkVersion: | |
| intver = ver[: ver.rfind('.')] | |
| path = rf'Microsoft SDKs\Windows Kits\{intver}' | |
| d = os.path.join(self.ProgramFiles, path) | |
| if os.path.isdir(d): | |
| sdkdir = d | |
| if not sdkdir or not os.path.isdir(sdkdir): | |
| # If fail, use default old path | |
| for ver in self.WindowsSdkVersion: | |
| path = rf'Microsoft SDKs\Windows\v{ver}' | |
| d = os.path.join(self.ProgramFiles, path) | |
| if os.path.isdir(d): | |
| sdkdir = d | |
| if not sdkdir: | |
| # If fail, use Platform SDK | |
| sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK') | |
| return sdkdir | |
| def WindowsSDKExecutablePath(self): | |
| """ | |
| Microsoft Windows SDK executable directory. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| # Find WinSDK NetFx Tools registry dir name | |
| if self.vs_ver <= 11.0: | |
| netfxver = 35 | |
| arch = '' | |
| else: | |
| netfxver = 40 | |
| hidex86 = True if self.vs_ver <= 12.0 else False | |
| arch = self.pi.current_dir(x64=True, hidex86=hidex86).replace('\\', '-') | |
| fx = f'WinSDK-NetFx{netfxver}Tools{arch}' | |
| # list all possibles registry paths | |
| regpaths = [] | |
| if self.vs_ver >= 14.0: | |
| for ver in self.NetFxSdkVersion: | |
| regpaths += [os.path.join(self.ri.netfx_sdk, ver, fx)] | |
| for ver in self.WindowsSdkVersion: | |
| regpaths += [os.path.join(self.ri.windows_sdk, f'v{ver}A', fx)] | |
| # Return installation folder from the more recent path | |
| for path in regpaths: | |
| execpath = self.ri.lookup(path, 'installationfolder') | |
| if execpath: | |
| return execpath | |
| return None | |
| def FSharpInstallDir(self): | |
| """ | |
| Microsoft Visual F# directory. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| path = os.path.join(self.ri.visualstudio, rf'{self.vs_ver:0.1f}\Setup\F#') | |
| return self.ri.lookup(path, 'productdir') or '' | |
| def UniversalCRTSdkDir(self): | |
| """ | |
| Microsoft Universal CRT SDK directory. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| # Set Kit Roots versions for specified MSVC++ version | |
| vers = ('10', '81') if self.vs_ver >= 14.0 else () | |
| # Find path of the more recent Kit | |
| for ver in vers: | |
| sdkdir = self.ri.lookup(self.ri.windows_kits_roots, f'kitsroot{ver}') | |
| if sdkdir: | |
| return sdkdir or '' | |
| return None | |
| def UniversalCRTSdkLastVersion(self): | |
| """ | |
| Microsoft Universal C Runtime SDK last version. | |
| Return | |
| ------ | |
| str | |
| version | |
| """ | |
| return self._use_last_dir_name(os.path.join(self.UniversalCRTSdkDir, 'lib')) | |
| def NetFxSdkVersion(self): | |
| """ | |
| Microsoft .NET Framework SDK versions. | |
| Return | |
| ------ | |
| tuple of str | |
| versions | |
| """ | |
| # Set FxSdk versions for specified VS version | |
| return ( | |
| ('4.7.2', '4.7.1', '4.7', '4.6.2', '4.6.1', '4.6', '4.5.2', '4.5.1', '4.5') | |
| if self.vs_ver >= 14.0 | |
| else () | |
| ) | |
| def NetFxSdkDir(self): | |
| """ | |
| Microsoft .NET Framework SDK directory. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| sdkdir = '' | |
| for ver in self.NetFxSdkVersion: | |
| loc = os.path.join(self.ri.netfx_sdk, ver) | |
| sdkdir = self.ri.lookup(loc, 'kitsinstallationfolder') | |
| if sdkdir: | |
| break | |
| return sdkdir | |
| def FrameworkDir32(self): | |
| """ | |
| Microsoft .NET Framework 32bit directory. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| # Default path | |
| guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework') | |
| # Try to get path from registry, if fail use default path | |
| return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw | |
| def FrameworkDir64(self): | |
| """ | |
| Microsoft .NET Framework 64bit directory. | |
| Return | |
| ------ | |
| str | |
| path | |
| """ | |
| # Default path | |
| guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework64') | |
| # Try to get path from registry, if fail use default path | |
| return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw | |
| def FrameworkVersion32(self) -> tuple[str, ...]: | |
| """ | |
| Microsoft .NET Framework 32bit versions. | |
| Return | |
| ------ | |
| tuple of str | |
| versions | |
| """ | |
| return self._find_dot_net_versions(32) | |
| def FrameworkVersion64(self) -> tuple[str, ...]: | |
| """ | |
| Microsoft .NET Framework 64bit versions. | |
| Return | |
| ------ | |
| tuple of str | |
| versions | |
| """ | |
| return self._find_dot_net_versions(64) | |
| def _find_dot_net_versions(self, bits) -> tuple[str, ...]: | |
| """ | |
| Find Microsoft .NET Framework versions. | |
| Parameters | |
| ---------- | |
| bits: int | |
| Platform number of bits: 32 or 64. | |
| Return | |
| ------ | |
| tuple of str | |
| versions | |
| """ | |
| # Find actual .NET version in registry | |
| reg_ver = self.ri.lookup(self.ri.vc, f'frameworkver{bits}') | |
| dot_net_dir = getattr(self, f'FrameworkDir{bits}') | |
| ver = reg_ver or self._use_last_dir_name(dot_net_dir, 'v') or '' | |
| # Set .NET versions for specified MSVC++ version | |
| if self.vs_ver >= 12.0: | |
| return ver, 'v4.0' | |
| elif self.vs_ver >= 10.0: | |
| return 'v4.0.30319' if ver.lower()[:2] != 'v4' else ver, 'v3.5' | |
| elif self.vs_ver == 9.0: | |
| return 'v3.5', 'v2.0.50727' | |
| elif self.vs_ver == 8.0: | |
| return 'v3.0', 'v2.0.50727' | |
| return () | |
| def _use_last_dir_name(path, prefix=''): | |
| """ | |
| Return name of the last dir in path or '' if no dir found. | |
| Parameters | |
| ---------- | |
| path: str | |
| Use dirs in this path | |
| prefix: str | |
| Use only dirs starting by this prefix | |
| Return | |
| ------ | |
| str | |
| name | |
| """ | |
| matching_dirs = ( | |
| dir_name | |
| for dir_name in reversed(os.listdir(path)) | |
| if os.path.isdir(os.path.join(path, dir_name)) | |
| and dir_name.startswith(prefix) | |
| ) | |
| return next(matching_dirs, None) or '' | |
| class _EnvironmentDict(TypedDict): | |
| include: str | |
| lib: str | |
| libpath: str | |
| path: str | |
| py_vcruntime_redist: NotRequired[str | None] | |
| class EnvironmentInfo: | |
| """ | |
| Return environment variables for specified Microsoft Visual C++ version | |
| and platform : Lib, Include, Path and libpath. | |
| This function is compatible with Microsoft Visual C++ 9.0 to 14.X. | |
| Script created by analysing Microsoft environment configuration files like | |
| "vcvars[...].bat", "SetEnv.Cmd", "vcbuildtools.bat", ... | |
| Parameters | |
| ---------- | |
| arch: str | |
| Target architecture. | |
| vc_ver: float | |
| Required Microsoft Visual C++ version. If not set, autodetect the last | |
| version. | |
| vc_min_ver: float | |
| Minimum Microsoft Visual C++ version. | |
| """ | |
| # Variables and properties in this class use originals CamelCase variables | |
| # names from Microsoft source files for more easy comparison. | |
| def __init__(self, arch, vc_ver=None, vc_min_ver=0) -> None: | |
| self.pi = PlatformInfo(arch) | |
| self.ri = RegistryInfo(self.pi) | |
| self.si = SystemInfo(self.ri, vc_ver) | |
| if self.vc_ver < vc_min_ver: | |
| err = 'No suitable Microsoft Visual C++ version found' | |
| raise distutils.errors.DistutilsPlatformError(err) | |
| def vs_ver(self): | |
| """ | |
| Microsoft Visual Studio. | |
| Return | |
| ------ | |
| float | |
| version | |
| """ | |
| return self.si.vs_ver | |
| def vc_ver(self): | |
| """ | |
| Microsoft Visual C++ version. | |
| Return | |
| ------ | |
| float | |
| version | |
| """ | |
| return self.si.vc_ver | |
| def VSTools(self): | |
| """ | |
| Microsoft Visual Studio Tools. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| paths = [r'Common7\IDE', r'Common7\Tools'] | |
| if self.vs_ver >= 14.0: | |
| arch_subdir = self.pi.current_dir(hidex86=True, x64=True) | |
| paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow'] | |
| paths += [r'Team Tools\Performance Tools'] | |
| paths += [rf'Team Tools\Performance Tools{arch_subdir}'] | |
| return [os.path.join(self.si.VSInstallDir, path) for path in paths] | |
| def VCIncludes(self): | |
| """ | |
| Microsoft Visual C++ & Microsoft Foundation Class Includes. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| return [ | |
| os.path.join(self.si.VCInstallDir, 'Include'), | |
| os.path.join(self.si.VCInstallDir, r'ATLMFC\Include'), | |
| ] | |
| def VCLibraries(self): | |
| """ | |
| Microsoft Visual C++ & Microsoft Foundation Class Libraries. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver >= 15.0: | |
| arch_subdir = self.pi.target_dir(x64=True) | |
| else: | |
| arch_subdir = self.pi.target_dir(hidex86=True) | |
| paths = [f'Lib{arch_subdir}', rf'ATLMFC\Lib{arch_subdir}'] | |
| if self.vs_ver >= 14.0: | |
| paths += [rf'Lib\store{arch_subdir}'] | |
| return [os.path.join(self.si.VCInstallDir, path) for path in paths] | |
| def VCStoreRefs(self): | |
| """ | |
| Microsoft Visual C++ store references Libraries. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver < 14.0: | |
| return [] | |
| return [os.path.join(self.si.VCInstallDir, r'Lib\store\references')] | |
| def VCTools(self): | |
| """ | |
| Microsoft Visual C++ Tools. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| When host CPU is ARM, the tools should be found for ARM. | |
| >>> getfixture('windows_only') | |
| >>> mp = getfixture('monkeypatch') | |
| >>> mp.setattr(PlatformInfo, 'current_cpu', 'arm64') | |
| >>> ei = EnvironmentInfo(arch='irrelevant') | |
| >>> paths = ei.VCTools | |
| >>> any('HostARM64' in path for path in paths) | |
| True | |
| """ | |
| si = self.si | |
| tools = [os.path.join(si.VCInstallDir, 'VCPackages')] | |
| forcex86 = True if self.vs_ver <= 10.0 else False | |
| arch_subdir = self.pi.cross_dir(forcex86) | |
| if arch_subdir: | |
| tools += [os.path.join(si.VCInstallDir, f'Bin{arch_subdir}')] | |
| if self.vs_ver == 14.0: | |
| path = f'Bin{self.pi.current_dir(hidex86=True)}' | |
| tools += [os.path.join(si.VCInstallDir, path)] | |
| elif self.vs_ver >= 15.0: | |
| host_id = self.pi.current_cpu.replace('amd64', 'x64').upper() | |
| host_dir = os.path.join('bin', f'Host{host_id}%s') | |
| tools += [ | |
| os.path.join(si.VCInstallDir, host_dir % self.pi.target_dir(x64=True)) | |
| ] | |
| if self.pi.current_cpu != self.pi.target_cpu: | |
| tools += [ | |
| os.path.join( | |
| si.VCInstallDir, host_dir % self.pi.current_dir(x64=True) | |
| ) | |
| ] | |
| else: | |
| tools += [os.path.join(si.VCInstallDir, 'Bin')] | |
| return tools | |
| def OSLibraries(self): | |
| """ | |
| Microsoft Windows SDK Libraries. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver <= 10.0: | |
| arch_subdir = self.pi.target_dir(hidex86=True, x64=True) | |
| return [os.path.join(self.si.WindowsSdkDir, f'Lib{arch_subdir}')] | |
| else: | |
| arch_subdir = self.pi.target_dir(x64=True) | |
| lib = os.path.join(self.si.WindowsSdkDir, 'lib') | |
| libver = self._sdk_subdir | |
| return [os.path.join(lib, f'{libver}um{arch_subdir}')] | |
| def OSIncludes(self): | |
| """ | |
| Microsoft Windows SDK Include. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| include = os.path.join(self.si.WindowsSdkDir, 'include') | |
| if self.vs_ver <= 10.0: | |
| return [include, os.path.join(include, 'gl')] | |
| else: | |
| if self.vs_ver >= 14.0: | |
| sdkver = self._sdk_subdir | |
| else: | |
| sdkver = '' | |
| return [ | |
| os.path.join(include, f'{sdkver}shared'), | |
| os.path.join(include, f'{sdkver}um'), | |
| os.path.join(include, f'{sdkver}winrt'), | |
| ] | |
| def OSLibpath(self): | |
| """ | |
| Microsoft Windows SDK Libraries Paths. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| ref = os.path.join(self.si.WindowsSdkDir, 'References') | |
| libpath = [] | |
| if self.vs_ver <= 9.0: | |
| libpath += self.OSLibraries | |
| if self.vs_ver >= 11.0: | |
| libpath += [os.path.join(ref, r'CommonConfiguration\Neutral')] | |
| if self.vs_ver >= 14.0: | |
| libpath += [ | |
| ref, | |
| os.path.join(self.si.WindowsSdkDir, 'UnionMetadata'), | |
| os.path.join(ref, 'Windows.Foundation.UniversalApiContract', '1.0.0.0'), | |
| os.path.join(ref, 'Windows.Foundation.FoundationContract', '1.0.0.0'), | |
| os.path.join( | |
| ref, 'Windows.Networking.Connectivity.WwanContract', '1.0.0.0' | |
| ), | |
| os.path.join( | |
| self.si.WindowsSdkDir, | |
| 'ExtensionSDKs', | |
| 'Microsoft.VCLibs', | |
| f'{self.vs_ver:0.1f}', | |
| 'References', | |
| 'CommonConfiguration', | |
| 'neutral', | |
| ), | |
| ] | |
| return libpath | |
| def SdkTools(self): | |
| """ | |
| Microsoft Windows SDK Tools. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| return list(self._sdk_tools()) | |
| def _sdk_tools(self): | |
| """ | |
| Microsoft Windows SDK Tools paths generator. | |
| Return | |
| ------ | |
| generator of str | |
| paths | |
| """ | |
| if self.vs_ver < 15.0: | |
| bin_dir = 'Bin' if self.vs_ver <= 11.0 else r'Bin\x86' | |
| yield os.path.join(self.si.WindowsSdkDir, bin_dir) | |
| if not self.pi.current_is_x86(): | |
| arch_subdir = self.pi.current_dir(x64=True) | |
| path = f'Bin{arch_subdir}' | |
| yield os.path.join(self.si.WindowsSdkDir, path) | |
| if self.vs_ver in (10.0, 11.0): | |
| if self.pi.target_is_x86(): | |
| arch_subdir = '' | |
| else: | |
| arch_subdir = self.pi.current_dir(hidex86=True, x64=True) | |
| path = rf'Bin\NETFX 4.0 Tools{arch_subdir}' | |
| yield os.path.join(self.si.WindowsSdkDir, path) | |
| elif self.vs_ver >= 15.0: | |
| path = os.path.join(self.si.WindowsSdkDir, 'Bin') | |
| arch_subdir = self.pi.current_dir(x64=True) | |
| sdkver = self.si.WindowsSdkLastVersion | |
| yield os.path.join(path, f'{sdkver}{arch_subdir}') | |
| if self.si.WindowsSDKExecutablePath: | |
| yield self.si.WindowsSDKExecutablePath | |
| def _sdk_subdir(self): | |
| """ | |
| Microsoft Windows SDK version subdir. | |
| Return | |
| ------ | |
| str | |
| subdir | |
| """ | |
| ucrtver = self.si.WindowsSdkLastVersion | |
| return (f'{ucrtver}\\') if ucrtver else '' | |
| def SdkSetup(self): | |
| """ | |
| Microsoft Windows SDK Setup. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver > 9.0: | |
| return [] | |
| return [os.path.join(self.si.WindowsSdkDir, 'Setup')] | |
| def FxTools(self): | |
| """ | |
| Microsoft .NET Framework Tools. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| pi = self.pi | |
| si = self.si | |
| if self.vs_ver <= 10.0: | |
| include32 = True | |
| include64 = not pi.target_is_x86() and not pi.current_is_x86() | |
| else: | |
| include32 = pi.target_is_x86() or pi.current_is_x86() | |
| include64 = pi.current_cpu == 'amd64' or pi.target_cpu == 'amd64' | |
| tools = [] | |
| if include32: | |
| tools += [ | |
| os.path.join(si.FrameworkDir32, ver) for ver in si.FrameworkVersion32 | |
| ] | |
| if include64: | |
| tools += [ | |
| os.path.join(si.FrameworkDir64, ver) for ver in si.FrameworkVersion64 | |
| ] | |
| return tools | |
| def NetFxSDKLibraries(self): | |
| """ | |
| Microsoft .Net Framework SDK Libraries. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver < 14.0 or not self.si.NetFxSdkDir: | |
| return [] | |
| arch_subdir = self.pi.target_dir(x64=True) | |
| return [os.path.join(self.si.NetFxSdkDir, rf'lib\um{arch_subdir}')] | |
| def NetFxSDKIncludes(self): | |
| """ | |
| Microsoft .Net Framework SDK Includes. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver < 14.0 or not self.si.NetFxSdkDir: | |
| return [] | |
| return [os.path.join(self.si.NetFxSdkDir, r'include\um')] | |
| def VsTDb(self): | |
| """ | |
| Microsoft Visual Studio Team System Database. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| return [os.path.join(self.si.VSInstallDir, r'VSTSDB\Deploy')] | |
| def MSBuild(self): | |
| """ | |
| Microsoft Build Engine. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver < 12.0: | |
| return [] | |
| elif self.vs_ver < 15.0: | |
| base_path = self.si.ProgramFilesx86 | |
| arch_subdir = self.pi.current_dir(hidex86=True) | |
| else: | |
| base_path = self.si.VSInstallDir | |
| arch_subdir = '' | |
| path = rf'MSBuild\{self.vs_ver:0.1f}\bin{arch_subdir}' | |
| build = [os.path.join(base_path, path)] | |
| if self.vs_ver >= 15.0: | |
| # Add Roslyn C# & Visual Basic Compiler | |
| build += [os.path.join(base_path, path, 'Roslyn')] | |
| return build | |
| def HTMLHelpWorkshop(self): | |
| """ | |
| Microsoft HTML Help Workshop. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver < 11.0: | |
| return [] | |
| return [os.path.join(self.si.ProgramFilesx86, 'HTML Help Workshop')] | |
| def UCRTLibraries(self): | |
| """ | |
| Microsoft Universal C Runtime SDK Libraries. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver < 14.0: | |
| return [] | |
| arch_subdir = self.pi.target_dir(x64=True) | |
| lib = os.path.join(self.si.UniversalCRTSdkDir, 'lib') | |
| ucrtver = self._ucrt_subdir | |
| return [os.path.join(lib, f'{ucrtver}ucrt{arch_subdir}')] | |
| def UCRTIncludes(self): | |
| """ | |
| Microsoft Universal C Runtime SDK Include. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if self.vs_ver < 14.0: | |
| return [] | |
| include = os.path.join(self.si.UniversalCRTSdkDir, 'include') | |
| return [os.path.join(include, f'{self._ucrt_subdir}ucrt')] | |
| def _ucrt_subdir(self): | |
| """ | |
| Microsoft Universal C Runtime SDK version subdir. | |
| Return | |
| ------ | |
| str | |
| subdir | |
| """ | |
| ucrtver = self.si.UniversalCRTSdkLastVersion | |
| return (f'{ucrtver}\\') if ucrtver else '' | |
| def FSharp(self): | |
| """ | |
| Microsoft Visual F#. | |
| Return | |
| ------ | |
| list of str | |
| paths | |
| """ | |
| if 11.0 > self.vs_ver > 12.0: | |
| return [] | |
| return [self.si.FSharpInstallDir] | |
| def VCRuntimeRedist(self) -> str | None: | |
| """ | |
| Microsoft Visual C++ runtime redistributable dll. | |
| Returns the first suitable path found or None. | |
| """ | |
| vcruntime = f'vcruntime{self.vc_ver}0.dll' | |
| arch_subdir = self.pi.target_dir(x64=True).strip('\\') | |
| # Installation prefixes candidates | |
| prefixes = [] | |
| tools_path = self.si.VCInstallDir | |
| redist_path = os.path.dirname(tools_path.replace(r'\Tools', r'\Redist')) | |
| if os.path.isdir(redist_path): | |
| # Redist version may not be exactly the same as tools | |
| redist_path = os.path.join(redist_path, os.listdir(redist_path)[-1]) | |
| prefixes += [redist_path, os.path.join(redist_path, 'onecore')] | |
| prefixes += [os.path.join(tools_path, 'redist')] # VS14 legacy path | |
| # CRT directory | |
| crt_dirs = ( | |
| f'Microsoft.VC{self.vc_ver * 10}.CRT', | |
| # Sometime store in directory with VS version instead of VC | |
| f'Microsoft.VC{int(self.vs_ver) * 10}.CRT', | |
| ) | |
| # vcruntime path | |
| candidate_paths = ( | |
| os.path.join(prefix, arch_subdir, crt_dir, vcruntime) | |
| for (prefix, crt_dir) in itertools.product(prefixes, crt_dirs) | |
| ) | |
| return next(filter(os.path.isfile, candidate_paths), None) # type: ignore[arg-type] #python/mypy#12682 | |
| def return_env(self, exists: bool = True) -> _EnvironmentDict: | |
| """ | |
| Return environment dict. | |
| Parameters | |
| ---------- | |
| exists: bool | |
| It True, only return existing paths. | |
| Return | |
| ------ | |
| dict | |
| environment | |
| """ | |
| env = _EnvironmentDict( | |
| include=self._build_paths( | |
| 'include', | |
| [ | |
| self.VCIncludes, | |
| self.OSIncludes, | |
| self.UCRTIncludes, | |
| self.NetFxSDKIncludes, | |
| ], | |
| exists, | |
| ), | |
| lib=self._build_paths( | |
| 'lib', | |
| [ | |
| self.VCLibraries, | |
| self.OSLibraries, | |
| self.FxTools, | |
| self.UCRTLibraries, | |
| self.NetFxSDKLibraries, | |
| ], | |
| exists, | |
| ), | |
| libpath=self._build_paths( | |
| 'libpath', | |
| [self.VCLibraries, self.FxTools, self.VCStoreRefs, self.OSLibpath], | |
| exists, | |
| ), | |
| path=self._build_paths( | |
| 'path', | |
| [ | |
| self.VCTools, | |
| self.VSTools, | |
| self.VsTDb, | |
| self.SdkTools, | |
| self.SdkSetup, | |
| self.FxTools, | |
| self.MSBuild, | |
| self.HTMLHelpWorkshop, | |
| self.FSharp, | |
| ], | |
| exists, | |
| ), | |
| ) | |
| if self.vs_ver >= 14 and self.VCRuntimeRedist: | |
| env['py_vcruntime_redist'] = self.VCRuntimeRedist | |
| return env | |
| def _build_paths(self, name, spec_path_lists, exists): | |
| """ | |
| Given an environment variable name and specified paths, | |
| return a pathsep-separated string of paths containing | |
| unique, extant, directories from those paths and from | |
| the environment variable. Raise an error if no paths | |
| are resolved. | |
| Parameters | |
| ---------- | |
| name: str | |
| Environment variable name | |
| spec_path_lists: list of str | |
| Paths | |
| exists: bool | |
| It True, only return existing paths. | |
| Return | |
| ------ | |
| str | |
| Pathsep-separated paths | |
| """ | |
| # flatten spec_path_lists | |
| spec_paths = itertools.chain.from_iterable(spec_path_lists) | |
| env_paths = environ.get(name, '').split(os.pathsep) | |
| paths = itertools.chain(spec_paths, env_paths) | |
| extant_paths = list(filter(os.path.isdir, paths)) if exists else paths | |
| if not extant_paths: | |
| msg = f"{name.upper()} environment variable is empty" | |
| raise distutils.errors.DistutilsPlatformError(msg) | |
| unique_paths = unique_everseen(extant_paths) | |
| return os.pathsep.join(unique_paths) | |
Xet Storage Details
- Size:
- 41.6 kB
- Xet hash:
- 1e1d740fb67dc06ed80ac9d48663b3153c9f00220109c70c1b4b420ad2715ddb
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.