Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Doc/library/platform.rst
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,17 @@ Windows Platform
later (support for this was added in Python 2.6). It obviously
only runs on Win32 compatible platforms.

.. function:: win32_edition()

Returns a string representing the current Windows edition. Possible
values include but are not limited to ``'Enterprise'``, ``'IoTUAP'``,
``'ServerStandard'``, and ``'nanoserver'``.

.. function:: win32_is_iot()

Returns True if the windows edition returned by win32_edition is recognized
as an IoT edition.

Comment thread
paulmon marked this conversation as resolved.

Mac OS Platform
---------------
Expand Down
16 changes: 14 additions & 2 deletions Lib/distutils/_msvccompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,24 @@ def _find_vc2017():

return None, None

PLAT_SPEC_TO_RUNTIME = {
'x86' : 'x86',
'x86_amd64' : 'x64',
'x86_arm' : 'arm',
}

def _find_vcvarsall(plat_spec):
_, best_dir = _find_vc2017()
vcruntime = None
vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86'

if plat_spec in PLAT_SPEC_TO_RUNTIME:
vcruntime_plat = PLAT_SPEC_TO_RUNTIME[plat_spec]
else:
vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86'

if best_dir:
vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**",
"Microsoft.VC141.CRT", "vcruntime140.dll")
vcruntime_plat, "Microsoft.VC141.CRT", "vcruntime140.dll")
try:
import glob
vcruntime = glob.glob(vcredist, recursive=True)[-1]
Expand Down Expand Up @@ -178,6 +189,7 @@ def _find_exe(exe, paths=None):
PLAT_TO_VCVARS = {
'win32' : 'x86',
'win-amd64' : 'x86_amd64',
'win-arm32' : 'x86_arm',
}

# A set containing the DLLs that are guaranteed to be available for
Expand Down
11 changes: 10 additions & 1 deletion Lib/distutils/sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import sys

from .errors import DistutilsPlatformError
from .util import get_platform, get_host_platform

# These are needed in a couple of spots, so just compute them once.
PREFIX = os.path.normpath(sys.prefix)
Expand Down Expand Up @@ -449,7 +450,15 @@ def _init_nt():
# XXX hmmm.. a normal install puts include files here
g['INCLUDEPY'] = get_python_inc(plat_specific=0)

g['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
# if cross-compiling replace hardcoded platform-specific EXT_SUFFIX
# with an EXT_SUFFIX that matches the target platform
if get_platform() == get_host_platform():
g['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
else:
plat_tag = get_platform().replace('-', '_')
host_plat_tag = get_host_platform().replace('-', '_')
g['EXT_SUFFIX'] = _imp.extension_suffixes()[0].replace(host_plat_tag, plat_tag)
Comment thread
paulmon marked this conversation as resolved.
Outdated

g['EXE'] = ".exe"
g['VERSION'] = get_python_version().replace(".", "")
g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable))
Expand Down
23 changes: 21 additions & 2 deletions Lib/distutils/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from distutils import log
from distutils.errors import DistutilsByteCompileError

def get_platform ():
def get_host_platform ():
"""Return a string that identifies the current platform. This is used mainly to
distinguish platform-specific build directories and platform-specific built
distributions. Typically includes the OS name and version and the
Expand All @@ -38,6 +38,8 @@ def get_platform ():
if os.name == 'nt':
if 'amd64' in sys.version.lower():
return 'win-amd64'
if 'arm32' in sys.version.lower():
return 'win-arm32'
return sys.platform

# Set for cross builds explicitly
Expand Down Expand Up @@ -90,8 +92,25 @@ def get_platform ():

return "%s-%s-%s" % (osname, release, machine)

# get_platform ()
# get_host_platform ()

def get_platform ():
Comment thread
paulmon marked this conversation as resolved.
Outdated
TARGET_TO_PLAT = {
'x86' : 'win32',
'x64' : 'win-amd64',
'arm' : 'win-arm32',
}

targetPlatformFromEnvironment = os.environ.get('VSCMD_ARG_TGT_ARCH')

if targetPlatformFromEnvironment != None and targetPlatformFromEnvironment in TARGET_TO_PLAT:
targetPlatform = TARGET_TO_PLAT[targetPlatformFromEnvironment]
else:
targetPlatform = get_host_platform()

return targetPlatform
Comment thread
paulmon marked this conversation as resolved.
Outdated

# get_platform ()
Comment thread
paulmon marked this conversation as resolved.
Outdated

def convert_path (pathname):
"""Return 'pathname' as a name that will work on the native filesystem,
Expand Down
22 changes: 22 additions & 0 deletions Lib/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,28 @@ def _syscmd_ver(system='', release='', version='',
(6, None): "post2012ServerR2",
}

def win32_is_iot():
return win32_edition() in ('IoTUAP', 'NanoServer', 'WindowsCoreHeadless', 'IoTEdgeOS')

def win32_edition():
try:
from winreg import OpenKeyEx, QueryValueEx, CloseKey, HKEY_LOCAL_MACHINE
except ImportError:
from _winreg import OpenKeyEx, QueryValueEx, CloseKey, HKEY_LOCAL_MACHINE

