From f811e510c184e312fe8820a8b32f083418c5a998 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Sun, 8 Nov 2020 00:18:33 +0100 Subject: [PATCH 01/12] Convert projects to SDK style - Convert tests to SDK style - Delete obsolete files and add common build props - Convert Runtime to SDK style and always use .NET Standard - Convert console to SDK style - Convert clrmodule to SDK style and switch to NXPorts --- .gitignore | 4 + Directory.Build.props | 17 + NuGet.config | 7 - appveyor.yml | 25 +- clr.py | 23 + pyproject.toml | 2 + pythonnet.15.sln | 403 ---------- requirements.txt | 4 +- setup.py | 713 ++++-------------- src/SharedAssemblyInfo.cs | 28 - src/clrmodule/ClrModule.cs | 2 +- src/clrmodule/Properties/AssemblyInfo.cs | 6 - src/clrmodule/clrmodule.15.csproj | 95 --- src/clrmodule/clrmodule.csproj | 105 +-- src/clrmodule/packages.config | 4 - src/console/Console.15.csproj | 94 --- src/console/Console.csproj | 100 +-- src/console/Properties/AssemblyInfo.cs | 8 - src/embed_tests/Program.cs | 19 - .../Python.EmbeddingTest.15.csproj | 121 --- src/embed_tests/Python.EmbeddingTest.csproj | 154 +--- src/embed_tests/TestDomainReload.cs | 4 +- src/embed_tests/TestPyWith.cs | 6 +- src/embed_tests/pyimport.cs | 8 +- src/perf_tests/Python.PerformanceTests.csproj | 8 +- src/runtime/Properties/AssemblyInfo.cs | 8 - src/runtime/Python.Runtime.15.csproj | 176 ----- src/runtime/Python.Runtime.csproj | 234 +----- src/runtime/nativecall.cs | 8 - ...ionPolifills.cs => ReflectionPolyfills.cs} | 6 +- src/runtime/runtime.cs | 4 +- src/testing/Python.Test.15.csproj | 86 --- src/testing/Python.Test.csproj | 116 +-- tools/nuget/nuget.exe | Bin 4596440 -> 0 bytes tools/vswhere/vswhere.exe | Bin 458872 -> 0 bytes 35 files changed, 315 insertions(+), 2283 deletions(-) create mode 100644 Directory.Build.props delete mode 100644 NuGet.config create mode 100644 clr.py create mode 100644 pyproject.toml delete mode 100644 pythonnet.15.sln delete mode 100644 src/SharedAssemblyInfo.cs delete mode 100644 src/clrmodule/clrmodule.15.csproj delete mode 100644 src/clrmodule/packages.config delete mode 100644 src/console/Console.15.csproj delete mode 100644 src/console/Properties/AssemblyInfo.cs delete mode 100644 src/embed_tests/Program.cs delete mode 100644 src/embed_tests/Python.EmbeddingTest.15.csproj delete mode 100644 src/runtime/Python.Runtime.15.csproj rename src/runtime/polyfill/{ReflectionPolifills.cs => ReflectionPolyfills.cs} (89%) delete mode 100644 src/testing/Python.Test.15.csproj delete mode 100644 tools/nuget/nuget.exe delete mode 100644 tools/vswhere/vswhere.exe diff --git a/.gitignore b/.gitignore index 87f7fe4ed..e40c8b709 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ /src/runtime/interopNative.cs +# Configuration data +configured.props + # General binaries and Build results *.dll *.exe @@ -17,6 +20,7 @@ __pycache__/ build/ dist/ *.egg-info/ +.eggs/ # Unit test / coverage reports htmlcov/ diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 000000000..5ad0c0e77 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,17 @@ + + + 3.0.0 + Copyright (c) 2006-2020 The Contributors of the Python.NET Project + pythonnet + Python.NET + 7.3 + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/NuGet.config b/NuGet.config deleted file mode 100644 index 5210cd6c9..000000000 --- a/NuGet.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index a91afdcba..1468a7b71 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,7 +10,7 @@ platform: environment: global: - PYTHONUNBUFFERED: True + PYTHONUNBUFFERED: 'True' PYTHONWARNINGS: 'ignore:::wheel.pep425tags:' CODECOV_ENV: PYTHON_VERSION, PLATFORM @@ -47,35 +47,16 @@ init: install: - python -m pip install -U pip - pip install --upgrade -r requirements.txt --quiet - - pip install pycparser --quiet - - # Install OpenCover. Can't put on `packages.config`, not Mono compatible - - .\tools\nuget\nuget.exe install OpenCover -OutputDirectory packages -Verbosity quiet build_script: + - python setup.py configure # Create clean `sdist`. Only used for releases - python setup.py --quiet sdist - # Build `wheel` with coverage of `setup.py` - - coverage run setup.py bdist_wheel %BUILD_OPTS% + - python setup.py bdist_wheel test_script: - pip install --no-index --find-links=.\dist\ pythonnet - ps: .\ci\appveyor_run_tests.ps1 -on_finish: - # Temporary disable multiple upload due to codecov limit of 20 per commit. - # https://docs.codecov.io/blog/week-8-2017 - - coverage xml -i - # - codecov --file coverage.xml --flags setup_windows - # - codecov --file py.coverage --flags python_tests - # - codecov --file cs.coverage --flags embedded_tests - - codecov --file py.coverage cs.coverage coverage.xml --flags setup_windows - artifacts: - path: dist\* - - path: '.\src\runtime\bin\*.nupkg' - -notifications: - - provider: Slack - incoming_webhook: - secure: 2S/t6rGHdbwoxehnvn5KgfsHrBFEtwnPD7M5olGErmz70oWFVpqoWd/EvDwh7rKZGdOTjDmpwcukc2xi5VRaGHbBAqFYS3tAdgAMrcaTNWs= diff --git a/clr.py b/clr.py new file mode 100644 index 000000000..ead32bbbf --- /dev/null +++ b/clr.py @@ -0,0 +1,23 @@ +""" +Legacy Python.NET loader for backwards compatibility +""" + +def _load(): + import os, sys + import importlib.util as util + + if sys.maxsize > 2 ** 32: + arch = "amd64" + else: + arch = "x86" + + path = os.path.join(os.path.dirname(__file__), "pythonnet", "dlls", arch, "clr.pyd") + del sys.modules["clr"] + + spec = util.spec_from_file_location("clr", path) + clr = util.module_from_spec(spec) + spec.loader.exec_module(clr) + + sys.modules["clr"] = clr + +_load() \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..51000e45b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,2 @@ +[build-system] +requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4"] diff --git a/pythonnet.15.sln b/pythonnet.15.sln deleted file mode 100644 index 76986c84f..000000000 --- a/pythonnet.15.sln +++ /dev/null @@ -1,403 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29102.190 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Runtime.15", "src\runtime\Python.Runtime.15.csproj", "{2759F4FF-716B-4828-916F-50FA86613DFC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.EmbeddingTest.15", "src\embed_tests\Python.EmbeddingTest.15.csproj", "{66B8D01A-9906-452A-B09E-BF75EA76468F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "clrmodule.15", "src\clrmodule\clrmodule.15.csproj", "{E08678D4-9A52-4AD5-B63D-8EBC7399981B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Console.15", "src\console\Console.15.csproj", "{CDAD305F-8E72-492C-A314-64CF58D472A0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Test.15", "src\testing\Python.Test.15.csproj", "{F94B547A-E97E-4500-8D53-B4D64D076E5F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.PerformanceTests", "src\perf_tests\Python.PerformanceTests.csproj", "{6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo", "Repo", "{441A0123-F4C6-4EE4-9AEE-315FD79BE2D5}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - .gitignore = .gitignore - CHANGELOG.md = CHANGELOG.md - README.rst = README.rst - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CI", "CI", "{D301657F-5EAF-4534-B280-B858D651B2E5}" - ProjectSection(SolutionItems) = preProject - appveyor.yml = appveyor.yml - ci\appveyor_build_recipe.ps1 = ci\appveyor_build_recipe.ps1 - ci\appveyor_run_tests.ps1 = ci\appveyor_run_tests.ps1 - .github\workflows\main.yml = .github\workflows\main.yml - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{57F5D701-F265-4736-A5A2-07249E7A4DA3}" - ProjectSection(SolutionItems) = preProject - setup.py = setup.py - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "conda.recipe", "conda.recipe", "{7FD2404D-0CE8-4645-8DFB-766470E2150E}" - ProjectSection(SolutionItems) = preProject - conda.recipe\bld.bat = conda.recipe\bld.bat - conda.recipe\meta.yaml = conda.recipe\meta.yaml - conda.recipe\README.md = conda.recipe\README.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{BC426F42-8494-4AA5-82C9-5109ACD97BD1}" - ProjectSection(SolutionItems) = preProject - tools\geninterop\geninterop.py = tools\geninterop\geninterop.py - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - DebugMono|Any CPU = DebugMono|Any CPU - DebugMono|x64 = DebugMono|x64 - DebugMono|x86 = DebugMono|x86 - DebugMonoPY3|Any CPU = DebugMonoPY3|Any CPU - DebugMonoPY3|x64 = DebugMonoPY3|x64 - DebugMonoPY3|x86 = DebugMonoPY3|x86 - DebugWin|Any CPU = DebugWin|Any CPU - DebugWin|x64 = DebugWin|x64 - DebugWin|x86 = DebugWin|x86 - DebugWinPY3|Any CPU = DebugWinPY3|Any CPU - DebugWinPY3|x64 = DebugWinPY3|x64 - DebugWinPY3|x86 = DebugWinPY3|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - ReleaseMono|Any CPU = ReleaseMono|Any CPU - ReleaseMono|x64 = ReleaseMono|x64 - ReleaseMono|x86 = ReleaseMono|x86 - ReleaseMonoPY3|Any CPU = ReleaseMonoPY3|Any CPU - ReleaseMonoPY3|x64 = ReleaseMonoPY3|x64 - ReleaseMonoPY3|x86 = ReleaseMonoPY3|x86 - ReleaseWin|Any CPU = ReleaseWin|Any CPU - ReleaseWin|x64 = ReleaseWin|x64 - ReleaseWin|x86 = ReleaseWin|x86 - ReleaseWinPY3|Any CPU = ReleaseWinPY3|Any CPU - ReleaseWinPY3|x64 = ReleaseWinPY3|x64 - ReleaseWinPY3|x86 = ReleaseWinPY3|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|Any CPU.ActiveCfg = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|Any CPU.Build.0 = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x64.ActiveCfg = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x64.Build.0 = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x86.ActiveCfg = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x86.Build.0 = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|Any CPU.ActiveCfg = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|Any CPU.Build.0 = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x64.ActiveCfg = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x64.Build.0 = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x86.ActiveCfg = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x86.Build.0 = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|Any CPU.Build.0 = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|Any CPU.ActiveCfg = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|Any CPU.Build.0 = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x64.ActiveCfg = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x64.Build.0 = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x86.ActiveCfg = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x86.Build.0 = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|Any CPU.Build.0 = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x64.Build.0 = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x86.Build.0 = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|Any CPU.Build.0 = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x64.ActiveCfg = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x64.Build.0 = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x86.ActiveCfg = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x86.Build.0 = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|Any CPU.Build.0 = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x64.ActiveCfg = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x64.Build.0 = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x86.ActiveCfg = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x86.Build.0 = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|Any CPU.Build.0 = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|Any CPU.Build.0 = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x64.ActiveCfg = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x64.Build.0 = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x86.Build.0 = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|Any CPU.Build.0 = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|Any CPU - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x64.ActiveCfg = DebugWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x64.Build.0 = DebugWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x86.ActiveCfg = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x86.Build.0 = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x64.Build.0 = DebugMono|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x86.Build.0 = DebugMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x64.Build.0 = DebugWin|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x86.Build.0 = DebugWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x64.Build.0 = ReleaseWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x86.Build.0 = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x64.ActiveCfg = DebugWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x64.Build.0 = DebugWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x86.ActiveCfg = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x86.Build.0 = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x64.Build.0 = DebugWin|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x86.Build.0 = DebugWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x64.Build.0 = ReleaseWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x86.Build.0 = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x64.ActiveCfg = DebugWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x64.Build.0 = DebugWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x86.ActiveCfg = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x86.Build.0 = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x64.Build.0 = DebugMono|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x86.Build.0 = DebugMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x64.Build.0 = DebugWin|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x86.Build.0 = DebugWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x64.Build.0 = ReleaseWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x86.Build.0 = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x64.ActiveCfg = DebugWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x64.Build.0 = DebugWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x86.ActiveCfg = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x86.Build.0 = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x64.Build.0 = DebugMono|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x86.Build.0 = DebugMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x64.Build.0 = DebugWin|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x86.Build.0 = DebugWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x64.Build.0 = ReleaseWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x86.Build.0 = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Debug|Any CPU.ActiveCfg = ReleaseWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Debug|Any CPU.Build.0 = ReleaseWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Debug|x64.ActiveCfg = DebugWinPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Debug|x64.Build.0 = DebugWinPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Debug|x86.ActiveCfg = DebugWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Debug|x86.Build.0 = DebugWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMono|x64.Build.0 = DebugMono|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMono|x86.Build.0 = DebugMono|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWin|x64.Build.0 = DebugWin|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWin|x86.Build.0 = DebugWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Release|Any CPU.ActiveCfg = ReleaseWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Release|Any CPU.Build.0 = ReleaseWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Release|x64.Build.0 = ReleaseWinPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.Release|x86.Build.0 = ReleaseWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {6FB0D091-9CEC-4DCC-8701-C40F9BFC9EDE}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {A6347B90-BBE6-4E45-90BF-1BD8B76069E3} - EndGlobalSection -EndGlobal diff --git a/requirements.txt b/requirements.txt index 78570cb95..e0e465bd1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,13 @@ # Requirements for both Travis and AppVeyor pytest -coverage psutil # Coverage upload +coverage codecov # Platform specific requirements wheel pycparser +setuptools +setuptools_scm diff --git a/setup.py b/setup.py index 0b352b8af..c1c9924a4 100644 --- a/setup.py +++ b/setup.py @@ -1,156 +1,17 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -""" -Setup script for building clr.pyd and dependencies using mono and into -an egg or wheel. -""" +from setuptools import setup, find_packages, Command, Extension +from wheel.bdist_wheel import bdist_wheel +from setuptools.command.build_ext import build_ext +import distutils +from subprocess import check_output, check_call -import collections -import fnmatch -import glob -import os -import subprocess -import sys -import sysconfig -from distutils import spawn -from distutils.command import install, build, build_ext, install_data, install_lib +import sys, os -from setuptools import Extension, setup - -try: - from wheel import bdist_wheel -except ImportError: - bdist_wheel = None - -# Allow config/verbosity to be set from cli -# http://stackoverflow.com/a/4792601/5208670 -CONFIG = "Release" # Release or Debug -VERBOSITY = "normal" # quiet, minimal, normal, detailed, diagnostic - -is_64bits = sys.maxsize > 2 ** 32 -DEVTOOLS = "MsDev" if sys.platform == "win32" else "Mono" -ARCH = "x64" if is_64bits else "x86" PY_MAJOR = sys.version_info[0] PY_MINOR = sys.version_info[1] -############################################################################### -# 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=os.path.join("bin", "10.0.16299.0", ARCH), - ), - RegKey( - sdk_name="Windows Kit 10.0", - key=kits_root, - value_name="KitsRoot10", - suffix=os.path.join("bin", "10.0.15063.0", ARCH), - ), - 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 15", - key=vs_root.format("15.0"), - value_name="MSBuildToolsPath", - suffix="", - ), - 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 _check_output(*args, **kwargs): - """Check output wrapper for py2/py3 compatibility""" - output = subprocess.check_output(*args, **kwargs) - return output.decode("ascii") +CONFIGURED_PROPS = "configured.props" def _get_interop_filename(): @@ -165,466 +26,200 @@ 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",): - for path in glob.glob("*" + ext): - yield path - - for root, dirnames, filenames in os.walk("src"): - for ext in (".cs", ".csproj", ".snk", ".config", ".py", ".c", ".h", ".ico"): - for filename in fnmatch.filter(filenames, "*" + ext): - yield os.path.join(root, filename) +def _write_configure_props(): + defines = [ + "PYTHON{0}{1}".format(PY_MAJOR, PY_MINOR), + ] - 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) + if sys.platform == "win32": + defines.append("WINDOWS") + if hasattr(sys, "abiflags"): + if "d" in sys.abiflags: + defines.append("PYTHON_WITH_PYDEBUG") + if "m" in sys.abiflags: + defines.append("PYTHON_WITH_PYMALLOC") -def _get_long_description(): - """Helper to populate long_description for pypi releases""" - return open("README.rst").read() + # check the interop file exists, and create it if it doesn't + interop_file = _get_interop_filename() + if not os.path.exists(interop_file): + print("Creating {0}".format(interop_file)) + geninterop = os.path.join("tools", "geninterop", "geninterop.py") + check_call([sys.executable, geninterop, interop_file]) + import xml.etree.ElementTree as ET -def _update_xlat_devtools(): - global DEVTOOLS - if DEVTOOLS == "MsDev": - DEVTOOLS = "MsDev15" - elif DEVTOOLS == "Mono": - DEVTOOLS = "dotnet" + proj = ET.Element("Project") + props = ET.SubElement(proj, "PropertyGroup") + f = ET.SubElement(props, "PythonInteropFile") + f.text = os.path.basename(interop_file) + c = ET.SubElement(props, "ConfiguredConstants") + c.text = " ".join(defines) -def _collect_installed_windows_kits_v10(winreg): - """Adds the installed Windows 10 kits to WIN_SDK_KEYS """ - global WIN_SDK_KEYS - installed_kits = [] + ET.ElementTree(proj).write(CONFIGURED_PROPS) - with winreg.OpenKey( - winreg.HKEY_LOCAL_MACHINE, kits_root, 0, winreg.KEY_READ - ) as key: - i = 0 - while True: - try: - installed_kits.append(winreg.EnumKey(key, i)) - i += 1 - except WindowsError: - break - def make_reg_key(version): - return RegKey( - sdk_name="Windows Kit 10.0", - key=kits_root, - value_name="KitsRoot10", - suffix=os.path.join("bin", version, ARCH), - ) +class Configure(Command): + """Configure command""" - WIN_SDK_KEYS += [make_reg_key(e) for e in installed_kits if e.startswith("10.")] + description = "Configure the pythonnet build" + user_options = [] - # Make sure this function won't be called again - _collect_installed_windows_kits_v10 = lambda: None + def initialize_options(self): + pass + def finalize_options(self): + pass -class BuildExtPythonnet(build_ext.build_ext): - user_options = build_ext.build_ext.user_options + [("xplat", None, None)] + def run(self): + self.announce("Writing configured.props...", level=distutils.log.INFO) + _write_configure_props() - def initialize_options(self): - build_ext.build_ext.initialize_options(self) - self.xplat = None - def finalize_options(self): - build_ext.build_ext.finalize_options(self) - - def build_extension(self, ext): - if self.xplat: - _update_xlat_devtools() - - """Builds the .pyd file using msbuild or xbuild""" - if ext.name != "clr": - return build_ext.build_ext.build_extension(self, ext) - - # install packages using nuget - self._install_packages() - - dest_file = self.get_ext_fullpath(ext.name) - dest_dir = os.path.dirname(dest_file) - if not os.path.exists(dest_dir): - os.makedirs(dest_dir) - - defines = [ - "PYTHON{0}{1}".format(PY_MAJOR, PY_MINOR), - ] - - if CONFIG == "Debug": - defines.extend(["DEBUG", "TRACE"]) - - if sys.platform != "win32" and (DEVTOOLS == "Mono" or DEVTOOLS == "dotnet"): - on_darwin = sys.platform == "darwin" - - # Check if --enable-shared was set when Python was built - enable_shared = sysconfig.get_config_var("Py_ENABLE_SHARED") - if enable_shared: - # Double-check if libpython is linked dynamically with python - ldd_cmd = ["otool", "-L"] if on_darwin else ["ldd"] - lddout = _check_output(ldd_cmd + [sys.executable]) - if "libpython" not in lddout: - enable_shared = False - - if not enable_shared: - defines.append("PYTHON_WITHOUT_ENABLE_SHARED") - - if sys.platform == "win32": - defines.append("WINDOWS") - - if hasattr(sys, "abiflags"): - if "d" in sys.abiflags: - defines.append("PYTHON_WITH_PYDEBUG") - if "m" in sys.abiflags: - defines.append("PYTHON_WITH_PYMALLOC") - - # 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]) - - if DEVTOOLS == "MsDev": - _xbuild = '"{0}"'.format(self._find_msbuild_tool("msbuild.exe")) - _config = "{0}Win".format(CONFIG) - _solution_file = "pythonnet.sln" - _custom_define_constants = False - elif DEVTOOLS == "MsDev15": - _xbuild = '"{0}"'.format(self._find_msbuild_tool_15()) - _config = "{0}Win".format(CONFIG) - _solution_file = "pythonnet.15.sln" - _custom_define_constants = True - elif DEVTOOLS == "Mono": - _xbuild = "xbuild" - _config = "{0}Mono".format(CONFIG) - _solution_file = "pythonnet.sln" - _custom_define_constants = False - elif DEVTOOLS == "dotnet": - _xbuild = "dotnet msbuild" - _config = "{0}Mono".format(CONFIG) - _solution_file = "pythonnet.15.sln" - _custom_define_constants = True - else: - raise NotImplementedError( - "DevTool {0} not supported (use MsDev/MsDev15/Mono/dotnet)".format( - DEVTOOLS - ) - ) +class DotnetLib(Extension): + def __init__(self, name, path, **kwargs): + self.path = path + self.args = kwargs + super().__init__(name, sources=[]) - cmd = [ - _xbuild, - _solution_file, - "/p:Configuration={}".format(_config), - "/p:Platform={}".format(ARCH), - '/p:{}DefineConstants="{}"'.format( - "Custom" if _custom_define_constants else "", "%3B".join(defines) - ), - '/p:PythonBuildDir="{}"'.format(os.path.abspath(dest_dir)), - '/p:PythonInteropFile="{}"'.format(os.path.basename(interop_file)), - "/p:PackageId=pythonnet_py{0}{1}_{2}".format(PY_MAJOR, PY_MINOR, ARCH), - "/verbosity:{}".format(VERBOSITY), - ] - - manifest = self._get_manifest(dest_dir) - if manifest: - cmd.append('/p:PythonManifest="{0}"'.format(manifest)) - - self.debug_print("Building: {0}".format(" ".join(cmd))) - use_shell = True if DEVTOOLS == "Mono" or DEVTOOLS == "dotnet" else False - - subprocess.check_call(" ".join(cmd + ["/t:Clean"]), shell=use_shell) - subprocess.check_call(" ".join(cmd + ["/t:Build"]), shell=use_shell) - if DEVTOOLS == "MsDev15" or DEVTOOLS == "dotnet": - subprocess.check_call( - " ".join( - cmd - + [ - '"/t:Console_15:publish;Python_EmbeddingTest_15:publish"', - "/p:TargetFramework=netcoreapp3.1", - ] - ), - shell=use_shell, - ) - subprocess.check_call( - " ".join( - cmd - + [ - '"/t:Python_PerformanceTests:publish"', - "/p:TargetFramework=net461", - ] - ), - shell=use_shell, - ) - if DEVTOOLS == "Mono" or DEVTOOLS == "dotnet": - self._build_monoclr() - - def _get_manifest(self, build_dir): - if DEVTOOLS != "MsDev" and DEVTOOLS != "MsDev15": - 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.debug_print("Extracting manifest from {}".format(sys.executable)) - subprocess.check_call(" ".join(cmd), shell=False) - return manifest - - def _build_monoclr(self): - try: - mono_libs = _check_output("pkg-config --libs mono-2", shell=True) - except: - if DEVTOOLS == "dotnet": - print("Skipping building monoclr module...") - return - raise - mono_cflags = _check_output("pkg-config --cflags mono-2", shell=True) - cflags = mono_cflags.strip() - libs = mono_libs.strip() - - # build the clr python module - clr_ext = Extension( - "clr", - language="c++", - 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) - - def _install_packages(self): - """install packages using nuget""" - use_shell = DEVTOOLS == "Mono" or DEVTOOLS == "dotnet" - - if DEVTOOLS == "MsDev15" or DEVTOOLS == "dotnet": - if DEVTOOLS == "MsDev15": - _config = "{0}Win".format(CONFIG) - elif DEVTOOLS == "dotnet": - _config = "{0}Mono".format(CONFIG) - - cmd = "dotnet msbuild /t:Restore pythonnet.15.sln /p:Configuration={0} /p:Platform={1}".format( - _config, ARCH - ) - self.debug_print("Updating packages with xplat: {0}".format(cmd)) - subprocess.check_call(cmd, shell=use_shell) - else: - nuget = os.path.join("tools", "nuget", "nuget.exe") - - if DEVTOOLS == "Mono": - nuget = "mono {0}".format(nuget) - - cmd = "{0} update -self".format(nuget) - self.debug_print("Updating NuGet: {0}".format(cmd)) - subprocess.check_call(cmd, shell=use_shell) - - try: - # msbuild=14 is mainly for Mono issues - cmd = "{0} restore pythonnet.sln -MSBuildVersion 14 -o packages".format( - nuget - ) - self.debug_print("Installing packages: {0}".format(cmd)) - subprocess.check_call(cmd, shell=use_shell) - except: - # when only VS 2017 is installed do not specify msbuild version - cmd = "{0} restore pythonnet.sln -o packages".format(nuget) - 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): - """Return full path to one of the Microsoft build tools""" - - # trying to search path with help of vswhere when MSBuild 15.0 and higher installed. - if tool == "msbuild.exe" and use_windows_sdk == False: - try: - basePaths = subprocess.check_output( - [ - "tools\\vswhere\\vswhere.exe", - "-latest", - "-version", - "[15.0,)", - "-requires", - "Microsoft.Component.MSBuild", - "-find", - "MSBuild\**\Bin\MSBuild.exe", - ] - ).splitlines() - if len(basePaths): - return basePaths[0].decode(sys.stdout.encoding or "utf-8") - except: - pass # keep trying to search by old method. - - # Search in PATH first - path = spawn.find_executable(tool) - if path: - return path - - # Search within registry to find build tools - import winreg - - _collect_installed_windows_kits_v10(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.debug_print( - "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.debug_print("Using {0} from {1}".format(tool, sdk_name)) - return path - - raise RuntimeError("{0} could not be found".format(tool)) - - def _find_msbuild_tool_15(self): - """Return full path to one of the Microsoft build tools""" - try: - basePaths = subprocess.check_output( - [ - "tools\\vswhere\\vswhere.exe", - "-latest", - "-version", - "[15.0,)", - "-requires", - "Microsoft.Component.MSBuild", - "-find", - "MSBuild\**\Bin\MSBuild.exe", - ] - ).splitlines() - if len(basePaths): - return basePaths[0].decode(sys.stdout.encoding or "utf-8") - else: - raise RuntimeError("MSBuild >=15.0 could not be found.") - except subprocess.CalledProcessError as e: - raise RuntimeError( - "MSBuild >=15.0 could not be found. {0}".format(e.output) - ) +class BuildDotnet(build_ext): + """Build command for dotnet-cli based builds""" -class InstallLibPythonnet(install_lib.install_lib): - def install(self): - if not os.path.isdir(self.build_dir): - self.warn( - "'{0}' does not exist -- no Python modules" - " to install".format(self.build_dir) - ) - return + description = "Build DLLs with dotnet-cli" + user_options = [("dotnet-config", None, "dotnet build configuration")] - if not os.path.exists(self.install_dir): - self.mkpath(self.install_dir) + def initialize_options(self): + self.dotnet_config = "release" + super().initialize_options() - # only copy clr.pyd/.so - 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) + def finalize_options(self): + super().finalize_options() + def get_source_files(self): + return super().get_source_files() -class InstallDataPythonnet(install_data.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) - - for i, data_files in enumerate(self.data_files): - if isinstance(data_files, str): - self.data_files[i] = data_files[i].format(build_lib=build_lib) + orig_modules = self.distribution.ext_modules + dotnet_modules = [lib for lib in orig_modules if isinstance(lib, DotnetLib)] + other_modules = [lib for lib in orig_modules if not isinstance(lib, DotnetLib)] + + if dotnet_modules: + if os.path.isfile(CONFIGURED_PROPS): + self.announce("Already configured", level=distutils.log.INFO) else: - for j, filename in enumerate(data_files[1]): - data_files[1][j] = filename.format(build_lib=build_lib) - dest = data_files[0].format(install_platlib=install_platlib) - self.data_files[i] = dest, data_files[1] + self.announce("Writing configured.props...", level=distutils.log.INFO) + _write_configure_props() - return install_data.install_data.run(self) + for lib in dotnet_modules: + output = os.path.join(os.path.abspath(self.build_lib), lib.args.pop("output")) + rename = lib.args.pop("rename", {}) + opts = sum( + [ + ["--" + name.replace("_", "-"), value] + for name, value in lib.args.items() + ], + [], + ) -class InstallPythonnet(install.install): - user_options = install.install.user_options + [("xplat", None, None)] + opts.extend(["--configuration", self.dotnet_config]) + opts.extend(["--output", output]) - def initialize_options(self): - install.install.initialize_options(self) - self.xplat = None + self.announce("Running dotnet build...", level=distutils.log.INFO) + self.spawn(["dotnet", "build", lib.path] + opts) - def finalize_options(self): - install.install.finalize_options(self) + for k, v in rename.items(): + source = os.path.join(output, k) + dest = os.path.join(output, v) - def run(self): - if self.xplat: - _update_xlat_devtools() - return install.install.run(self) + if os.path.isfile(source): + try: + os.remove(dest) + except OSError: + pass -if bdist_wheel: - class BDistWheelPythonnet(bdist_wheel.bdist_wheel): - user_options = bdist_wheel.bdist_wheel.user_options + [("xplat", None, None)] + self.move_file(src=source, dst=dest, level=distutils.log.INFO) + else: + self.warn("Can't find file to rename: {}, current dir: {}".format(source, os.getcwd())) - def initialize_options(self): - bdist_wheel.bdist_wheel.initialize_options(self) - self.xplat = None + if other_modules: + self.distribution.ext_modules = other_modules + super().run() + self.distribution.ext_modules = orig_modules + # If no modules need to be compiled, skip - def finalize_options(self): - bdist_wheel.bdist_wheel.finalize_options(self) - def run(self): - if self.xplat: - _update_xlat_devtools() - return bdist_wheel.bdist_wheel.run(self) +class bdist_wheel_patched(bdist_wheel): + def finalize_options(self): + # Monkey patch bdist_wheel to think the package is pure even though we + # include DLLs + super().finalize_options() + self.root_is_pure = True + - ############################################################################### +with open("README.rst", "r") as f: + long_description = f.read() -setupdir = os.path.dirname(__file__) -if setupdir: - os.chdir(setupdir) +ext_modules = [ + DotnetLib( + "clrmodule-amd64", + "src/clrmodule/", + runtime="win-x64", + output="pythonnet/dlls/amd64", + rename={"clr.dll": "clr.pyd"}, + ), + DotnetLib( + "clrmodule-x86", + "src/clrmodule/", + runtime="win-x86", + output="pythonnet/dlls/x86", + rename={"clr.dll": "clr.pyd"}, + ), +] + +try: + mono_libs = check_output("pkg-config --libs mono-2", shell=True, encoding="utf8") + mono_cflags = check_output( + "pkg-config --cflags mono-2", shell=True, encoding="utf8" + ) + cflags = mono_cflags.strip() + libs = mono_libs.strip() + + # build the clr python module + clr_ext = Extension( + "clr", + language="c++", + sources=["src/monoclr/pynetinit.c", "src/monoclr/clrmod.c"], + extra_compile_args=cflags.split(" "), + extra_link_args=libs.split(" "), + ) + ext_modules.append(clr_ext) +except Exception: + print("Failed to find mono libraries via pkg-config, skipping the Mono CLR loader") -cmdclass={ - "install": InstallPythonnet, - "build_ext": BuildExtPythonnet, - "install_lib": InstallLibPythonnet, - "install_data": InstallDataPythonnet, -} -if bdist_wheel: - cmdclass["bdist_wheel"] = BDistWheelPythonnet setup( name="pythonnet", - version="3.0.0dev1", + version="3.0.0.dev1", description=".Net and Mono integration for Python", url="https://pythonnet.github.io/", license="MIT", author="The Contributors of the Python.NET Project", author_email="pythonnet@python.org", + setup_requires=["setuptools_scm"], install_requires=["pycparser"], - long_description=_get_long_description(), - ext_modules=[Extension("clr", sources=list(_get_source_files()))], - data_files=[("{install_platlib}", ["{build_lib}/Python.Runtime.dll"])], - cmdclass=cmdclass, + long_description=long_description, + # data_files=[("{install_platlib}", ["{build_lib}/pythonnet"])], + cmdclass={ + "build_ext": BuildDotnet, + "bdist_wheel": bdist_wheel_patched, + "configure": Configure, + }, + py_modules=["clr"], + ext_modules=ext_modules, classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", diff --git a/src/SharedAssemblyInfo.cs b/src/SharedAssemblyInfo.cs deleted file mode 100644 index ab79c56eb..000000000 --- a/src/SharedAssemblyInfo.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("pythonnet")] -[assembly: AssemblyProduct("Python.NET")] -[assembly: AssemblyCopyright("Copyright (c) 2006-2020 the contributors of the Python.NET project")] -[assembly: AssemblyTrademark("")] - -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("")] - -[assembly: CLSCompliant(true)] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// Version Information. Keeping it simple. May need to revisit for Nuget -// See: https://codingforsmarties.wordpress.com/2016/01/21/how-to-version-assemblies-destined-for-nuget/ -// AssemblyVersion can only be numeric -[assembly: AssemblyVersion("3.0.0")] diff --git a/src/clrmodule/ClrModule.cs b/src/clrmodule/ClrModule.cs index e19e58594..7b0387d46 100644 --- a/src/clrmodule/ClrModule.cs +++ b/src/clrmodule/ClrModule.cs @@ -26,7 +26,7 @@ using System.IO; using System.Reflection; using System.Runtime.InteropServices; -using RGiesecke.DllExport; +using NXPorts.Attributes; public class clrModule { diff --git a/src/clrmodule/Properties/AssemblyInfo.cs b/src/clrmodule/Properties/AssemblyInfo.cs index 939f4171f..5e2e05ed4 100644 --- a/src/clrmodule/Properties/AssemblyInfo.cs +++ b/src/clrmodule/Properties/AssemblyInfo.cs @@ -1,11 +1,5 @@ using System.Reflection; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("clrmodule")] -[assembly: AssemblyDescription("")] - // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("ae10d6a4-55c2-482f-9716-9988e6c169e3")] diff --git a/src/clrmodule/clrmodule.15.csproj b/src/clrmodule/clrmodule.15.csproj deleted file mode 100644 index 7fc9c2dda..000000000 --- a/src/clrmodule/clrmodule.15.csproj +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - net40 - x64;x86 - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 - clrmodule - clrmodule - clrmodule - 2.5.0 - false - false - false - false - false - false - bin\clrmodule.xml - bin\ - false - 1591 - ..\..\ - $(SolutionDir)\bin\ - $(PythonBuildDir)\$(TargetFramework)\ - 6 - prompt - $(PYTHONNET_DEFINE_CONSTANTS) - XPLAT - $(DefineConstants);$(CustomDefineConstants);$(BaseDefineConstants); - $(DefineConstants);TRACE;DEBUG - - - - x86 - - - x64 - - - - false - full - - - true - pdbonly - - - - $(DefineConstants);PYTHON2;TRACE;DEBUG - - - $(DefineConstants);PYTHON2 - - - $(DefineConstants);PYTHON2;TRACE;DEBUG - - - $(DefineConstants);PYTHON2 - - - $(DefineConstants);PYTHON3;TRACE;DEBUG - - - $(DefineConstants);PYTHON3 - - - $(DefineConstants);PYTHON3;TRACE;DEBUG - - - $(DefineConstants);PYTHON3 - - - - - - - - - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - - - diff --git a/src/clrmodule/clrmodule.csproj b/src/clrmodule/clrmodule.csproj index 6e5ff4966..8595fd0ba 100644 --- a/src/clrmodule/clrmodule.csproj +++ b/src/clrmodule/clrmodule.csproj @@ -1,95 +1,24 @@ - - + - Debug - AnyCPU - {86E834DE-1139-4511-96CC-69636A56E7AC} - Library - clrmodule - clrmodule - bin\clrmodule.xml - bin\ - v4.0 - - 1591 - ..\..\ - $(SolutionDir)\bin\ - Properties - 6 - true - prompt + net472 + win-x86;win-x64 + clr - + + + + + + 1.0.0 + all + runtime; build; native; contentfiles; analyzers + + + + x86 - + x64 - - true - PYTHON2;TRACE;DEBUG - full - - - PYTHON2 - true - pdbonly - - - true - PYTHON2;TRACE;DEBUG - full - - - PYTHON2 - true - pdbonly - - - true - PYTHON3;TRACE;DEBUG - full - - - PYTHON3 - true - pdbonly - - - true - PYTHON3;TRACE;DEBUG - full - - - PYTHON3 - true - pdbonly - - - - ..\..\packages\UnmanagedExports.1.2.7\lib\net\RGiesecke.DllExport.Metadata.dll - False - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - diff --git a/src/clrmodule/packages.config b/src/clrmodule/packages.config deleted file mode 100644 index 2a95dc54d..000000000 --- a/src/clrmodule/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/console/Console.15.csproj b/src/console/Console.15.csproj deleted file mode 100644 index a5d8043f9..000000000 --- a/src/console/Console.15.csproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - net40;netcoreapp3.1 - x64;x86 - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 - Exe - nPython - Python.Runtime - nPython - 2.5.0 - false - false - false - false - false - false - bin\ - false - $(OutputPath)\$(AssemblyName).xml - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - 1591 - ..\..\ - $(SolutionDir)\bin\ - $(PythonBuildDir)\$(TargetFramework)\ - 6 - python-clear.ico - prompt - $(PYTHONNET_DEFINE_CONSTANTS) - XPLAT - $(DefineConstants);$(CustomDefineConstants);$(BaseDefineConstants); - $(DefineConstants);TRACE;DEBUG - $(NuGetPackageRoot)\microsoft.targetingpack.netframework.v4.5\1.0.1\lib\net45\ - - - x86 - - - x64 - - - - false - full - - - true - pdbonly - - - true - false - full - - - true - true - portable - - - - $(DefineConstants);DEBUG;TRACE - - - $(DefineConstants) - - - - $(PythonManifest) - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - Python.Runtime.dll - - - - - - - - - - - - diff --git a/src/console/Console.csproj b/src/console/Console.csproj index 226105f95..08854cfc9 100644 --- a/src/console/Console.csproj +++ b/src/console/Console.csproj @@ -1,101 +1,27 @@ - - + - Debug - AnyCPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349} + net472;netcoreapp3.1 + x64;x86 Exe nPython Python.Runtime - bin\nPython.xml - bin\ - v4.0 - - 1591 - ..\..\ - $(SolutionDir)\bin\ - Properties - 6 + nPython python-clear.ico - prompt - - x86 - - - x64 - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - $(PythonManifest) - - - - - - - - Properties\SharedAssemblyInfo.cs - - - + - + Python.Runtime.dll - - {097b4ac0-74e9-4c58-bcf8-c69746ec8271} - Python.Runtime - + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + - - - - diff --git a/src/console/Properties/AssemblyInfo.cs b/src/console/Properties/AssemblyInfo.cs deleted file mode 100644 index 081ae0c94..000000000 --- a/src/console/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Reflection; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Python Console")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyDefaultAlias("python.exe")] diff --git a/src/embed_tests/Program.cs b/src/embed_tests/Program.cs deleted file mode 100644 index b4439e3e4..000000000 --- a/src/embed_tests/Program.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -using NUnit.Common; - -using NUnitLite; - -namespace Python.EmbeddingTest -{ - public class Program - { - public static int Main(string[] args) - { - return new AutoRun(typeof(Program).Assembly).Execute( - args, - new ExtendedTextWrapper(Console.Out), - Console.In); - } - } -} diff --git a/src/embed_tests/Python.EmbeddingTest.15.csproj b/src/embed_tests/Python.EmbeddingTest.15.csproj deleted file mode 100644 index 9d439cff4..000000000 --- a/src/embed_tests/Python.EmbeddingTest.15.csproj +++ /dev/null @@ -1,121 +0,0 @@ - - - - - net40;netcoreapp3.1 - x64;x86 - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 - Exe - false - Python.EmbeddingTest - Python.EmbeddingTest - Python.EmbeddingTest - 2.5.0 - false - false - false - false - bin\ - false - $(OutputPath)\$(AssemblyName).xml - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - 1591 - ..\..\ - $(SolutionDir)\bin\ - $(OutputPath)\$(TargetFramework)_publish - 7.3 - prompt - $(PYTHONNET_DEFINE_CONSTANTS) - XPLAT - $(DefineConstants);$(CustomDefineConstants);$(BaseDefineConstants); - $(DefineConstants);NETCOREAPP - $(DefineConstants);NETSTANDARD - $(DefineConstants);TRACE;DEBUG - $(NuGetPackageRoot)\microsoft.targetingpack.netframework.v4.5\1.0.1\lib\net45\ - - - x86 - - - x64 - - - - false - full - - - true - pdbonly - - - true - false - full - - - true - true - portable - - - - $(DefineConstants);DEBUG;TRACE - - - $(DefineConstants) - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - - - diff --git a/src/embed_tests/Python.EmbeddingTest.csproj b/src/embed_tests/Python.EmbeddingTest.csproj index 264b3a5ed..8f2db8efe 100644 --- a/src/embed_tests/Python.EmbeddingTest.csproj +++ b/src/embed_tests/Python.EmbeddingTest.csproj @@ -1,143 +1,29 @@ - - + + - Debug - AnyCPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5} - Library - Python.EmbeddingTest - Python.EmbeddingTest - bin\Python.EmbeddingTest.xml - bin\ - v4.0 - - 1591 - ..\..\ - $(SolutionDir)\bin\ - 7.3 - true - prompt + net472;netcoreapp3.1 - - x86 - - - x64 - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - - - ..\..\packages\NUnit.3.12.0\lib\net40\nunit.framework.dll - - - ..\..\packages\System.ValueTuple.4.5.0\lib\portable-net40+sl4+win8+wp8\System.ValueTuple.dll - - - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - {097B4AC0-74E9-4C58-BCF8-C69746EC8271} - Python.Runtime - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + 1.0.0 + all + runtime; build; native; contentfiles; analyzers + - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + diff --git a/src/embed_tests/TestDomainReload.cs b/src/embed_tests/TestDomainReload.cs index 4c9de1461..a606932f3 100644 --- a/src/embed_tests/TestDomainReload.cs +++ b/src/embed_tests/TestDomainReload.cs @@ -14,7 +14,7 @@ // // Unfortunately this means no continuous integration testing for this case. // -#if !NETSTANDARD && !NETCOREAPP +#if NETFRAMEWORK namespace Python.EmbeddingTest { class TestDomainReload @@ -400,7 +400,7 @@ public object Call(string methodName, params object[] args) return method.Invoke(null, args); } } - + static T CreateInstanceInstanceAndUnwrap(AppDomain domain) { Type type = typeof(T); diff --git a/src/embed_tests/TestPyWith.cs b/src/embed_tests/TestPyWith.cs index 0c4e9023f..dcd539504 100644 --- a/src/embed_tests/TestPyWith.cs +++ b/src/embed_tests/TestPyWith.cs @@ -25,15 +25,14 @@ public void Dispose() public void TestWithPositive() { var locals = new PyDict(); - + PythonEngine.Exec(@" class CmTest: def __enter__(self): - print('Enter') return self def __exit__(self, t, v, tb): # Exception not handled, return will be False - print('Exit') + pass def fail(self): return 5 / 0 @@ -51,6 +50,7 @@ def fail(self): } catch (PythonException e) { + TestContext.Out.WriteLine(e.Message); Assert.IsTrue(e.Message.Contains("ZeroDivisionError")); } } diff --git a/src/embed_tests/pyimport.cs b/src/embed_tests/pyimport.cs index ebb4fabd0..24f31acff 100644 --- a/src/embed_tests/pyimport.cs +++ b/src/embed_tests/pyimport.cs @@ -30,12 +30,8 @@ public void SetUp() /* Append the tests directory to sys.path * using reflection to circumvent the private * modifiers placed on most Runtime methods. */ -#if NETCOREAPP - const string s = "../../fixtures"; -#else - const string s = "../fixtures"; -#endif - string testPath = Path.Combine(TestContext.CurrentContext.TestDirectory, s); + string testPath = Path.Combine(TestContext.CurrentContext.TestDirectory, "fixtures"); + TestContext.Out.WriteLine(testPath); IntPtr str = Runtime.Runtime.PyString_FromString(testPath); BorrowedReference path = Runtime.Runtime.PySys_GetObject("path"); diff --git a/src/perf_tests/Python.PerformanceTests.csproj b/src/perf_tests/Python.PerformanceTests.csproj index f84e556aa..22783e595 100644 --- a/src/perf_tests/Python.PerformanceTests.csproj +++ b/src/perf_tests/Python.PerformanceTests.csproj @@ -1,12 +1,8 @@ - net461 - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 - bin\ - + net472 false - x64;x86 @@ -28,7 +24,7 @@ - + diff --git a/src/runtime/Properties/AssemblyInfo.cs b/src/runtime/Properties/AssemblyInfo.cs index cab9df30b..470488c02 100644 --- a/src/runtime/Properties/AssemblyInfo.cs +++ b/src/runtime/Properties/AssemblyInfo.cs @@ -1,11 +1,3 @@ -using System.Reflection; using System.Runtime.CompilerServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Python.NET")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyDefaultAlias("Python.Runtime.dll")] - [assembly: InternalsVisibleTo("Python.EmbeddingTest")] diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj deleted file mode 100644 index d530fd5e4..000000000 --- a/src/runtime/Python.Runtime.15.csproj +++ /dev/null @@ -1,176 +0,0 @@ - - - - net40;netstandard2.0 - AnyCPU - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 - net45 - Python.Runtime - Python.Runtime - pythonnet - 2.5.0 - true - false - Python.NET - Copyright (c) 2006-2020 the contributors of the Python.NET project - Python and CLR (.NET and Mono) cross-platform language interop - pythonnet - https://github.com/pythonnet/pythonnet/blob/master/LICENSE - https://github.com/pythonnet/pythonnet - git - - true - true - true - snupkg - - python interop dynamic dlr Mono pinvoke - https://raw.githubusercontent.com/pythonnet/pythonnet/master/src/console/python-clear.ico - https://pythonnet.github.io/ - bin\ - false - $(OutputPath)\$(AssemblyName).xml - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - 1591;NU1701 - ..\..\ - $(SolutionDir)\bin\ - $(PythonBuildDir)\$(TargetFramework)\ - 7.3 - True - ..\pythonnet.snk - $(PYTHONNET_DEFINE_CONSTANTS) - XPLAT - $(DefineConstants);$(CustomDefineConstants);$(BaseDefineConstants); - $(DefineConstants);NETSTANDARD - $(DefineConstants);TRACE;DEBUG - $(NuGetPackageRoot)\microsoft.targetingpack.netframework.v4.5\1.0.1\lib\net45\ - $(PYTHONNET_PY2_VERSION) - PYTHON27 - $(PYTHONNET_PY3_VERSION) - PYTHON38 - $(PYTHONNET_WIN_DEFINE_CONSTANTS) - $(PYTHONNET_MONO_DEFINE_CONSTANTS) - MONO_LINUX;PYTHON_WITH_PYMALLOC - $(PYTHONNET_INTEROP_FILE) - - - false - full - - - true - pdbonly - - - true - false - full - - - true - true - portable - - - - $(DefineConstants);PYTHON2;$(Python2Version);$(PythonMonoDefineConstants) - - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonMonoDefineConstants) - - - $(DefineConstants);PYTHON2;$(Python2Version);$(PythonMonoDefineConstants);FINALIZER_CHECK;TRACE;DEBUG - - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonMonoDefineConstants);FINALIZER_CHECK;TRACE;DEBUG - - - $(DefineConstants);PYTHON2;$(Python2Version);$(PythonWinDefineConstants) - - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonWinDefineConstants) - - - $(DefineConstants);PYTHON2;$(Python2Version);$(PythonWinDefineConstants);FINALIZER_CHECK;TRACE;DEBUG - - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonWinDefineConstants);FINALIZER_CHECK;TRACE;DEBUG - - - - - - - - - - - - - - - - - - - - - - clr.py - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - TextTemplatingFileGenerator - intern_.cs - - - - - - - True - True - intern_.tt - - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - - - - - - diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj index 8d56774c9..acb8efc4e 100644 --- a/src/runtime/Python.Runtime.csproj +++ b/src/runtime/Python.Runtime.csproj @@ -1,195 +1,39 @@ - - - - Debug - AnyCPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271} - Library - Python.Runtime - Python.Runtime - bin\Python.Runtime.xml - bin\ - v4.0 - - 1591 - ..\..\ - $(SolutionDir)\bin\ - Properties - 7.3 - true - false - ..\pythonnet.snk - - - - - - PYTHON2;PYTHON27 - true - pdbonly - - - PYTHON3;PYTHON38 - true - pdbonly - - - true - PYTHON2;PYTHON27;TRACE;DEBUG - false - full - - - true - PYTHON3;PYTHON38;TRACE;DEBUG - false - full - - - PYTHON2;PYTHON27 - true - pdbonly - - - PYTHON3;PYTHON38 - true - pdbonly - - - true - PYTHON2;PYTHON27;TRACE;DEBUG - false - full - - - true - PYTHON3;PYTHON38;TRACE;DEBUG - false - full - - - - - - - - - - - - - - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - clr.py - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - + + + netstandard2.0 + AnyCPU + Python.Runtime + Python.Runtime + pythonnet + https://github.com/pythonnet/pythonnet/blob/master/LICENSE + https://github.com/pythonnet/pythonnet + git + python interop dynamic dlr Mono pinvoke + https://raw.githubusercontent.com/pythonnet/pythonnet/master/src/console/python-clear.ico + https://pythonnet.github.io/ + 1591;NU1701 + True + + + + $(DefineConstants);$(ConfiguredConstants) + + + + + + + + + + + + clr.py + + + + + + + + diff --git a/src/runtime/nativecall.cs b/src/runtime/nativecall.cs index ec0bf338c..e33eb1c81 100644 --- a/src/runtime/nativecall.cs +++ b/src/runtime/nativecall.cs @@ -12,14 +12,6 @@ namespace Python.Runtime /// C API can just be wrapped with p/invoke, but there are some /// situations (specifically, calling functions through Python /// type structures) where we need to call functions indirectly. - /// This class uses Reflection.Emit to generate IJW thunks that - /// support indirect calls to native code using various common - /// call signatures. This is mainly a workaround for the fact - /// that you can't spell an indirect call in C# (but can in IL). - /// Another approach that would work is for this to be turned - /// into a separate utility program that could be run during the - /// build process to generate the thunks as a separate assembly - /// that could then be referenced by the main Python runtime. /// internal class NativeCall { diff --git a/src/runtime/polyfill/ReflectionPolifills.cs b/src/runtime/polyfill/ReflectionPolyfills.cs similarity index 89% rename from src/runtime/polyfill/ReflectionPolifills.cs rename to src/runtime/polyfill/ReflectionPolyfills.cs index b8bc7ea3e..65f9b83de 100644 --- a/src/runtime/polyfill/ReflectionPolifills.cs +++ b/src/runtime/polyfill/ReflectionPolyfills.cs @@ -5,10 +5,8 @@ namespace Python.Runtime { - [Obsolete("This API is for internal use only")] - public static class ReflectionPolifills + internal static class ReflectionPolyfills { -#if NETSTANDARD public static AssemblyBuilder DefineDynamicAssembly(this AppDomain appDomain, AssemblyName assemblyName, AssemblyBuilderAccess assemblyBuilderAccess) { return AssemblyBuilder.DefineDynamicAssembly(assemblyName, assemblyBuilderAccess); @@ -18,7 +16,7 @@ public static Type CreateType(this TypeBuilder typeBuilder) { return typeBuilder.CreateTypeInfo(); } -#endif + public static T GetCustomAttribute(this Type type) where T: Attribute { return type.GetCustomAttributes(typeof(T), inherit: false) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 8b6526b4f..43c63f346 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -706,7 +706,7 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) /// internal static unsafe void XIncref(IntPtr op) { -#if PYTHON_WITH_PYDEBUG || NETSTANDARD +#if !CUSTOM_INCDEC_REF Py_IncRef(op); return; #else @@ -736,7 +736,7 @@ internal static IntPtr SelfIncRef(IntPtr op) internal static unsafe void XDecref(IntPtr op) { -#if PYTHON_WITH_PYDEBUG || NETSTANDARD +#if !CUSTOM_INCDEC_REF Py_DecRef(op); return; #else diff --git a/src/testing/Python.Test.15.csproj b/src/testing/Python.Test.15.csproj deleted file mode 100644 index 0e19adf91..000000000 --- a/src/testing/Python.Test.15.csproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - net40;netstandard2.0 - x64;x86 - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 - Python.Test - Python.Test - Python.Test - 2.5.0 - bin\ - false - $(OutputPath)\$(AssemblyName).xml - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - 1591,0067 - ..\..\ - $(SolutionDir)\bin\ - $(PythonBuildDir)\$(TargetFramework)\ - 6 - false - ..\pythonnet.snk - prompt - $(PYTHONNET_DEFINE_CONSTANTS) - XPLAT - $(DefineConstants);$(CustomDefineConstants);$(BaseDefineConstants); - $(DefineConstants);TRACE;DEBUG - $(NuGetPackageRoot)\microsoft.targetingpack.netframework.v4.5\1.0.1\lib\net45\ - - - x86 - - - x64 - - - - false - full - - - true - pdbonly - - - true - false - full - - - true - true - portable - - - - $(DefineConstants);DEBUG;TRACE - - - $(DefineConstants) - - - - - - - - - - - - - - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - - diff --git a/src/testing/Python.Test.csproj b/src/testing/Python.Test.csproj index e1a5ab85c..e0c0ca8b1 100644 --- a/src/testing/Python.Test.csproj +++ b/src/testing/Python.Test.csproj @@ -1,117 +1,13 @@ - - + - Debug - AnyCPU - {6F401A34-273B-450F-9A4C-13550BE0767B} - Library - Python.Test - Python.Test - bin\Python.Test.xml - bin\ - v4.0 - - 1591,0067 - ..\..\ - $(SolutionDir)\bin\ - 6 - false - ..\pythonnet.snk - prompt + netstandard2.0 - - x86 - - - x64 - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + - - - {097B4AC0-74E9-4C58-BCF8-C69746EC8271} - Python.Runtime - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - + - - + diff --git a/tools/nuget/nuget.exe b/tools/nuget/nuget.exe deleted file mode 100644 index 463f8e137da6faa6695d029ff8b0e130ad31ebff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4596440 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

