From 67c161266b6c36612eaaf465a549da99112f482a Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Thu, 12 Jan 2017 12:44:38 -0700 Subject: [PATCH 01/12] Use built-in check_output (mostly) Replace one check_output to check_call since we don't use the output. --- setup.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/setup.py b/setup.py index f8409799a..d854cd141 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ from distutils.spawn import find_executable from distutils import log from platform import architecture -from subprocess import Popen, CalledProcessError, PIPE, check_call +from subprocess import check_output, check_call from glob import glob import fnmatch import sys @@ -179,7 +179,7 @@ def build_extension(self, ext): interop_file = _get_interop_filename() if not os.path.exists(interop_file): geninterop = os.path.join("tools", "geninterop", "geninterop.py") - _check_output([sys.executable, geninterop, interop_file]) + check_call([sys.executable, geninterop, interop_file]) cmd = [ _xbuild, @@ -285,18 +285,9 @@ def run(self): return install_data.run(self) -def _check_output(*popenargs, **kwargs): - """subprocess.check_output from python 2.7. - Added here to support building for earlier versions of Python. - """ - process = Popen(stdout=PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise CalledProcessError(retcode, cmd, output=output) +def _check_output(*args, **kwargs): + """Check output wrapper for py2/py3 compatibility""" + output = check_output(*args, **kwargs) if sys.version_info[0] > 2: return output.decode("ascii") return output From 9143b5491e27f2146159179beb0cb3432f98ee90 Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Fri, 27 Jan 2017 10:45:45 -0700 Subject: [PATCH 02/12] Rename build classes, and PLATFORM to ARCH --- setup.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/setup.py b/setup.py index d854cd141..992030ae2 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ CONFIG = "Release" # Release or Debug DEVTOOLS = "MsDev" if sys.platform == "win32" else "Mono" VERBOSITY = "minimal" # quiet, minimal, normal, detailed, diagnostic -PLATFORM = "x64" if architecture()[0] == "64bit" else "x86" +ARCH = "x64" if architecture()[0] == "64bit" else "x86" def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): @@ -41,7 +41,7 @@ def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): if use_windows_sdk: sdks_root = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows" kits_root = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots" - kits_suffix = os.path.join("bin", PLATFORM) + kits_suffix = os.path.join("bin", ARCH) keys_to_check.extend([ ("Windows Kit 10.0", kits_root, "KitsRoot10", kits_suffix), ("Windows Kit 8.1", kits_root, "KitsRoot81", kits_suffix), @@ -91,7 +91,7 @@ def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): if use_windows_sdk: localappdata = os.environ["LOCALAPPDATA"] pywinsdk = localappdata + r"\Programs\Common\Microsoft\Visual C++ for Python\9.0\WinSDK\Bin" - if PLATFORM == "x64": + if ARCH == "x64": pywinsdk += r"\x64" paths_to_check.append(("Visual C++ for Python", pywinsdk)) @@ -119,7 +119,7 @@ def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): "DevTools %s not supported (use MsDev or Mono)" % DEVTOOLS) -class PythonNET_BuildExt(build_ext): +class BuildExtPythonnet(build_ext): def build_extension(self, ext): """Builds the .pyd file using msbuild or xbuild""" if ext.name != "clr": @@ -185,7 +185,7 @@ def build_extension(self, ext): _xbuild, "pythonnet.sln", "/p:Configuration=%s" % _config, - "/p:Platform=%s" % PLATFORM, + "/p:Platform=%s" % ARCH, "/p:DefineConstants=\"%s\"" % _defines_sep.join(defines), "/p:PythonBuildDir=\"%s\"" % os.path.abspath(dest_dir), "/p:PythonInteropFile=\"%s\"" % os.path.basename(interop_file), @@ -250,7 +250,7 @@ def _install_packages(self): check_call(cmd, shell=use_shell) -class PythonNET_InstallLib(install_lib): +class InstallLibPythonnet(install_lib): def install(self): if not os.path.isdir(self.build_dir): self.warn("'%s' does not exist -- no Python modules to install" % @@ -262,16 +262,18 @@ def install(self): # only copy clr.pyd/.so for srcfile in glob(os.path.join(self.build_dir, "clr.*")): - destfile = os.path.join(self.install_dir, os.path.basename(srcfile)) + destfile = os.path.join( + self.install_dir, os.path.basename(srcfile)) self.copy_file(srcfile, destfile) -class PythonNET_InstallData(install_data): +class InstallDataPythonnet(install_data): def run(self): build_cmd = self.get_finalized_command("build_ext") install_cmd = self.get_finalized_command("install") build_lib = os.path.abspath(build_cmd.build_lib) - install_platlib = os.path.relpath(install_cmd.install_platlib, self.install_dir) + install_platlib = os.path.relpath( + install_cmd.install_platlib, self.install_dir) for i, data_files in enumerate(self.data_files): if isinstance(data_files, str): @@ -313,7 +315,8 @@ def _get_interop_filename(): sources.extend(glob("*" + ext)) for root, dirnames, filenames in os.walk("src"): - for ext in (".cs", ".csproj", ".sln", ".snk", ".config", ".il", ".py", ".c", ".h", ".ico"): + for ext in (".cs", ".csproj", ".sln", ".snk", ".config", ".il", + ".py", ".c", ".h", ".ico"): for filename in fnmatch.filter(filenames, "*" + ext): sources.append(os.path.join(root, filename)) @@ -360,9 +363,9 @@ def _get_interop_filename(): ], zip_safe=False, cmdclass={ - "build_ext": PythonNET_BuildExt, - "install_lib": PythonNET_InstallLib, - "install_data": PythonNET_InstallData, + "build_ext": BuildExtPythonnet, + "install_lib": InstallLibPythonnet, + "install_data": InstallDataPythonnet, }, setup_requires=setup_requires ) From 53590980202b62dc9854a1a21c0c43303722bdca Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Fri, 27 Jan 2017 10:50:13 -0700 Subject: [PATCH 03/12] Organize imports --- setup.py | 75 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/setup.py b/setup.py index 992030ae2..30f3719fb 100644 --- a/setup.py +++ b/setup.py @@ -6,36 +6,35 @@ an egg or wheel. """ -from setuptools import setup, Extension -from distutils.command.build_ext import build_ext -from distutils.command.install_lib import install_lib -from distutils.command.install_data import install_data -from distutils.sysconfig import get_config_var -from distutils.spawn import find_executable -from distutils import log -from platform import architecture -from subprocess import check_output, check_call -from glob import glob import fnmatch -import sys +import glob import os +import platform +import subprocess +import sys +import sysconfig +from distutils import log, spawn +from distutils.command import build_ext, install_data, install_lib + +from setuptools import Extension, setup CONFIG = "Release" # Release or Debug -DEVTOOLS = "MsDev" if sys.platform == "win32" else "Mono" VERBOSITY = "minimal" # quiet, minimal, normal, detailed, diagnostic -ARCH = "x64" if architecture()[0] == "64bit" else "x86" + +DEVTOOLS = "MsDev" if sys.platform == "win32" else "Mono" +ARCH = "x64" if platform.architecture()[0] == "64bit" else "x86" def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): """Return full path to one of the Microsoft build tools""" - path = find_executable(tool) + path = spawn.find_executable(tool) if path: return path - try: - import _winreg - except ImportError: - import winreg as _winreg + try: # PY2 + import _winreg as winreg + except ImportError: # PY3 + import winreg keys_to_check = [] if use_windows_sdk: @@ -64,16 +63,16 @@ def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): # read the possible tools paths from the various registry locations paths_to_check = [] - hreg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) + hreg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) try: for key_to_check in keys_to_check: sdk_name, key, value_name = key_to_check[:3] suffix = key_to_check[3] if len(key_to_check) > 3 else None hkey = None try: - hkey = _winreg.OpenKey(hreg, key) - val, type_ = _winreg.QueryValueEx(hkey, value_name) - if type_ != _winreg.REG_SZ: + hkey = winreg.OpenKey(hreg, key) + val, type_ = winreg.QueryValueEx(hkey, value_name) + if type_ != winreg.REG_SZ: continue if suffix: val = os.path.join(val, suffix) @@ -119,11 +118,11 @@ def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): "DevTools %s not supported (use MsDev or Mono)" % DEVTOOLS) -class BuildExtPythonnet(build_ext): +class BuildExtPythonnet(build_ext.build_ext): def build_extension(self, ext): """Builds the .pyd file using msbuild or xbuild""" if ext.name != "clr": - return build_ext.build_extension(self, ext) + return build_ext.build_ext.build_extension(self, ext) # install packages using nuget self._install_packages() @@ -157,7 +156,7 @@ def build_extension(self, ext): defines.append("MONO_LINUX") # Check if --enable-shared was set when Python was built - enable_shared = get_config_var("Py_ENABLE_SHARED") + enable_shared = sysconfig.get_config_var("Py_ENABLE_SHARED") if enable_shared: # Double-check if libpython is linked dynamically with python lddout = _check_output(["ldd", sys.executable]) @@ -179,7 +178,7 @@ def build_extension(self, ext): interop_file = _get_interop_filename() if not os.path.exists(interop_file): geninterop = os.path.join("tools", "geninterop", "geninterop.py") - check_call([sys.executable, geninterop, interop_file]) + subprocess.check_call([sys.executable, geninterop, interop_file]) cmd = [ _xbuild, @@ -198,8 +197,8 @@ def build_extension(self, ext): self.announce("Building: %s" % " ".join(cmd)) use_shell = True if DEVTOOLS == "Mono" else False - check_call(" ".join(cmd + ["/t:Clean"]), shell=use_shell) - check_call(" ".join(cmd + ["/t:Build"]), shell=use_shell) + subprocess.check_call(" ".join(cmd + ["/t:Clean"]), shell=use_shell) + subprocess.check_call(" ".join(cmd + ["/t:Build"]), shell=use_shell) if DEVTOOLS == "Mono": self._build_monoclr(ext) @@ -211,7 +210,7 @@ def _get_manifest(self, build_dir): cmd = [mt, '-inputresource:"%s"' % sys.executable, '-out:"%s"' % manifest] self.announce("Extracting manifest from %s" % sys.executable) - check_call(" ".join(cmd), shell=False) + subprocess.check_call(" ".join(cmd), shell=False) return manifest def _build_monoclr(self, ext): @@ -231,7 +230,7 @@ def _build_monoclr(self, ext): extra_compile_args=cflags.split(" "), extra_link_args=libs.split(" ")) - build_ext.build_extension(self, clr_ext) + build_ext.build_ext.build_extension(self, clr_ext) def _install_packages(self): """install packages using nuget""" @@ -243,14 +242,14 @@ def _install_packages(self): cmd = "%s update -self" % nuget self.announce("Updating NuGet: %s" % cmd) - check_call(cmd, shell=use_shell) + subprocess.check_call(cmd, shell=use_shell) cmd = "%s restore pythonnet.sln -o packages" % nuget self.announce("Installing packages: %s" % cmd) - check_call(cmd, shell=use_shell) + subprocess.check_call(cmd, shell=use_shell) -class InstallLibPythonnet(install_lib): +class InstallLibPythonnet(install_lib.install_lib): def install(self): if not os.path.isdir(self.build_dir): self.warn("'%s' does not exist -- no Python modules to install" % @@ -261,13 +260,13 @@ def install(self): self.mkpath(self.install_dir) # only copy clr.pyd/.so - for srcfile in glob(os.path.join(self.build_dir, "clr.*")): + for srcfile in glob.glob(os.path.join(self.build_dir, "clr.*")): destfile = os.path.join( self.install_dir, os.path.basename(srcfile)) self.copy_file(srcfile, destfile) -class InstallDataPythonnet(install_data): +class InstallDataPythonnet(install_data.install_data): def run(self): build_cmd = self.get_finalized_command("build_ext") install_cmd = self.get_finalized_command("install") @@ -284,12 +283,12 @@ def run(self): dest = data_files[0].format(install_platlib=install_platlib) self.data_files[i] = dest, data_files[1] - return install_data.run(self) + return install_data.install_data.run(self) def _check_output(*args, **kwargs): """Check output wrapper for py2/py3 compatibility""" - output = check_output(*args, **kwargs) + output = subprocess.check_output(*args, **kwargs) if sys.version_info[0] > 2: return output.decode("ascii") return output @@ -312,7 +311,7 @@ def _get_interop_filename(): sources = [] for ext in (".sln", ".snk", ".config"): - sources.extend(glob("*" + ext)) + sources.extend(glob.glob("*" + ext)) for root, dirnames, filenames in os.walk("src"): for ext in (".cs", ".csproj", ".sln", ".snk", ".config", ".il", From 0078d7600e0337d2cec77773f7c2aa58f81b90c8 Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Fri, 27 Jan 2017 13:51:10 -0700 Subject: [PATCH 04/12] Move to appropriate context --- setup.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/setup.py b/setup.py index 30f3719fb..c160009af 100644 --- a/setup.py +++ b/setup.py @@ -103,21 +103,6 @@ def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): raise RuntimeError("%s could not be found" % tool) -if DEVTOOLS == "MsDev": - _xbuild = "\"%s\"" % _find_msbuild_tool("msbuild.exe") - _defines_sep = ";" - _config = "%sWin" % CONFIG - -elif DEVTOOLS == "Mono": - _xbuild = "xbuild" - _defines_sep = "," - _config = "%sMono" % CONFIG - -else: - raise NotImplementedError( - "DevTools %s not supported (use MsDev or Mono)" % DEVTOOLS) - - class BuildExtPythonnet(build_ext.build_ext): def build_extension(self, ext): """Builds the .pyd file using msbuild or xbuild""" @@ -180,6 +165,19 @@ def build_extension(self, ext): geninterop = os.path.join("tools", "geninterop", "geninterop.py") subprocess.check_call([sys.executable, geninterop, interop_file]) + if DEVTOOLS == "MsDev": + _xbuild = '"{0}"'.format(_find_msbuild_tool("msbuild.exe")) + _defines_sep = ";" + _config = "{0}Win".format(CONFIG) + + elif DEVTOOLS == "Mono": + _xbuild = "xbuild" + _defines_sep = "," + _config = "{0}Mono".format(CONFIG) + else: + raise NotImplementedError( + "DevTool {0} not supported (use MsDev/Mono)".format(DEVTOOLS)) + cmd = [ _xbuild, "pythonnet.sln", From 8fe702a0907adf123bec849eeddfe7f0ca966c27 Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Fri, 27 Jan 2017 14:44:00 -0700 Subject: [PATCH 05/12] Refactor registry search Use context manager for closing registries --- setup.py | 128 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 55 deletions(-) diff --git a/setup.py b/setup.py index c160009af..365dc2147 100644 --- a/setup.py +++ b/setup.py @@ -6,6 +6,7 @@ an egg or wheel. """ +import collections import fnmatch import glob import os @@ -24,83 +25,100 @@ DEVTOOLS = "MsDev" if sys.platform == "win32" else "Mono" ARCH = "x64" if platform.architecture()[0] == "64bit" else "x86" +############################################################################### +# Windows Keys Constants for MSBUILD tools +RegKey = collections.namedtuple('RegKey', 'sdk_name key value_name suffix') +vs_python = "Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\WinSDK" +vs_root = "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{0}" +sdks_root = "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v{0}Win32Tools" +kits_root = "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots" +kits_suffix = os.path.join("bin", ARCH) +WIN_SDK_KEYS = ( + RegKey(sdk_name="Windows Kit 10.0", key=kits_root, + value_name="KitsRoot10", suffix=kits_suffix), + + RegKey(sdk_name="Windows Kit 8.1", key=kits_root, + value_name="KitsRoot81", suffix=kits_suffix), + + RegKey(sdk_name="Windows Kit 8.0", key=kits_root, + value_name="KitsRoot", suffix=kits_suffix), + + RegKey(sdk_name="Windows SDK 7.1A", key=sdks_root.format("7.1A\\WinSDK-"), + value_name="InstallationFolder", suffix=""), + + RegKey(sdk_name="Windows SDK 7.1", key=sdks_root.format("7.1\\WinSDK"), + value_name="InstallationFolder", suffix=""), + + RegKey(sdk_name="Windows SDK 7.0A", key=sdks_root.format("7.0A\\WinSDK-"), + value_name="InstallationFolder", suffix=""), + + RegKey(sdk_name="Windows SDK 7.0", key=sdks_root.format("7.0\\WinSDK"), + value_name="InstallationFolder", suffix=""), + + RegKey(sdk_name="Windows SDK 6.0A", key=sdks_root.format("6.0A\\WinSDK"), + value_name="InstallationFolder", suffix=""), +) + +VS_KEYS = ( + RegKey(sdk_name="MSBuild 14", key=vs_root.format("14.0"), + value_name="MSBuildToolsPath", suffix=""), + + RegKey(sdk_name="MSBuild 12", key=vs_root.format("12.0"), + value_name="MSBuildToolsPath", suffix=""), + + RegKey(sdk_name="MSBuild 4", key=vs_root.format("4.0"), + value_name="MSBuildToolsPath", suffix=""), + + RegKey(sdk_name="MSBuild 3.5", key=vs_root.format("3.5"), + value_name="MSBuildToolsPath", suffix=""), + + RegKey(sdk_name="MSBuild 2.0", key=vs_root.format("2.0"), + value_name="MSBuildToolsPath", suffix=""), +) + + +############################################################################### def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): """Return full path to one of the Microsoft build tools""" + # Search in PATH first path = spawn.find_executable(tool) if path: return path + # Search within registry to find build tools try: # PY2 import _winreg as winreg except ImportError: # PY3 import winreg - keys_to_check = [] - if use_windows_sdk: - sdks_root = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows" - kits_root = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots" - kits_suffix = os.path.join("bin", ARCH) - keys_to_check.extend([ - ("Windows Kit 10.0", kits_root, "KitsRoot10", kits_suffix), - ("Windows Kit 8.1", kits_root, "KitsRoot81", kits_suffix), - ("Windows Kit 8.0", kits_root, "KitsRoot", kits_suffix), - ("Windows SDK 7.1A", sdks_root + r"\v7.1A\WinSDK-Win32Tools", "InstallationFolder"), - ("Windows SDK 7.1", sdks_root + r"\v7.1\WinSDKWin32Tools", "InstallationFolder"), - ("Windows SDK 7.0A", sdks_root + r"\v7.0A\WinSDK-Win32Tools", "InstallationFolder"), - ("Windows SDK 7.0", sdks_root + r"\v7.0\WinSDKWin32Tools", "InstallationFolder"), - ("Windows SDK 6.0A", sdks_root + r"\v6.0A\WinSDKWin32Tools", "InstallationFolder") - ]) - else: - vs_root = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions" - keys_to_check.extend([ - ("MSBuild 14", vs_root + r"\14.0", "MSBuildToolsPath"), - ("MSBuild 12", vs_root + r"\12.0", "MSBuildToolsPath"), - ("MSBuild 4", vs_root + r"\4.0", "MSBuildToolsPath"), - ("MSBuild 3.5", vs_root + r"\3.5", "MSBuildToolsPath"), - ("MSBuild 2.0", vs_root + r"\2.0", "MSBuildToolsPath") - ]) - - # read the possible tools paths from the various registry locations - paths_to_check = [] - hreg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - try: - for key_to_check in keys_to_check: - sdk_name, key, value_name = key_to_check[:3] - suffix = key_to_check[3] if len(key_to_check) > 3 else None - hkey = None - try: - hkey = winreg.OpenKey(hreg, key) - val, type_ = winreg.QueryValueEx(hkey, value_name) + keys_to_check = WIN_SDK_KEYS if use_windows_sdk else VS_KEYS + for rkey in keys_to_check: + try: + with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, rkey.key) as hkey: + val, type_ = winreg.QueryValueEx(hkey, rkey.value_name) if type_ != winreg.REG_SZ: continue - if suffix: - val = os.path.join(val, suffix) - paths_to_check.append((sdk_name, val)) - except WindowsError: - pass - finally: - if hkey: - hkey.Close() - finally: - hreg.Close() + path = os.path.join(val, rkey.suffix, tool) + if os.path.exists(path): + log.info("Using {0} from {1}".format(tool, rkey.sdk_name)) + return path + except WindowsError: + # Key doesn't exist + pass # Add Visual C++ for Python as a fall-back in case one # of the other Windows SDKs isn't installed if use_windows_sdk: + sdk_name = "Visual C++ for Python" localappdata = os.environ["LOCALAPPDATA"] - pywinsdk = localappdata + r"\Programs\Common\Microsoft\Visual C++ for Python\9.0\WinSDK\Bin" - if ARCH == "x64": - pywinsdk += r"\x64" - paths_to_check.append(("Visual C++ for Python", pywinsdk)) - - for sdk_name, path in paths_to_check: - path = os.path.join(path, tool) + suffix = "Bin\\x64" if ARCH == "x64" else "Bin" + path = os.path.join(localappdata, vs_python, suffix, tool) if os.path.exists(path): - log.info("Using %s from %s" % (tool, sdk_name)) + log.info("Using {0} from {1}".format(tool, sdk_name)) return path - raise RuntimeError("%s could not be found" % tool) + raise RuntimeError("{0} could not be found".format(tool)) class BuildExtPythonnet(build_ext.build_ext): From de630171ef0516fb1a038248674f482027df91ac Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Sat, 28 Jan 2017 09:25:57 -0700 Subject: [PATCH 06/12] Format setup.py --- setup.py | 81 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/setup.py b/setup.py index 365dc2147..bd048f71f 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,8 @@ DEVTOOLS = "MsDev" if sys.platform == "win32" else "Mono" ARCH = "x64" if platform.architecture()[0] == "64bit" else "x86" +PY_MAJOR = sys.version_info[0] +PY_MINOR = sys.version_info[1] ############################################################################### # Windows Keys Constants for MSBUILD tools @@ -144,9 +146,9 @@ def build_extension(self, ext): unicode_width = ctypes.sizeof(ctypes.c_wchar) defines = [ - "PYTHON%d%d" % (sys.version_info[:2]), - "PYTHON%d" % (sys.version_info[:1]), # Python Major Version - "UCS%d" % unicode_width, + "PYTHON{0}{1}".format(PY_MAJOR, PY_MINOR), + "PYTHON{0}".format(PY_MAJOR), # Python Major Version + "UCS{0}".format(unicode_width), ] if CONFIG == "Debug": @@ -185,12 +187,10 @@ def build_extension(self, ext): if DEVTOOLS == "MsDev": _xbuild = '"{0}"'.format(_find_msbuild_tool("msbuild.exe")) - _defines_sep = ";" _config = "{0}Win".format(CONFIG) elif DEVTOOLS == "Mono": _xbuild = "xbuild" - _defines_sep = "," _config = "{0}Mono".format(CONFIG) else: raise NotImplementedError( @@ -198,38 +198,38 @@ def build_extension(self, ext): cmd = [ _xbuild, - "pythonnet.sln", - "/p:Configuration=%s" % _config, - "/p:Platform=%s" % ARCH, - "/p:DefineConstants=\"%s\"" % _defines_sep.join(defines), - "/p:PythonBuildDir=\"%s\"" % os.path.abspath(dest_dir), - "/p:PythonInteropFile=\"%s\"" % os.path.basename(interop_file), - "/verbosity:%s" % VERBOSITY, + 'pythonnet.sln', + '/p:Configuration={}'.format(_config), + '/p:Platform={}'.format(ARCH), + '/p:DefineConstants="{}"'.format(','.join(defines)), + '/p:PythonBuildDir="{}"'.format(os.path.abspath(dest_dir)), + '/p:PythonInteropFile="{}"'.format(os.path.basename(interop_file)), + '/verbosity:{}'.format(VERBOSITY), ] manifest = self._get_manifest(dest_dir) if manifest: - cmd.append("/p:PythonManifest=\"%s\"" % manifest) + cmd.append('/p:PythonManifest="{0}"'.format(manifest)) - self.announce("Building: %s" % " ".join(cmd)) + self.announce("Building: {0}".format(" ".join(cmd))) use_shell = True if DEVTOOLS == "Mono" else False subprocess.check_call(" ".join(cmd + ["/t:Clean"]), shell=use_shell) subprocess.check_call(" ".join(cmd + ["/t:Build"]), shell=use_shell) if DEVTOOLS == "Mono": - self._build_monoclr(ext) + self._build_monoclr() def _get_manifest(self, build_dir): if DEVTOOLS == "MsDev" and sys.version_info[:2] > (2, 5): mt = _find_msbuild_tool("mt.exe", use_windows_sdk=True) manifest = os.path.abspath(os.path.join(build_dir, "app.manifest")) - cmd = [mt, '-inputresource:"%s"' % sys.executable, - '-out:"%s"' % manifest] - self.announce("Extracting manifest from %s" % sys.executable) + cmd = [mt, '-inputresource:"{0}"'.format(sys.executable), + '-out:"{0}"'.format(manifest)] + self.announce("Extracting manifest from {}".format(sys.executable)) subprocess.check_call(" ".join(cmd), shell=False) return manifest - def _build_monoclr(self, ext): + def _build_monoclr(self): mono_libs = _check_output("pkg-config --libs mono-2", shell=True) mono_cflags = _check_output("pkg-config --cflags mono-2", shell=True) glib_libs = _check_output("pkg-config --libs glib-2.0", shell=True) @@ -238,13 +238,15 @@ def _build_monoclr(self, ext): libs = mono_libs.strip() + " " + glib_libs.strip() # build the clr python module - clr_ext = Extension("clr", - sources=[ - "src/monoclr/pynetinit.c", - "src/monoclr/clrmod.c" - ], - extra_compile_args=cflags.split(" "), - extra_link_args=libs.split(" ")) + clr_ext = Extension( + "clr", + sources=[ + "src/monoclr/pynetinit.c", + "src/monoclr/clrmod.c" + ], + extra_compile_args=cflags.split(" "), + extra_link_args=libs.split(" ") + ) build_ext.build_ext.build_extension(self, clr_ext) @@ -253,23 +255,23 @@ def _install_packages(self): nuget = os.path.join("tools", "nuget", "nuget.exe") use_shell = False if DEVTOOLS == "Mono": - nuget = "mono %s" % nuget + nuget = "mono {0}".format(nuget) use_shell = True - cmd = "%s update -self" % nuget - self.announce("Updating NuGet: %s" % cmd) + cmd = "{0} update -self".format(nuget) + self.announce("Updating NuGet: {0}".format(cmd)) subprocess.check_call(cmd, shell=use_shell) - cmd = "%s restore pythonnet.sln -o packages" % nuget - self.announce("Installing packages: %s" % cmd) + cmd = "{0} restore pythonnet.sln -o packages".format(nuget) + self.announce("Installing packages: {0}".format(cmd)) subprocess.check_call(cmd, shell=use_shell) class InstallLibPythonnet(install_lib.install_lib): def install(self): if not os.path.isdir(self.build_dir): - self.warn("'%s' does not exist -- no Python modules to install" % - self.build_dir) + self.warn("'{0}' does not exist -- no Python modules" + " to install".format(self.build_dir)) return if not os.path.exists(self.install_dir): @@ -305,9 +307,9 @@ def run(self): def _check_output(*args, **kwargs): """Check output wrapper for py2/py3 compatibility""" output = subprocess.check_output(*args, **kwargs) - if sys.version_info[0] > 2: - return output.decode("ascii") - return output + if PY_MAJOR == 2: + return output + return output.decode("ascii") def _get_interop_filename(): @@ -316,8 +318,9 @@ def _get_interop_filename(): as most windows users won't have Clang installed, which is required to generate the file. """ - interop_file = "interop%d%d%s.cs" % (sys.version_info[0], sys.version_info[1], getattr(sys, "abiflags", "")) - return os.path.join("src", "runtime", interop_file) + interop_filename = "interop{0}{1}{2}.cs".format( + PY_MAJOR, PY_MINOR, getattr(sys, "abiflags", "")) + return os.path.join("src", "runtime", interop_filename) if __name__ == "__main__": @@ -382,5 +385,5 @@ def _get_interop_filename(): "install_lib": InstallLibPythonnet, "install_data": InstallDataPythonnet, }, - setup_requires=setup_requires + setup_requires=setup_requires, ) From ee210011a7b285e16ce4523f24b6fe5c36c3d01f Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Sat, 28 Jan 2017 15:31:02 -0700 Subject: [PATCH 07/12] Organize functions --- setup.py | 141 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 68 deletions(-) diff --git a/setup.py b/setup.py index bd048f71f..847bde9a1 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ import subprocess import sys import sysconfig -from distutils import log, spawn +from distutils import spawn from distutils.command import build_ext, install_data, install_lib from setuptools import Extension, setup @@ -81,46 +81,23 @@ ############################################################################### -def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): - """Return full path to one of the Microsoft build tools""" - # Search in PATH first - path = spawn.find_executable(tool) - if path: - return path - - # Search within registry to find build tools - try: # PY2 - import _winreg as winreg - except ImportError: # PY3 - import winreg - - keys_to_check = WIN_SDK_KEYS if use_windows_sdk else VS_KEYS - for rkey in keys_to_check: - try: - with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, rkey.key) as hkey: - val, type_ = winreg.QueryValueEx(hkey, rkey.value_name) - if type_ != winreg.REG_SZ: - continue - path = os.path.join(val, rkey.suffix, tool) - if os.path.exists(path): - log.info("Using {0} from {1}".format(tool, rkey.sdk_name)) - return path - except WindowsError: - # Key doesn't exist - pass - - # Add Visual C++ for Python as a fall-back in case one - # of the other Windows SDKs isn't installed - if use_windows_sdk: - sdk_name = "Visual C++ for Python" - localappdata = os.environ["LOCALAPPDATA"] - suffix = "Bin\\x64" if ARCH == "x64" else "Bin" - path = os.path.join(localappdata, vs_python, suffix, tool) - if os.path.exists(path): - log.info("Using {0} from {1}".format(tool, sdk_name)) - return path +def _check_output(*args, **kwargs): + """Check output wrapper for py2/py3 compatibility""" + output = subprocess.check_output(*args, **kwargs) + if PY_MAJOR == 2: + return output + return output.decode("ascii") - raise RuntimeError("{0} could not be found".format(tool)) + +def _get_interop_filename(): + """interopXX.cs is auto-generated as part of the build. + For common windows platforms pre-generated files are included + as most windows users won't have Clang installed, which is + required to generate the file. + """ + interop_filename = "interop{0}{1}{2}.cs".format( + PY_MAJOR, PY_MINOR, getattr(sys, "abiflags", "")) + return os.path.join("src", "runtime", interop_filename) class BuildExtPythonnet(build_ext.build_ext): @@ -139,6 +116,7 @@ def build_extension(self, ext): # Up to Python 3.2 sys.maxunicode is used to determine the size of # Py_UNICODE, but from 3.3 onwards Py_UNICODE is a typedef of wchar_t. + # TODO: Is this doing the right check for Py27? if sys.version_info[:2] <= (3, 2): unicode_width = 2 if sys.maxunicode < 0x10FFFF else 4 else: @@ -186,7 +164,7 @@ def build_extension(self, ext): subprocess.check_call([sys.executable, geninterop, interop_file]) if DEVTOOLS == "MsDev": - _xbuild = '"{0}"'.format(_find_msbuild_tool("msbuild.exe")) + _xbuild = '"{0}"'.format(self._find_msbuild_tool("msbuild.exe")) _config = "{0}Win".format(CONFIG) elif DEVTOOLS == "Mono": @@ -220,14 +198,15 @@ def build_extension(self, ext): self._build_monoclr() def _get_manifest(self, build_dir): - if DEVTOOLS == "MsDev" and sys.version_info[:2] > (2, 5): - mt = _find_msbuild_tool("mt.exe", use_windows_sdk=True) - manifest = os.path.abspath(os.path.join(build_dir, "app.manifest")) - cmd = [mt, '-inputresource:"{0}"'.format(sys.executable), - '-out:"{0}"'.format(manifest)] - self.announce("Extracting manifest from {}".format(sys.executable)) - subprocess.check_call(" ".join(cmd), shell=False) - return manifest + if DEVTOOLS != "MsDev": + return + mt = self._find_msbuild_tool("mt.exe", use_windows_sdk=True) + manifest = os.path.abspath(os.path.join(build_dir, "app.manifest")) + cmd = [mt, '-inputresource:"{0}"'.format(sys.executable), + '-out:"{0}"'.format(manifest)] + self.announce("Extracting manifest from {}".format(sys.executable)) + subprocess.check_call(" ".join(cmd), shell=False) + return manifest def _build_monoclr(self): mono_libs = _check_output("pkg-config --libs mono-2", shell=True) @@ -266,6 +245,50 @@ def _install_packages(self): self.announce("Installing packages: {0}".format(cmd)) subprocess.check_call(cmd, shell=use_shell) + def _find_msbuild_tool(self, tool="msbuild.exe", use_windows_sdk=False): + """Return full path to one of the Microsoft build tools""" + # Search in PATH first + path = spawn.find_executable(tool) + if path: + return path + + # Search within registry to find build tools + try: # PY2 + import _winreg as winreg + except ImportError: # PY3 + import winreg + + keys_to_check = WIN_SDK_KEYS if use_windows_sdk else VS_KEYS + hklm = winreg.HKEY_LOCAL_MACHINE + for rkey in keys_to_check: + try: + with winreg.OpenKey(hklm, rkey.key) as hkey: + val, type_ = winreg.QueryValueEx(hkey, rkey.value_name) + if type_ != winreg.REG_SZ: + continue + path = os.path.join(val, rkey.suffix, tool) + if os.path.exists(path): + self.announce("Using {0} from {1}".format( + tool, rkey.sdk_name)) + return path + except WindowsError: + # Key doesn't exist + pass + + # Add Visual C++ for Python as a fall-back in case one + # of the other Windows SDKs isn't installed. + # TODO: Extend checking by using setuptools/msvc.py? + if use_windows_sdk: + sdk_name = "Visual C++ for Python" + localappdata = os.environ["LOCALAPPDATA"] + suffix = "Bin\\x64" if ARCH == "x64" else "Bin" + path = os.path.join(localappdata, vs_python, suffix, tool) + if os.path.exists(path): + self.announce("Using {0} from {1}".format(tool, sdk_name)) + return path + + raise RuntimeError("{0} could not be found".format(tool)) + class InstallLibPythonnet(install_lib.install_lib): def install(self): @@ -304,25 +327,7 @@ def run(self): return install_data.install_data.run(self) -def _check_output(*args, **kwargs): - """Check output wrapper for py2/py3 compatibility""" - output = subprocess.check_output(*args, **kwargs) - if PY_MAJOR == 2: - return output - return output.decode("ascii") - - -def _get_interop_filename(): - """interopXX.cs is auto-generated as part of the build. - For common windows platforms pre-generated files are included - as most windows users won't have Clang installed, which is - required to generate the file. - """ - interop_filename = "interop{0}{1}{2}.cs".format( - PY_MAJOR, PY_MINOR, getattr(sys, "abiflags", "")) - return os.path.join("src", "runtime", interop_filename) - - +############################################################################### if __name__ == "__main__": setupdir = os.path.dirname(__file__) if setupdir: From b32b4d000000388b9f81aaf0c04f58f1885684ee Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Sat, 28 Jan 2017 15:37:34 -0700 Subject: [PATCH 08/12] Create get_source_files function --- setup.py | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/setup.py b/setup.py index 847bde9a1..cc345ac7f 100644 --- a/setup.py +++ b/setup.py @@ -100,6 +100,24 @@ def _get_interop_filename(): return os.path.join("src", "runtime", interop_filename) +def _get_source_files(): + """Walk project and collect the files needed for ext_module""" + for ext in (".sln", ".snk", ".config"): + for path in glob.glob("*" + ext): + yield path + + for root, dirnames, filenames in os.walk("src"): + for ext in (".cs", ".csproj", ".sln", ".snk", ".config", ".il", + ".py", ".c", ".h", ".ico"): + for filename in fnmatch.filter(filenames, "*" + ext): + yield os.path.join(root, filename) + + for root, dirnames, filenames in os.walk("tools"): + for ext in (".exe", ".py", ".c", ".h"): + for filename in fnmatch.filter(filenames, "*" + ext): + yield os.path.join(root, filename) + + class BuildExtPythonnet(build_ext.build_ext): def build_extension(self, ext): """Builds the .pyd file using msbuild or xbuild""" @@ -333,21 +351,6 @@ def run(self): if setupdir: os.chdir(setupdir) - sources = [] - for ext in (".sln", ".snk", ".config"): - sources.extend(glob.glob("*" + ext)) - - for root, dirnames, filenames in os.walk("src"): - for ext in (".cs", ".csproj", ".sln", ".snk", ".config", ".il", - ".py", ".c", ".h", ".ico"): - for filename in fnmatch.filter(filenames, "*" + ext): - sources.append(os.path.join(root, filename)) - - for root, dirnames, filenames in os.walk("tools"): - for ext in (".exe", ".py", ".c", ".h"): - for filename in fnmatch.filter(filenames, "*" + ext): - sources.append(os.path.join(root, filename)) - setup_requires = [] interop_file = _get_interop_filename() if not os.path.exists(interop_file): @@ -377,7 +380,7 @@ def run(self): 'Operating System :: MacOS :: MacOS X', ], ext_modules=[ - Extension("clr", sources=sources) + Extension("clr", sources=list(_get_source_files())) ], data_files=[ ("{install_platlib}", [ From f52082947b655e8c8237687781b1f8a9d89b0953 Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Sat, 28 Jan 2017 15:55:25 -0700 Subject: [PATCH 09/12] No need to put `setup` in `if __name__==...` --- setup.py | 98 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/setup.py b/setup.py index cc345ac7f..51211e6c7 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,8 @@ from setuptools import Extension, setup +# Allow config/verbosity to be set from cli +# http://stackoverflow.com/a/4792601/5208670 CONFIG = "Release" # Release or Debug VERBOSITY = "minimal" # quiet, minimal, normal, detailed, diagnostic @@ -346,52 +348,50 @@ def run(self): ############################################################################### -if __name__ == "__main__": - setupdir = os.path.dirname(__file__) - if setupdir: - os.chdir(setupdir) - - setup_requires = [] - interop_file = _get_interop_filename() - if not os.path.exists(interop_file): - setup_requires.append("pycparser") - - setup( - name="pythonnet", - version="2.2.2", - description=".Net and Mono integration for Python", - url='https://pythonnet.github.io/', - license='MIT', - author="The Python for .Net developers", - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: C#', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX :: Linux', - 'Operating System :: MacOS :: MacOS X', - ], - ext_modules=[ - Extension("clr", sources=list(_get_source_files())) - ], - data_files=[ - ("{install_platlib}", [ - "{build_lib}/Python.Runtime.dll", - "Python.Runtime.dll.config"]), - ], - zip_safe=False, - cmdclass={ - "build_ext": BuildExtPythonnet, - "install_lib": InstallLibPythonnet, - "install_data": InstallDataPythonnet, - }, - setup_requires=setup_requires, - ) +setupdir = os.path.dirname(__file__) +if setupdir: + os.chdir(setupdir) + +setup_requires = [] +if not os.path.exists(_get_interop_filename()): + setup_requires.append("pycparser") + +setup( + name="pythonnet", + version="2.2.2", + description=".Net and Mono integration for Python", + url='https://pythonnet.github.io/', + license='MIT', + author="The Python for .Net developers", + setup_requires=setup_requires, + ext_modules=[ + Extension("clr", sources=list(_get_source_files())) + ], + data_files=[ + ("{install_platlib}", [ + "{build_lib}/Python.Runtime.dll", + "Python.Runtime.dll.config"]), + ], + cmdclass={ + "build_ext": BuildExtPythonnet, + "install_lib": InstallLibPythonnet, + "install_data": InstallDataPythonnet, + }, + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: C#', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX :: Linux', + 'Operating System :: MacOS :: MacOS X', + ], + zip_safe=False, +) From 126e5f0acd74017a67fbab29a9297ab39d30937e Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Sat, 28 Jan 2017 16:20:23 -0700 Subject: [PATCH 10/12] Add long_description --- setup.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/setup.py b/setup.py index 51211e6c7..ea20a99d3 100644 --- a/setup.py +++ b/setup.py @@ -120,6 +120,15 @@ def _get_source_files(): yield os.path.join(root, filename) +def _get_long_description(): + """Helper to populate long_description for pypi releases""" + try: + import pypandoc + return pypandoc.convert('README.md', 'rst') + except ImportError: + return '.Net and Mono integration for Python' + + class BuildExtPythonnet(build_ext.build_ext): def build_extension(self, ext): """Builds the .pyd file using msbuild or xbuild""" @@ -364,6 +373,7 @@ def run(self): license='MIT', author="The Python for .Net developers", setup_requires=setup_requires, + long_description=_get_long_description(), ext_modules=[ Extension("clr", sources=list(_get_source_files())) ], From ccf96cbe8edcbb73a0f45269d5349e7431828bd3 Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Sat, 28 Jan 2017 17:28:21 -0700 Subject: [PATCH 11/12] Clean-up getinterop --- tools/geninterop/geninterop.py | 46 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/tools/geninterop/geninterop.py b/tools/geninterop/geninterop.py index 946e30217..bf5fdb96b 100644 --- a/tools/geninterop/geninterop.py +++ b/tools/geninterop/geninterop.py @@ -15,16 +15,19 @@ from __future__ import print_function -from distutils.sysconfig import get_config_var -from subprocess import Popen, CalledProcessError, PIPE -from pycparser import c_parser, c_ast import logging -import sys import os +import sys +import sysconfig +import subprocess + +from pycparser import c_ast, c_parser _log = logging.getLogger() logging.basicConfig(level=logging.DEBUG) +PY_MAJOR = sys.version_info[0] +PY_MINOR = sys.version_info[1] # rename some members from their C name when generating the C# _typeoffset_member_renames = { @@ -33,6 +36,14 @@ } +def _check_output(*args, **kwargs): + """Check output wrapper for py2/py3 compatibility""" + output = subprocess.check_output(*args, **kwargs) + if PY_MAJOR == 2: + return output + return output.decode("ascii") + + class AstParser(object): """Walk an AST and determine the members of all structs""" @@ -147,23 +158,6 @@ def __get_struct_name(self, node): return node.name or "_struct_%d" % id(node) -def check_output(*popenargs, **kwargs): - """subprocess.check_output from python 2.7. - Added here to support building for earlier versions of Python. - """ - process = Popen(stdout=PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise CalledProcessError(retcode, cmd) - if sys.version_info[0] > 2: - return output.decode("ascii") - return output - - def preprocess_python_headers(): """Return Python.h pre-processed, ready for parsing. Requires clang. @@ -172,7 +166,7 @@ def preprocess_python_headers(): "fake_libc_include") include_dirs = [fake_libc_include] - include_py = get_config_var("INCLUDEPY") + include_py = sysconfig.get_config_var("INCLUDEPY") include_dirs.append(include_py) defines = [ @@ -195,7 +189,7 @@ def preprocess_python_headers(): # normalize as the parser doesn't like windows line endings. lines = [] - for line in check_output(cmd).splitlines(): + for line in _check_output(cmd).splitlines(): if line.startswith("#"): line = line.replace("\\", "/") lines.append(line) @@ -206,7 +200,7 @@ def gen_interop_code(members): """Generate the TypeOffset C# class""" defines = [ - "PYTHON%d%d" % (sys.version_info[:2]) + "PYTHON{0}{1}".format(PY_MAJOR, PY_MINOR) ] if hasattr(sys, "abiflags"): @@ -217,6 +211,8 @@ def gen_interop_code(members): if "u" in sys.abiflags: defines.append("PYTHON_WITH_WIDE_UNICODE") + filename = os.path.basename(__file__) + defines_str = " && ".join(defines) class_definition = """ // Auto-generated by %s. // DO NOT MODIFIY BY HAND. @@ -252,7 +248,7 @@ def gen_interop_code(members): } // Auto-generated from PyHeapTypeObject in Python.h -""" % (os.path.basename(__file__), " && ".join(defines)) +""" % (filename, defines_str) # All the members are sizeof(void*) so we don't need to do any # extra work to determine the size based on the type. From 65210335d2e4b5efffdb9d840503fb402e037752 Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Sat, 28 Jan 2017 17:38:58 -0700 Subject: [PATCH 12/12] Fix setup.py log messages self.announce is based on an incomplete logger. use debug_print that turns on when env_var DISTUTILS_DEBUG is present --- setup.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index ea20a99d3..3ef19afd7 100644 --- a/setup.py +++ b/setup.py @@ -189,6 +189,7 @@ def build_extension(self, ext): # check the interop file exists, and create it if it doesn't interop_file = _get_interop_filename() if not os.path.exists(interop_file): + self.debug_print("Creating {0}".format(interop_file)) geninterop = os.path.join("tools", "geninterop", "geninterop.py") subprocess.check_call([sys.executable, geninterop, interop_file]) @@ -218,7 +219,7 @@ def build_extension(self, ext): if manifest: cmd.append('/p:PythonManifest="{0}"'.format(manifest)) - self.announce("Building: {0}".format(" ".join(cmd))) + self.debug_print("Building: {0}".format(" ".join(cmd))) use_shell = True if DEVTOOLS == "Mono" else False subprocess.check_call(" ".join(cmd + ["/t:Clean"]), shell=use_shell) subprocess.check_call(" ".join(cmd + ["/t:Build"]), shell=use_shell) @@ -233,7 +234,7 @@ def _get_manifest(self, build_dir): manifest = os.path.abspath(os.path.join(build_dir, "app.manifest")) cmd = [mt, '-inputresource:"{0}"'.format(sys.executable), '-out:"{0}"'.format(manifest)] - self.announce("Extracting manifest from {}".format(sys.executable)) + self.debug_print("Extracting manifest from {}".format(sys.executable)) subprocess.check_call(" ".join(cmd), shell=False) return manifest @@ -267,11 +268,11 @@ def _install_packages(self): use_shell = True cmd = "{0} update -self".format(nuget) - self.announce("Updating NuGet: {0}".format(cmd)) + self.debug_print("Updating NuGet: {0}".format(cmd)) subprocess.check_call(cmd, shell=use_shell) cmd = "{0} restore pythonnet.sln -o packages".format(nuget) - self.announce("Installing packages: {0}".format(cmd)) + self.debug_print("Installing packages: {0}".format(cmd)) subprocess.check_call(cmd, shell=use_shell) def _find_msbuild_tool(self, tool="msbuild.exe", use_windows_sdk=False): @@ -297,7 +298,7 @@ def _find_msbuild_tool(self, tool="msbuild.exe", use_windows_sdk=False): continue path = os.path.join(val, rkey.suffix, tool) if os.path.exists(path): - self.announce("Using {0} from {1}".format( + self.debug_print("Using {0} from {1}".format( tool, rkey.sdk_name)) return path except WindowsError: @@ -313,7 +314,7 @@ def _find_msbuild_tool(self, tool="msbuild.exe", use_windows_sdk=False): suffix = "Bin\\x64" if ARCH == "x64" else "Bin" path = os.path.join(localappdata, vs_python, suffix, tool) if os.path.exists(path): - self.announce("Using {0} from {1}".format(tool, sdk_name)) + self.debug_print("Using {0} from {1}".format(tool, sdk_name)) return path raise RuntimeError("{0} could not be found".format(tool))