key = None
try:
key = OpenKeyEx(HKEY_LOCAL_MACHINE,
r'SOFTWARE\Microsoft\Windows NT\CurrentVersion')
return QueryValueEx(key, 'EditionId')[0]
Comment thread
paulmon marked this conversation as resolved.
Outdated
except OSError:
pass
finally:
if key:
CloseKey(key)

return None

def win32_ver(release='', version='', csd='', ptype=''):
try:
from sys import getwindowsversion
Expand Down
2 changes: 2 additions & 0 deletions Lib/sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,8 @@ def get_platform():
if os.name == 'nt':
if 'amd64' in sys.version.lower():
return 'win-amd64'
if 'arm32' in sys.version.lower():
return 'win-arm32'
return sys.platform

if os.name != "posix" or not hasattr(os, 'uname'):
Expand Down
47 changes: 46 additions & 1 deletion Lib/test/test_codecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,39 @@ def check(input, expect):
self.assertEqual(coder(input), (expect, len(input)))
return check

# On small versions of Windows like Windows IoT or Windows Nano Server not all codepages are present
def is_code_page_present(cp):
from ctypes import POINTER, WINFUNCTYPE, windll, WinError, Structure
from ctypes.wintypes import BOOL, UINT, BYTE, WCHAR, UINT, DWORD

MAX_LEADBYTES = 12 # 5 ranges, 2 bytes ea., 0 term.
MAX_DEFAULTCHAR = 2 # single or double byte
MAX_PATH = 260
class CPINFOEXW(ctypes.Structure):
_fields_ = [("MaxCharSize", UINT),
("DefaultChar", BYTE*MAX_DEFAULTCHAR),
("LeadByte", BYTE*MAX_LEADBYTES),
("UnicodeDefaultChar", WCHAR),
("CodePage", UINT),
("CodePageName", WCHAR*MAX_PATH)]

prototype = WINFUNCTYPE(BOOL, UINT, DWORD, POINTER(CPINFOEXW))
GetCPInfoEx = prototype(("GetCPInfoExW", windll.kernel32))
Comment thread
paulmon marked this conversation as resolved.
Outdated

def errcheck(result, func, args):
if not result:
from ctypes import WinError
Comment thread
paulmon marked this conversation as resolved.
Outdated
raise OSError(2, "code page not found")
return args

from ctypes import WinError
Comment thread
paulmon marked this conversation as resolved.
Outdated
try:
GetCPInfoEx.errcheck = errcheck
Comment thread
paulmon marked this conversation as resolved.
Outdated
info = CPINFOEXW()
GetCPInfoEx(cp,0, info)
Comment thread
paulmon marked this conversation as resolved.
Outdated
return True
except OSError:
return False

class Queue(object):
"""
Expand Down Expand Up @@ -3078,9 +3111,21 @@ def test_multibyte_encoding(self):
def test_code_page_decode_flags(self):
# Issue #36312: For some code pages (e.g. UTF-7) flags for
# MultiByteToWideChar() must be set to 0.
if support.verbose:
sys.stdout.write('\n')
for cp in (50220, 50221, 50222, 50225, 50227, 50229,
*range(57002, 57011+1), 65000):
self.assertEqual(codecs.code_page_decode(cp, b'abc'), ('abc', 3))
# On small versions of Windows like Windows IoT
# not all codepages are present.
# A missing codepage causes an OSError exception
# so check for the codepage before decoding
if is_code_page_present(cp):
if support.verbose:
sys.stdout.write(" testing cp={}\n".format(cp))
self.assertEqual(codecs.code_page_decode(cp, b'abc'), ('abc', 3))
Comment thread
paulmon marked this conversation as resolved.
Outdated
else:
if support.verbose:
sys.stdout.write(" skipping cp={}\n".format(cp))
Comment thread
paulmon marked this conversation as resolved.
Outdated
self.assertEqual(codecs.code_page_decode(42, b'abc'),
('\uf061\uf062\uf063', 3))

Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_mimetypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import unittest

from test import support
from platform import win32_edition

# Tell it we don't know about external files:
mimetypes.knownfiles = []
Expand Down Expand Up @@ -116,6 +117,7 @@ def tearDown(self):
mimetypes.types_map.clear()
mimetypes.types_map.update(self.original_types_map)

@unittest.skipIf(win32_edition() in ('NanoServer', 'WindowsCoreHeadless', 'IoTEdgeOS'), "mime types registry keys not available on NanoServer")
Comment thread
paulmon marked this conversation as resolved.
Outdated
def test_registry_parsing(self):
# the original, minimum contents of the MIME database in the
# Windows registry is undocumented AFAIK.
Expand Down
3 changes: 2 additions & 1 deletion Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import uuid
import warnings
from test import support
from platform import win32_is_iot

try:
import resource
Expand Down Expand Up @@ -2446,7 +2447,7 @@ def test_bad_fd(self):
# Return None when an fd doesn't actually exist.
self.assertIsNone(os.device_encoding(123456))

@unittest.skipUnless(os.isatty(0) and (sys.platform.startswith('win') or
@unittest.skipUnless(os.isatty(0) and not win32_is_iot() and (sys.platform.startswith('win') or
(hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET'))),
'test requires a tty and either Windows or nl_langinfo(CODESET)')
def test_device_encoding(self):
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_startfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import unittest
from test import support
import os
import platform
import sys
from os import path

Expand All @@ -20,6 +21,7 @@ class TestCase(unittest.TestCase):
def test_nonexisting(self):
self.assertRaises(OSError, startfile, "nonexisting.vbs")

@unittest.skipIf(platform.win32_is_iot(), "starting files is not supported on Windows IoT Core or nanoserver")
def test_empty(self):
# We need to make sure the child process starts in a directory
# we're not about to delete. If we're running under -j, that
Expand Down
3 changes: 2 additions & 1 deletion Lib/test/test_sundry.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Do a minimal test of all the modules that aren't otherwise tested."""
import importlib
import platform
import sys
from test import support
import unittest
Expand All @@ -25,7 +26,7 @@ def test_untested_modules_can_be_imported(self):
import distutils.unixccompiler

