bpo-40501: Replace ctypes code in uuid with native module (GH-19948)

This commit is contained in:
Steve Dower 2020-05-12 23:32:32 +01:00 committed by GitHub
parent f453221c8b
commit d6b727e2c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 248 additions and 186 deletions

View File

@ -852,17 +852,6 @@ eth0 Link encap:Ethernet HWaddr 12:34:56:78:90:ab
node = self.uuid._netstat_getnode() node = self.uuid._netstat_getnode()
self.check_node(node, 'netstat') self.check_node(node, 'netstat')
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
def test_ipconfig_getnode(self):
node = self.uuid._ipconfig_getnode()
self.check_node(node, 'ipconfig')
@unittest.skipUnless(importable('win32wnet'), 'requires win32wnet')
@unittest.skipUnless(importable('netbios'), 'requires netbios')
def test_netbios_getnode(self):
node = self.uuid._netbios_getnode()
self.check_node(node)
def test_random_getnode(self): def test_random_getnode(self):
node = self.uuid._random_getnode() node = self.uuid._random_getnode()
# The multicast bit, i.e. the least significant bit of first octet, # The multicast bit, i.e. the least significant bit of first octet,
@ -874,6 +863,13 @@ eth0 Link encap:Ethernet HWaddr 12:34:56:78:90:ab
node2 = self.uuid._random_getnode() node2 = self.uuid._random_getnode()
self.assertNotEqual(node2, node, '%012x' % node) self.assertNotEqual(node2, node, '%012x' % node)
class TestInternalsWithoutExtModule(BaseTestInternals, unittest.TestCase):
uuid = py_uuid
@unittest.skipUnless(c_uuid, 'requires the C _uuid module')
class TestInternalsWithExtModule(BaseTestInternals, unittest.TestCase):
uuid = c_uuid
@unittest.skipUnless(os.name == 'posix', 'requires Posix') @unittest.skipUnless(os.name == 'posix', 'requires Posix')
def test_unix_getnode(self): def test_unix_getnode(self):
if not importable('_uuid') and not importable('ctypes'): if not importable('_uuid') and not importable('ctypes'):
@ -885,19 +881,10 @@ eth0 Link encap:Ethernet HWaddr 12:34:56:78:90:ab
self.check_node(node, 'unix') self.check_node(node, 'unix')
@unittest.skipUnless(os.name == 'nt', 'requires Windows') @unittest.skipUnless(os.name == 'nt', 'requires Windows')
@unittest.skipUnless(importable('ctypes'), 'requires ctypes')
def test_windll_getnode(self): def test_windll_getnode(self):
node = self.uuid._windll_getnode() node = self.uuid._windll_getnode()
self.check_node(node) self.check_node(node)
class TestInternalsWithoutExtModule(BaseTestInternals, unittest.TestCase):
uuid = py_uuid
@unittest.skipUnless(c_uuid, 'requires the C _uuid module')
class TestInternalsWithExtModule(BaseTestInternals, unittest.TestCase):
uuid = c_uuid
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -555,178 +555,44 @@ def _netstat_getnode():
return _find_mac_under_heading('netstat', '-ian', b'Address') return _find_mac_under_heading('netstat', '-ian', b'Address')
def _ipconfig_getnode(): def _ipconfig_getnode():
"""Get the hardware address on Windows by running ipconfig.exe.""" """[DEPRECATED] Get the hardware address on Windows."""
import os, re, subprocess # bpo-40501: UuidCreateSequential() is now the only supported approach
first_local_mac = None return _windll_getnode()
dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
try:
import ctypes
buffer = ctypes.create_string_buffer(300)
ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
dirs.insert(0, buffer.value.decode('mbcs'))
except:
pass
for dir in dirs:
try:
proc = subprocess.Popen([os.path.join(dir, 'ipconfig'), '/all'],
stdout=subprocess.PIPE,
encoding="oem")
except OSError:
continue
with proc:
for line in proc.stdout:
value = line.split(':')[-1].strip().lower()
if re.fullmatch('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
mac = int(value.replace('-', ''), 16)
if _is_universal(mac):
return mac
first_local_mac = first_local_mac or mac
return first_local_mac or None
def _netbios_getnode(): def _netbios_getnode():
"""Get the hardware address on Windows using NetBIOS calls. """[DEPRECATED] Get the hardware address on Windows."""
See http://support.microsoft.com/kb/118623 for details.""" # bpo-40501: UuidCreateSequential() is now the only supported approach
import win32wnet, netbios return _windll_getnode()
first_local_mac = None
ncb = netbios.NCB()
ncb.Command = netbios.NCBENUM
ncb.Buffer = adapters = netbios.LANA_ENUM()
adapters._pack()
if win32wnet.Netbios(ncb) != 0:
return None
adapters._unpack()
for i in range(adapters.length):
ncb.Reset()
ncb.Command = netbios.NCBRESET
ncb.Lana_num = ord(adapters.lana[i])
if win32wnet.Netbios(ncb) != 0:
continue
ncb.Reset()
ncb.Command = netbios.NCBASTAT
ncb.Lana_num = ord(adapters.lana[i])
ncb.Callname = '*'.ljust(16)
ncb.Buffer = status = netbios.ADAPTER_STATUS()
if win32wnet.Netbios(ncb) != 0:
continue
status._unpack()
bytes = status.adapter_address[:6]
if len(bytes) != 6:
continue
mac = int.from_bytes(bytes, 'big')
if _is_universal(mac):
return mac
first_local_mac = first_local_mac or mac
return first_local_mac or None
_generate_time_safe = _UuidCreate = None
_has_uuid_generate_time_safe = None
# Import optional C extension at toplevel, to help disabling it when testing # Import optional C extension at toplevel, to help disabling it when testing
try: try:
import _uuid import _uuid
_generate_time_safe = getattr(_uuid, "generate_time_safe", None)
_UuidCreate = getattr(_uuid, "UuidCreate", None)
_has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
except ImportError: except ImportError:
_uuid = None _uuid = None
_generate_time_safe = None
_UuidCreate = None
_has_uuid_generate_time_safe = None
def _load_system_functions(): def _load_system_functions():
""" """[DEPRECATED] Platform-specific functions loaded at import time"""
Try to load platform-specific functions for generating uuids.
"""
global _generate_time_safe, _UuidCreate, _has_uuid_generate_time_safe
if _has_uuid_generate_time_safe is not None:
return
_has_uuid_generate_time_safe = False
if sys.platform == "darwin" and int(os.uname().release.split('.')[0]) < 9:
# The uuid_generate_* functions are broken on MacOS X 10.5, as noted
# in issue #8621 the function generates the same sequence of values
# in the parent process and all children created using fork (unless
# those children use exec as well).
#
# Assume that the uuid_generate functions are broken from 10.5 onward,
# the test can be adjusted when a later version is fixed.
pass
elif _uuid is not None:
_generate_time_safe = _uuid.generate_time_safe
_has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
return
try:
# If we couldn't find an extension module, try ctypes to find
# system routines for UUID generation.
# Thanks to Thomas Heller for ctypes and for his help with its use here.
import ctypes
import ctypes.util
# The uuid_generate_* routines are provided by libuuid on at least
# Linux and FreeBSD, and provided by libc on Mac OS X.
_libnames = ['uuid']
if not sys.platform.startswith('win'):
_libnames.append('c')
for libname in _libnames:
try:
lib = ctypes.CDLL(ctypes.util.find_library(libname))
except Exception: # pragma: nocover
continue
# Try to find the safe variety first.
if hasattr(lib, 'uuid_generate_time_safe'):
_uuid_generate_time_safe = lib.uuid_generate_time_safe
# int uuid_generate_time_safe(uuid_t out);
def _generate_time_safe():
_buffer = ctypes.create_string_buffer(16)
res = _uuid_generate_time_safe(_buffer)
return bytes(_buffer.raw), res
_has_uuid_generate_time_safe = True
break
elif hasattr(lib, 'uuid_generate_time'): # pragma: nocover
_uuid_generate_time = lib.uuid_generate_time
# void uuid_generate_time(uuid_t out);
_uuid_generate_time.restype = None
def _generate_time_safe():
_buffer = ctypes.create_string_buffer(16)
_uuid_generate_time(_buffer)
return bytes(_buffer.raw), None
break
# On Windows prior to 2000, UuidCreate gives a UUID containing the
# hardware address. On Windows 2000 and later, UuidCreate makes a
# random UUID and UuidCreateSequential gives a UUID containing the
# hardware address. These routines are provided by the RPC runtime.
# NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last
# 6 bytes returned by UuidCreateSequential are fixed, they don't appear
# to bear any relationship to the MAC address of any network device
# on the box.
try:
lib = ctypes.windll.rpcrt4
except:
lib = None
_UuidCreate = getattr(lib, 'UuidCreateSequential',
getattr(lib, 'UuidCreate', None))
except Exception as exc:
import warnings
warnings.warn(f"Could not find fallback ctypes uuid functions: {exc}",
ImportWarning)
def _unix_getnode(): def _unix_getnode():
"""Get the hardware address on Unix using the _uuid extension module """Get the hardware address on Unix using the _uuid extension module."""
or ctypes.""" if _generate_time_safe:
_load_system_functions() uuid_time, _ = _generate_time_safe()
uuid_time, _ = _generate_time_safe() return UUID(bytes=uuid_time).node
return UUID(bytes=uuid_time).node
def _windll_getnode(): def _windll_getnode():
"""Get the hardware address on Windows using ctypes.""" """Get the hardware address on Windows using the _uuid extension module."""
import ctypes if _UuidCreate:
_load_system_functions() uuid_bytes = _UuidCreate()
_buffer = ctypes.create_string_buffer(16) return UUID(bytes_le=uuid_bytes).node
if _UuidCreate(_buffer) == 0:
return UUID(bytes=bytes_(_buffer.raw)).node
def _random_getnode(): def _random_getnode():
"""Get a random node ID.""" """Get a random node ID."""
@ -755,7 +621,8 @@ if _LINUX:
elif _DARWIN: elif _DARWIN:
_OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode] _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
elif _WINDOWS: elif _WINDOWS:
_OS_GETTERS = [_netbios_getnode, _ipconfig_getnode] # bpo-40201: _windll_getnode will always succeed, so these are not needed
_OS_GETTERS = []
elif _AIX: elif _AIX:
_OS_GETTERS = [_netstat_getnode] _OS_GETTERS = [_netstat_getnode]
else: else:
@ -802,7 +669,6 @@ def uuid1(node=None, clock_seq=None):
# When the system provides a version-1 UUID generator, use it (but don't # When the system provides a version-1 UUID generator, use it (but don't
# use UuidCreate here because its UUIDs don't conform to RFC 4122). # use UuidCreate here because its UUIDs don't conform to RFC 4122).
_load_system_functions()
if _generate_time_safe is not None and node is clock_seq is None: if _generate_time_safe is not None and node is clock_seq is None:
uuid_time, safely_generated = _generate_time_safe() uuid_time, safely_generated = _generate_time_safe()
try: try:

View File

@ -0,0 +1,2 @@
:mod:`uuid` no longer uses :mod:`ctypes` to load :file:`libuuid` or
:file:`rpcrt4.dll` at runtime.

View File

@ -1,5 +1,5 @@
/* /*
* Python UUID module that wraps libuuid - * Python UUID module that wraps libuuid or Windows rpcrt4.dll.
* DCE compatible Universally Unique Identifier library. * DCE compatible Universally Unique Identifier library.
*/ */
@ -12,6 +12,12 @@
#include <uuid.h> #include <uuid.h>
#endif #endif
#ifdef MS_WINDOWS
#include <rpc.h>
#endif
#ifndef MS_WINDOWS
static PyObject * static PyObject *
py_uuid_generate_time_safe(PyObject *Py_UNUSED(context), py_uuid_generate_time_safe(PyObject *Py_UNUSED(context),
PyObject *Py_UNUSED(ignored)) PyObject *Py_UNUSED(ignored))
@ -31,17 +37,50 @@ py_uuid_generate_time_safe(PyObject *Py_UNUSED(context),
return Py_BuildValue("y#i", buf, sizeof(uuid), (int) status); return Py_BuildValue("y#i", buf, sizeof(uuid), (int) status);
# else # else
return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status); return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status);
# endif # endif /* HAVE_UUID_CREATE */
#else #else /* HAVE_UUID_GENERATE_TIME_SAFE */
uuid_generate_time(uuid); uuid_generate_time(uuid);
return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None); return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None);
#endif #endif /* HAVE_UUID_GENERATE_TIME_SAFE */
} }
#else /* MS_WINDOWS */
static PyObject *
py_UuidCreate(PyObject *Py_UNUSED(context),
PyObject *Py_UNUSED(ignored))
{
UUID uuid;
RPC_STATUS res;
Py_BEGIN_ALLOW_THREADS
res = UuidCreateSequential(&uuid);
Py_END_ALLOW_THREADS
switch (res) {
case RPC_S_OK:
case RPC_S_UUID_LOCAL_ONLY:
case RPC_S_UUID_NO_ADDRESS:
/*
All success codes, but the latter two indicate that the UUID is random
rather than based on the MAC address. If the OS can't figure this out,
neither can we, so we'll take it anyway.
*/
return Py_BuildValue("y#", (const char *)&uuid, sizeof(uuid));
}
PyErr_SetFromWindowsErr(res);
return NULL;
}
#endif /* MS_WINDOWS */
static int static int
uuid_exec(PyObject *module) { uuid_exec(PyObject *module) {
assert(sizeof(uuid_t) == 16); assert(sizeof(uuid_t) == 16);
#ifdef HAVE_UUID_GENERATE_TIME_SAFE #if defined(MS_WINDOWS)
int has_uuid_generate_time_safe = 0;
#elif defined(HAVE_UUID_GENERATE_TIME_SAFE)
int has_uuid_generate_time_safe = 1; int has_uuid_generate_time_safe = 1;
#else #else
int has_uuid_generate_time_safe = 0; int has_uuid_generate_time_safe = 0;
@ -54,7 +93,12 @@ uuid_exec(PyObject *module) {
} }
static PyMethodDef uuid_methods[] = { static PyMethodDef uuid_methods[] = {
#if defined(HAVE_UUID_UUID_H) || defined(HAVE_UUID_H)
{"generate_time_safe", py_uuid_generate_time_safe, METH_NOARGS, NULL}, {"generate_time_safe", py_uuid_generate_time_safe, METH_NOARGS, NULL},
#endif
#if defined(MS_WINDOWS)
{"UuidCreate", py_UuidCreate, METH_NOARGS, NULL},
#endif
{NULL, NULL, 0, NULL} /* sentinel */ {NULL, NULL, 0, NULL} /* sentinel */
}; };

115
PCbuild/_uuid.vcxproj Normal file
View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|ARM">
<Configuration>PGInstrument</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|ARM64">
<Configuration>PGInstrument</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|Win32">
<Configuration>PGInstrument</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|x64">
<Configuration>PGInstrument</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|ARM">
<Configuration>PGUpdate</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|ARM64">
<Configuration>PGUpdate</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|Win32">
<Configuration>PGUpdate</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|x64">
<Configuration>PGUpdate</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{CB435430-EBB1-478B-8F4E-C256F6838F55}</ProjectGuid>
<RootNamespace>_uuid</RootNamespace>
<Keyword>Win32Proj</Keyword>
<SupportPGO>false</SupportPGO>
</PropertyGroup>
<Import Project="python.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<TargetExt>.pyd</TargetExt>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="pyproject.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Modules\_uuidmodule.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\python_nt.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Modules\_uuidmodule.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -51,7 +51,7 @@
<!-- pyshellext.dll --> <!-- pyshellext.dll -->
<Projects Include="pyshellext.vcxproj" /> <Projects Include="pyshellext.vcxproj" />
<!-- Extension modules --> <!-- Extension modules -->
<ExtensionModules Include="_asyncio;_decimal;_elementtree;_msi;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound" /> <ExtensionModules Include="_asyncio;_decimal;_elementtree;_msi;_multiprocessing;_overlapped;pyexpat;_queue;select;unicodedata;winsound;_uuid" />
<ExtensionModules Include="_ctypes" Condition="$(IncludeCTypes)" /> <ExtensionModules Include="_ctypes" Condition="$(IncludeCTypes)" />
<!-- Extension modules that require external sources --> <!-- Extension modules that require external sources -->
<ExternalModules Include="_bz2;_lzma;_sqlite3" /> <ExternalModules Include="_bz2;_lzma;_sqlite3" />

View File

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.27130.2024 VisualStudioVersion = 16.0.30028.174
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{553EC33E-9816-4996-A660-5D6186A0B0B3}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{553EC33E-9816-4996-A660-5D6186A0B0B3}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
@ -103,6 +103,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "venvwlauncher", "venvwlaunc
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythonw_uwp", "pythonw_uwp.vcxproj", "{AB603547-1E2A-45B3-9E09-B04596006393}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythonw_uwp", "pythonw_uwp.vcxproj", "{AB603547-1E2A-45B3-9E09-B04596006393}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_uuid", "_uuid.vcxproj", "{CB435430-EBB1-478B-8F4E-C256F6838F55}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM Debug|ARM = Debug|ARM
@ -1440,6 +1442,38 @@ Global
{AB603547-1E2A-45B3-9E09-B04596006393}.Release|Win32.Build.0 = Release|Win32 {AB603547-1E2A-45B3-9E09-B04596006393}.Release|Win32.Build.0 = Release|Win32
{AB603547-1E2A-45B3-9E09-B04596006393}.Release|x64.ActiveCfg = Release|x64 {AB603547-1E2A-45B3-9E09-B04596006393}.Release|x64.ActiveCfg = Release|x64
{AB603547-1E2A-45B3-9E09-B04596006393}.Release|x64.Build.0 = Release|x64 {AB603547-1E2A-45B3-9E09-B04596006393}.Release|x64.Build.0 = Release|x64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Debug|ARM.ActiveCfg = Debug|ARM
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Debug|ARM.Build.0 = Debug|ARM
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Debug|ARM64.ActiveCfg = Debug|ARM64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Debug|ARM64.Build.0 = Debug|ARM64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Debug|Win32.ActiveCfg = Debug|Win32
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Debug|Win32.Build.0 = Debug|Win32
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Debug|x64.ActiveCfg = Debug|x64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Debug|x64.Build.0 = Debug|x64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGInstrument|ARM.ActiveCfg = PGInstrument|ARM
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGInstrument|ARM.Build.0 = PGInstrument|ARM
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGInstrument|ARM64.ActiveCfg = PGInstrument|ARM64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGInstrument|ARM64.Build.0 = PGInstrument|ARM64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGInstrument|Win32.Build.0 = PGInstrument|Win32
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGInstrument|x64.ActiveCfg = PGInstrument|x64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGInstrument|x64.Build.0 = PGInstrument|x64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGUpdate|ARM.ActiveCfg = PGUpdate|ARM
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGUpdate|ARM.Build.0 = PGUpdate|ARM
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGUpdate|ARM64.ActiveCfg = PGUpdate|ARM64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGUpdate|ARM64.Build.0 = PGUpdate|ARM64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGUpdate|Win32.Build.0 = PGUpdate|Win32
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGUpdate|x64.ActiveCfg = PGUpdate|x64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.PGUpdate|x64.Build.0 = PGUpdate|x64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|ARM.ActiveCfg = Release|ARM
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|ARM.Build.0 = Release|ARM
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|ARM64.ActiveCfg = Release|ARM64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|ARM64.Build.0 = Release|ARM64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|Win32.ActiveCfg = Release|Win32
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|Win32.Build.0 = Release|Win32
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|x64.ActiveCfg = Release|x64
{CB435430-EBB1-478B-8F4E-C256F6838F55}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define exts=pyexpat;select;unicodedata;winsound;_bz2;_elementtree;_socket;_ssl;_msi;_ctypes;_hashlib;_multiprocessing;_lzma;_decimal;_overlapped;_sqlite3;_asyncio;_queue ?> <?define exts=pyexpat;select;unicodedata;winsound;_bz2;_elementtree;_socket;_ssl;_msi;_ctypes;_hashlib;_multiprocessing;_lzma;_decimal;_overlapped;_sqlite3;_asyncio;_queue;_uuid ?>
<Fragment> <Fragment>
<DirectoryRef Id="Lib_venv_scripts_nt" /> <DirectoryRef Id="Lib_venv_scripts_nt" />