dl3K?G368K}Qyd#e6Y`<R9Hf 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

cd}vSFICyA3eCIz^zbWq_-GJ!(Wa`c0ZFn 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

q z9kA@;d#%&hV)&71JLqi#4$9ro(otaEam0mY*g1`Kl?^lWC&)Zgj%??rQXV2*v=qGy zq8WOR+5I9EZRa~uhEeqbW*`%B(8vyr+Ro3qglgs$!1F;IdrocVn64PTt2Y$tPFOudUZw~ zL4v&w5AC(7uj$sZ)s_TXO?Ga5Uny?6^$~BAD;wt`Bv2C3P5DsL1 zf-yjG+L4s5vNt>tcnN`0902fwky_s-+D1&Ai^+^ zwD?D+^fXAsst61840?>ATJMZ6C*gZzd;<}u(>E|&(NAQCn3UvB?wJKK$rpr35)fi? zWk{XG#gS}KpUeQJJ`V>d{C`3om^_jp=%-DabqPqar^95A)Jx=zn49s21i5!<;cn{vGRr_hOS0HSJ4(jA34a+6w3!fpAW0B+WK6w>~i$ z$ESGnHh<8pRAu^8V=^ZS`c}#i8ND0EC*jl(b_PLpG8P)7XTVT<4^oqpn&M6I_LvcB zikaJ{c>P__O!pFoc4AuoSDfCXn6Sub+m`m!>k~7rs`q+h*zDpIO9qXfMS3G)vk+$o zup%I1PWK98yMMz+Aa`;&;Asv&pBUr!He>viCZ3IRjLBFi7;+zjeV-H=Yz%asf64}w zxr1~xF`3MXR16I1X@Bxp}5P_j$?aMBmoGIMez$WIl)V$@uIZoKC6axzF2oOL5-d{lVRTLoqd0 zflv&hZs8ye-v7tADV2iaREp2NjR=VUA8a1@e%Bxj zaT0^D9(n31$y_C&RuA6wF>efKTm7t;zwa$0 z^e-M}J%a+aO0I|7i8Pd%`Hy#kQuHI`BM|N-!X1xvCrmv(B2y*@SD3k2-{3Nkd=A=!oag(Un zKRBB!S_`m-+$+0xX74+eyK}PxIoZJ;Db5bXMqrYX6*5;aJ0*Zsp5E{%tH@8s2v9bx2 zb(fc)}(fKV7mnX-^zR(~Sd0pyvK+Oqw!+$F73R;V-5U2x@;o)`}W zY-JG!*Tb5H|6(bB!m(6sJ%j&8@m~@uf5LC#|2SNhQ8-B2_s6=<3h^vlvqgV%hNNmF8D{5}*}S}%=@$1xx9n{~iuIX7n*Lc@Vl z$%sJIXOi!8e+byM2Gt*Zj^x|tyYnK1yl_+S5spbyjFql14pQx)R|@5%f@x>vlo6DQ zpa;%)CuMa;Ms~F}Inj_@w`3nz^tg9Ug-ElMi$Vl0v`w#EFKwV*lLn=FsUe9~J3=>5f2+-T2=w{g%hH`Z3u@*~;Yg}oCn07Q znHCy2s6u+fAhInyb<+`I=Xj|%X-EW`7Q z2ez+f8oK5B`;bM*V%gM0!0QKLPjpV(ZZ3}RuE1I*CeV4*_NPSWMxjZ`Euv+LOH2bj^zXV#G8 z6SJ&&va%!sKKFf4K$^Vu%ih)qD6N6M52Yg}Wg3Gv88xMa%rx03pbDE|VeaJAV89z7 z{WcdhHZi|8Zu`TdMpAkZ0uuNGlHp^ze5Cu``#hbg9y1p$Vf%iuO{RCSXV#VeA&KLz^b~p^Y5$f) zcv;eyi?w*V


?5 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