import distutils.command.bdist_dumb
if sys.platform.startswith('win'):
if sys.platform.startswith('win') and not platform.win32_is_iot():
import distutils.command.bdist_msi
import distutils.command.bdist
import distutils.command.bdist_rpm
Expand Down
3 changes: 2 additions & 1 deletion Lib/test/test_winreg.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import unittest
from test import support
import threading
from platform import machine
from platform import machine, win32_edition

# Do this first so test will be skipped if module doesn't exist
support.import_module('winreg', required_on=['win'])
Expand Down Expand Up @@ -399,6 +399,7 @@ def test_named_arguments(self):
DeleteKeyEx(key=HKEY_CURRENT_USER, sub_key=test_key_name,
access=KEY_ALL_ACCESS, reserved=0)

@unittest.skipIf(win32_edition() in ('WindowsCoreHeadless', 'IoTEdgeOS'), "APIs not available on WindowsCoreHeadless")
def test_reflection_functions(self):
# Test that we can call the query, enable, and disable functions
# on a key which isn't on the reflection list with no consequences.
Expand Down
16 changes: 16 additions & 0 deletions PC/bdist_wininst/bdist_wininst.vcxproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<?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|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
Expand All @@ -9,6 +13,10 @@
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|ARM">
<Configuration>PGInstrument</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGInstrument|Win32">
<Configuration>PGInstrument</Configuration>
<Platform>Win32</Platform>
Expand All @@ -17,6 +25,10 @@
<Configuration>PGInstrument</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|ARM">
<Configuration>PGUpdate</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="PGUpdate|Win32">
<Configuration>PGUpdate</Configuration>
<Platform>Win32</Platform>
Expand All @@ -25,6 +37,10 @@
<Configuration>PGUpdate</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
Expand Down
2 changes: 1 addition & 1 deletion PCbuild/build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ echo.
echo.Available arguments:
echo. -c Release ^| Debug ^| PGInstrument ^| PGUpdate
echo. Set the configuration (default: Release)
echo. -p x64 ^| Win32
echo. -p x64 ^| Win32 ^| ARM
echo. Set the platform (default: Win32)
echo. -t Build ^| Rebuild ^| Clean ^| CleanAll
echo. Set the target manually
Expand Down
9 changes: 5 additions & 4 deletions PCbuild/pcbuild.sln
Original file line number Diff line number Diff line change
Expand Up @@ -595,16 +595,16 @@ Global
{D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|Win32.Build.0 = Release|Win32
{D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.ActiveCfg = Release|x64
{D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.Build.0 = Release|x64
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|ARM.ActiveCfg = Debug|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|ARM.ActiveCfg = Debug|ARM
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|Win32.ActiveCfg = Debug|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|x64.ActiveCfg = Release|x64
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|ARM.ActiveCfg = PGInstrument|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|ARM.ActiveCfg = PGInstrument|ARM
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|Win32.ActiveCfg = Release|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|x64.ActiveCfg = Release|x64
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|ARM.ActiveCfg = PGUpdate|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|ARM.ActiveCfg = PGUpdate|ARM
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|Win32.ActiveCfg = Release|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|x64.ActiveCfg = Release|x64
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|ARM.ActiveCfg = Release|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|ARM.ActiveCfg = Release|ARM
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|Win32.ActiveCfg = Release|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|x64.ActiveCfg = Release|x64
{447F05A8-F581-4CAC-A466-5AC7936E207E}.Debug|ARM.ActiveCfg = Debug|ARM
Expand Down Expand Up @@ -894,6 +894,7 @@ Global
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|x64.ActiveCfg = PGUpdate|x64
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.PGUpdate|x64.Build.0 = PGUpdate|x64
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|ARM.ActiveCfg = Release|ARM
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|ARM.Build.0 = Release|ARM
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|Win32.ActiveCfg = Release|Win32
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|Win32.Build.0 = Release|Win32
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Release|x64.ActiveCfg = Release|x64
Expand Down