From 0ea1d29f912e9e4e1b43c4179df842ac2f3a0af2 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 8 Nov 2024 13:50:39 +0100 Subject: [PATCH 01/81] Drop reference to Py_Main (#2504) Was only used in the console and might not be available in some embedding scenarios. --- src/runtime/Runtime.Delegates.cs | 2 -- src/runtime/Runtime.cs | 14 -------------- 2 files changed, 16 deletions(-) diff --git a/src/runtime/Runtime.Delegates.cs b/src/runtime/Runtime.Delegates.cs index 6490c3fe..639ba481 100644 --- a/src/runtime/Runtime.Delegates.cs +++ b/src/runtime/Runtime.Delegates.cs @@ -35,7 +35,6 @@ static Delegates() PyGILState_Ensure = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyGILState_Ensure), GetUnmanagedDll(_PythonDll)); PyGILState_Release = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyGILState_Release), GetUnmanagedDll(_PythonDll)); PyGILState_GetThisThreadState = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyGILState_GetThisThreadState), GetUnmanagedDll(_PythonDll)); - Py_Main = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_Main), GetUnmanagedDll(_PythonDll)); PyEval_InitThreads = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_InitThreads), GetUnmanagedDll(_PythonDll)); PyEval_ThreadsInitialized = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_ThreadsInitialized), GetUnmanagedDll(_PythonDll)); PyEval_AcquireLock = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_AcquireLock), GetUnmanagedDll(_PythonDll)); @@ -319,7 +318,6 @@ static Delegates() internal static delegate* unmanaged[Cdecl] PyGILState_Ensure { get; } internal static delegate* unmanaged[Cdecl] PyGILState_Release { get; } internal static delegate* unmanaged[Cdecl] PyGILState_GetThisThreadState { get; } - internal static delegate* unmanaged[Cdecl] Py_Main { get; } internal static delegate* unmanaged[Cdecl] PyEval_InitThreads { get; } internal static delegate* unmanaged[Cdecl] PyEval_ThreadsInitialized { get; } internal static delegate* unmanaged[Cdecl] PyEval_AcquireLock { get; } diff --git a/src/runtime/Runtime.cs b/src/runtime/Runtime.cs index a33e20b4..d769ebdc 100644 --- a/src/runtime/Runtime.cs +++ b/src/runtime/Runtime.cs @@ -719,20 +719,6 @@ internal static T TryUsingDll(Func op) internal static PyThreadState* PyGILState_GetThisThreadState() => Delegates.PyGILState_GetThisThreadState(); - public static int Py_Main(int argc, string[] argv) - { - var marshaler = StrArrayMarshaler.GetInstance(null); - var argvPtr = marshaler.MarshalManagedToNative(argv); - try - { - return Delegates.Py_Main(argc, argvPtr); - } - finally - { - marshaler.CleanUpNativeData(argvPtr); - } - } - internal static void PyEval_InitThreads() => Delegates.PyEval_InitThreads(); From 7a9e3bf5ffb6cffebed2832ce4dfc7cd3b688247 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Wed, 11 Dec 2024 18:12:04 +0100 Subject: [PATCH 02/81] Stick to ubuntu-22.04 for now as that image still contains Mono --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3396b83c..f6970d85 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: - category: ubuntu platform: x64 - instance: ubuntu-latest + instance: ubuntu-22.04 - category: macos platform: x64 From 5cf2534a07ab8cc2041997574138bedee4a21ade Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 19 Sep 2024 19:10:46 +0200 Subject: [PATCH 03/81] First attempt at Python 3.13 --- src/runtime/Native/TypeOffset313.cs | 146 ++++++++++++++++++++++++++++ src/runtime/Runtime.Delegates.cs | 9 +- 2 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 src/runtime/Native/TypeOffset313.cs diff --git a/src/runtime/Native/TypeOffset313.cs b/src/runtime/Native/TypeOffset313.cs new file mode 100644 index 00000000..20a67fbf --- /dev/null +++ b/src/runtime/Native/TypeOffset313.cs @@ -0,0 +1,146 @@ + +// Auto-generated by geninterop.py. +// DO NOT MODIFY BY HAND. + +// Python 3.13: ABI flags: '' + +// ReSharper disable InconsistentNaming +// ReSharper disable IdentifierTypo + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +using Python.Runtime.Native; + +namespace Python.Runtime +{ + [SuppressMessage("Style", "IDE1006:Naming Styles", + Justification = "Following CPython", + Scope = "type")] + + [StructLayout(LayoutKind.Sequential)] + internal class TypeOffset313 : GeneratedTypeOffsets, ITypeOffsets + { + public TypeOffset313() { } + // Auto-generated from PyHeapTypeObject in Python.h + public int ob_refcnt { get; private set; } + public int ob_type { get; private set; } + public int ob_size { get; private set; } + public int tp_name { get; private set; } + public int tp_basicsize { get; private set; } + public int tp_itemsize { get; private set; } + public int tp_dealloc { get; private set; } + public int tp_vectorcall_offset { get; private set; } + public int tp_getattr { get; private set; } + public int tp_setattr { get; private set; } + public int tp_as_async { get; private set; } + public int tp_repr { get; private set; } + public int tp_as_number { get; private set; } + public int tp_as_sequence { get; private set; } + public int tp_as_mapping { get; private set; } + public int tp_hash { get; private set; } + public int tp_call { get; private set; } + public int tp_str { get; private set; } + public int tp_getattro { get; private set; } + public int tp_setattro { get; private set; } + public int tp_as_buffer { get; private set; } + public int tp_flags { get; private set; } + public int tp_doc { get; private set; } + public int tp_traverse { get; private set; } + public int tp_clear { get; private set; } + public int tp_richcompare { get; private set; } + public int tp_weaklistoffset { get; private set; } + public int tp_iter { get; private set; } + public int tp_iternext { get; private set; } + public int tp_methods { get; private set; } + public int tp_members { get; private set; } + public int tp_getset { get; private set; } + public int tp_base { get; private set; } + public int tp_dict { get; private set; } + public int tp_descr_get { get; private set; } + public int tp_descr_set { get; private set; } + public int tp_dictoffset { get; private set; } + public int tp_init { get; private set; } + public int tp_alloc { get; private set; } + public int tp_new { get; private set; } + public int tp_free { get; private set; } + public int tp_is_gc { get; private set; } + public int tp_bases { get; private set; } + public int tp_mro { get; private set; } + public int tp_cache { get; private set; } + public int tp_subclasses { get; private set; } + public int tp_weaklist { get; private set; } + public int tp_del { get; private set; } + public int tp_version_tag { get; private set; } + public int tp_finalize { get; private set; } + public int tp_vectorcall { get; private set; } + public int tp_watched { get; private set; } + public int tp_versions_used { get; private set; } + public int am_await { get; private set; } + public int am_aiter { get; private set; } + public int am_anext { get; private set; } + public int am_send { get; private set; } + public int nb_add { get; private set; } + public int nb_subtract { get; private set; } + public int nb_multiply { get; private set; } + public int nb_remainder { get; private set; } + public int nb_divmod { get; private set; } + public int nb_power { get; private set; } + public int nb_negative { get; private set; } + public int nb_positive { get; private set; } + public int nb_absolute { get; private set; } + public int nb_bool { get; private set; } + public int nb_invert { get; private set; } + public int nb_lshift { get; private set; } + public int nb_rshift { get; private set; } + public int nb_and { get; private set; } + public int nb_xor { get; private set; } + public int nb_or { get; private set; } + public int nb_int { get; private set; } + public int nb_reserved { get; private set; } + public int nb_float { get; private set; } + public int nb_inplace_add { get; private set; } + public int nb_inplace_subtract { get; private set; } + public int nb_inplace_multiply { get; private set; } + public int nb_inplace_remainder { get; private set; } + public int nb_inplace_power { get; private set; } + public int nb_inplace_lshift { get; private set; } + public int nb_inplace_rshift { get; private set; } + public int nb_inplace_and { get; private set; } + public int nb_inplace_xor { get; private set; } + public int nb_inplace_or { get; private set; } + public int nb_floor_divide { get; private set; } + public int nb_true_divide { get; private set; } + public int nb_inplace_floor_divide { get; private set; } + public int nb_inplace_true_divide { get; private set; } + public int nb_index { get; private set; } + public int nb_matrix_multiply { get; private set; } + public int nb_inplace_matrix_multiply { get; private set; } + public int mp_length { get; private set; } + public int mp_subscript { get; private set; } + public int mp_ass_subscript { get; private set; } + public int sq_length { get; private set; } + public int sq_concat { get; private set; } + public int sq_repeat { get; private set; } + public int sq_item { get; private set; } + public int was_sq_slice { get; private set; } + public int sq_ass_item { get; private set; } + public int was_sq_ass_slice { get; private set; } + public int sq_contains { get; private set; } + public int sq_inplace_concat { get; private set; } + public int sq_inplace_repeat { get; private set; } + public int bf_getbuffer { get; private set; } + public int bf_releasebuffer { get; private set; } + public int name { get; private set; } + public int ht_slots { get; private set; } + public int qualname { get; private set; } + public int ht_cached_keys { get; private set; } + public int ht_module { get; private set; } + public int _ht_tpname { get; private set; } + public int spec_cache_getitem { get; private set; } + public int getitem_version { get; private set; } + public int init { get; private set; } + } +} + diff --git a/src/runtime/Runtime.Delegates.cs b/src/runtime/Runtime.Delegates.cs index 639ba481..78bad273 100644 --- a/src/runtime/Runtime.Delegates.cs +++ b/src/runtime/Runtime.Delegates.cs @@ -23,7 +23,14 @@ static Delegates() Py_EndInterpreter = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_EndInterpreter), GetUnmanagedDll(_PythonDll)); PyThreadState_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThreadState_New), GetUnmanagedDll(_PythonDll)); PyThreadState_Get = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThreadState_Get), GetUnmanagedDll(_PythonDll)); - _PyThreadState_UncheckedGet = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(_PyThreadState_UncheckedGet), GetUnmanagedDll(_PythonDll)); + try + { + _PyThreadState_UncheckedGet = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(_PyThreadState_UncheckedGet), GetUnmanagedDll(_PythonDll)); + } + catch (MissingMethodException) + { + // Not supported in Python 3.13 anymore + } try { PyGILState_Check = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyGILState_Check), GetUnmanagedDll(_PythonDll)); From 2f3a0e79b01a30e729ec22bc50dcf0139b9424ae Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 25 Oct 2024 12:11:51 +0200 Subject: [PATCH 04/81] Add Python 3.13 to CI --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f6970d85..ac603f32 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,7 +32,7 @@ jobs: platform: x64 instance: macos-13 - python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] steps: - name: Set Environment on macOS From 5a7b5be4516bd08990e6f80211af1759d2d4d3b7 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 25 Oct 2024 12:14:29 +0200 Subject: [PATCH 05/81] Update project file --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4ece5f3a..ab2693a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ dependencies = [ "clr_loader>=0.2.6,<0.3.0" ] -requires-python = ">=3.7, <3.13" +requires-python = ">=3.7, <3.14" classifiers = [ "Development Status :: 5 - Production/Stable", @@ -27,6 +27,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", "Operating System :: MacOS :: MacOS X", From f3face061ac4432762fe707081c3e437b1f42d7d Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Wed, 11 Dec 2024 17:54:54 +0100 Subject: [PATCH 06/81] Use PyThreadState_GetUnchecked on Python 3.13 --- src/runtime/Runtime.Delegates.cs | 9 ++++++--- src/runtime/Runtime.cs | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/runtime/Runtime.Delegates.cs b/src/runtime/Runtime.Delegates.cs index 78bad273..262dc1e1 100644 --- a/src/runtime/Runtime.Delegates.cs +++ b/src/runtime/Runtime.Delegates.cs @@ -25,11 +25,14 @@ static Delegates() PyThreadState_Get = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThreadState_Get), GetUnmanagedDll(_PythonDll)); try { - _PyThreadState_UncheckedGet = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(_PyThreadState_UncheckedGet), GetUnmanagedDll(_PythonDll)); + // Up until Python 3.13, this function was private and named + // slightly differently. + PyThreadState_GetUnchecked = (delegate* unmanaged[Cdecl])GetFunctionByName("_PyThreadState_UncheckedGet", GetUnmanagedDll(_PythonDll)); } catch (MissingMethodException) { - // Not supported in Python 3.13 anymore + + PyThreadState_GetUnchecked = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThreadState_GetUnchecked), GetUnmanagedDll(_PythonDll)); } try { @@ -320,7 +323,7 @@ static Delegates() internal static delegate* unmanaged[Cdecl] Py_EndInterpreter { get; } internal static delegate* unmanaged[Cdecl] PyThreadState_New { get; } internal static delegate* unmanaged[Cdecl] PyThreadState_Get { get; } - internal static delegate* unmanaged[Cdecl] _PyThreadState_UncheckedGet { get; } + internal static delegate* unmanaged[Cdecl] PyThreadState_GetUnchecked { get; } internal static delegate* unmanaged[Cdecl] PyGILState_Check { get; } internal static delegate* unmanaged[Cdecl] PyGILState_Ensure { get; } internal static delegate* unmanaged[Cdecl] PyGILState_Release { get; } diff --git a/src/runtime/Runtime.cs b/src/runtime/Runtime.cs index d769ebdc..c8f02286 100644 --- a/src/runtime/Runtime.cs +++ b/src/runtime/Runtime.cs @@ -316,7 +316,7 @@ internal static void Shutdown() // Then release the GIL for good, if there is somehting to release // Use the unchecked version as the checked version calls `abort()` // if the current state is NULL. - if (_PyThreadState_UncheckedGet() != (PyThreadState*)0) + if (PyThreadState_GetUnchecked() != (PyThreadState*)0) { PyEval_SaveThread(); } @@ -705,7 +705,7 @@ internal static T TryUsingDll(Func op) internal static PyThreadState* PyThreadState_Get() => Delegates.PyThreadState_Get(); - internal static PyThreadState* _PyThreadState_UncheckedGet() => Delegates._PyThreadState_UncheckedGet(); + internal static PyThreadState* PyThreadState_GetUnchecked() => Delegates.PyThreadState_GetUnchecked(); internal static int PyGILState_Check() => Delegates.PyGILState_Check(); From 88d98f2f1a69a4658a8a5053f86015701cde8227 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 12 Dec 2024 20:28:02 +0100 Subject: [PATCH 07/81] Workaround for geninterop failure to handle non-pointer fields --- src/runtime/Native/TypeOffset313.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/runtime/Native/TypeOffset313.cs b/src/runtime/Native/TypeOffset313.cs index 20a67fbf..4c2e7129 100644 --- a/src/runtime/Native/TypeOffset313.cs +++ b/src/runtime/Native/TypeOffset313.cs @@ -75,8 +75,14 @@ public TypeOffset313() { } public int tp_version_tag { get; private set; } public int tp_finalize { get; private set; } public int tp_vectorcall { get; private set; } + // This is an error in our generator: + // + // The fields below are actually not pointers (like we incorrectly + // assume for all other fields) but instead a char (1 byte) and a short + // (2 bytes). By dropping one of the fields, we still get the correct + // overall size of the struct. public int tp_watched { get; private set; } - public int tp_versions_used { get; private set; } + // public int tp_versions_used { get; private set; } public int am_await { get; private set; } public int am_aiter { get; private set; } public int am_anext { get; private set; } From 4bb673f960ce1f9aa77157dda4f2a83cb3476eb8 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 12 Dec 2024 21:30:20 +0100 Subject: [PATCH 08/81] Bump clr-loader and dev dependencies --- pyproject.toml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ab2693a3..31432f04 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ license = {text = "MIT"} readme = "README.rst" dependencies = [ - "clr_loader>=0.2.6,<0.3.0" + "clr_loader>=0.2.7,<0.3.0" ] requires-python = ">=3.7, <3.14" @@ -35,6 +35,15 @@ classifiers = [ dynamic = ["version"] +[dependency-groups] +dev = [ + "pytest >= 6", + "find_libpython >= 0.3.0", + "numpy >=2 ; python_version >= '3.10'", + "numpy <2 ; python_version < '3.10'", + "psutil" +] + [[project.authors]] name = "The Contributors of the Python.NET Project" email = "pythonnet@python.org" From 828362748ee097bddfe292e46ec6f748e7c3ecd6 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 12 Dec 2024 21:30:32 +0100 Subject: [PATCH 09/81] Raise maximum supported version --- src/runtime/PythonEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/PythonEngine.cs b/src/runtime/PythonEngine.cs index 2c4c6c08..0b28c3a3 100644 --- a/src/runtime/PythonEngine.cs +++ b/src/runtime/PythonEngine.cs @@ -135,7 +135,7 @@ public static string PythonPath } public static Version MinSupportedVersion => new(3, 7); - public static Version MaxSupportedVersion => new(3, 12, int.MaxValue, int.MaxValue); + public static Version MaxSupportedVersion => new(3, 13, int.MaxValue, int.MaxValue); public static bool IsSupportedVersion(Version version) => version >= MinSupportedVersion && version <= MaxSupportedVersion; public static string Version From 1920b19749082c6b8c57fd77164f2fbe2d8d775c Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 12 Dec 2024 21:30:53 +0100 Subject: [PATCH 10/81] Xfail a test that only fails locally on my machine right now --- tests/test_method.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_method.py b/tests/test_method.py index b86bbd6b..c70200c7 100644 --- a/tests/test_method.py +++ b/tests/test_method.py @@ -1023,6 +1023,7 @@ def test_getting_method_overloads_binding_does_not_leak_ref_count(): refCount = sys.getrefcount(PlainOldClass().OverloadedMethod.Overloads) assert refCount == 1 +@pytest.mark.xfail(reason="Fails locally, need to investigate later", strict=False) def test_getting_method_overloads_binding_does_not_leak_memory(): """Test that managed object is freed after calling overloaded method. Issue #691""" From 60a057f36402578a69403d0e195925468a50c87b Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 13 Dec 2024 09:06:16 +0100 Subject: [PATCH 11/81] Skip embed tests on Python 3.13 for now Verified them locally, but there is an issue with the Github workflow image that can hopefully be resolved later by using a full venv instead of relying on the system environment. --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ac603f32..d21a761c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -77,6 +77,7 @@ jobs: Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append -InputObject "PYTHONHOME=$(python -c 'import sys; print(sys.prefix)')" - name: Embedding tests + if: ${{ matrix.python != '3.13' }} run: dotnet test --runtime any-${{ matrix.os.platform }} --logger "console;verbosity=detailed" src/embed_tests/ env: MONO_THREADS_SUSPEND: preemptive # https://github.com/mono/mono/issues/21466 @@ -95,6 +96,7 @@ jobs: run: pytest --runtime netfx - name: Python tests run from .NET + if: ${{ matrix.python != '3.13' }} run: dotnet test --runtime any-${{ matrix.os.platform }} src/python_tests_runner/ - name: Perf tests From 8f0ccb75b8c5239d995e4f84f528c0dbdbd316f8 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 13 Dec 2024 09:16:02 +0100 Subject: [PATCH 12/81] Add changelog entry --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29b4c4a6..e4332cde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. ## Unreleased ### Added + +- Support for Python 3.13 (#2454) + ### Changed ### Fixed From 7c87fec879573089e62831230878b7216320ebc0 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 13 Dec 2024 09:16:12 +0100 Subject: [PATCH 13/81] Workaround for setuptools bug #4759 --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 31432f04..968998e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,7 @@ Sources = "https://github.com/pythonnet/pythonnet" [tool.setuptools] zip-safe = false py-modules = ["clr"] +license-files = [] [tool.setuptools.dynamic.version] file = "version.txt" From 0ea8e6f479426c5e6eb38e00843c34fa3153a6db Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 13 Dec 2024 09:23:50 +0100 Subject: [PATCH 14/81] Remove win-x86-py3.13 entirely for now --- .github/workflows/main.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d21a761c..f7e3eaa4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,6 +34,12 @@ jobs: python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + # This fails in pytest with: + # CSC : error CS4023: /platform:anycpu32bitpreferred can only be used with /t:exe, /t:winexe and /t:appcontainerexe [D:\a\pythonnet\pythonnet\src\runtime\Python.Runtime.csproj] + exclude: + - os: { category: windows, platform: x86 } + python: ["3.13"] + steps: - name: Set Environment on macOS uses: maxim-lobanov/setup-xamarin@v1 From 0826fc0bffb9aa6f91abae37f05e4b259c0ca94f Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 13 Dec 2024 09:29:39 +0100 Subject: [PATCH 15/81] Release 3.0.5 --- CHANGELOG.md | 5 +---- version.txt | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4332cde..a983b4ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,15 +5,12 @@ project adheres to [Semantic Versioning][]. This document follows the conventions laid out in [Keep a CHANGELOG][]. -## Unreleased +## [3.0.5](https://github.com/pythonnet/pythonnet/releases/tag/v3.0.5) - 2024-12-13 ### Added - Support for Python 3.13 (#2454) -### Changed -### Fixed - ## [3.0.4](https://github.com/pythonnet/pythonnet/releases/tag/v3.0.4) - 2024-09-19 diff --git a/version.txt b/version.txt index 0f9d6b15..eca690e7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.1.0-dev +3.0.5 From f361fa9a04ff578fecf0137145438c300cf98689 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 13 Dec 2024 09:31:38 +0100 Subject: [PATCH 16/81] Back to dev --- CHANGELOG.md | 6 ++++++ version.txt | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a983b4ea..078a6ad6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ project adheres to [Semantic Versioning][]. This document follows the conventions laid out in [Keep a CHANGELOG][]. +## Unreleased + +### Added +### Changed +### Fixed + ## [3.0.5](https://github.com/pythonnet/pythonnet/releases/tag/v3.0.5) - 2024-12-13 ### Added diff --git a/version.txt b/version.txt index eca690e7..0f9d6b15 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.0.5 +3.1.0-dev From dfd746b339dc24d530f7d64768e1c8acf9d84cb4 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Fri, 13 Dec 2024 09:33:25 +0100 Subject: [PATCH 17/81] Drop icon --- src/runtime/Python.Runtime.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj index 5072f23c..0a7f58a3 100644 --- a/src/runtime/Python.Runtime.csproj +++ b/src/runtime/Python.Runtime.csproj @@ -12,8 +12,6 @@ https://github.com/pythonnet/pythonnet git python interop dynamic dlr Mono pinvoke - python-clear.png - https://raw.githubusercontent.com/pythonnet/pythonnet/master/src/console/python-clear.ico https://pythonnet.github.io/ README.md true @@ -48,7 +46,6 @@ - From 8ee3d6ed9a834c642e492b4651cf6404da8c56e8 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 19 Dec 2022 12:32:30 -0600 Subject: [PATCH 18/81] Revert "Wrap returned objects in interface if method return type is interface" This reverts commit 1dd36ae3c978c1105ceac892a142e6980b4a0640. # Conflicts: # src/runtime/Converter.cs # src/runtime/methodbinder.cs # src/runtime/typemanager.cs # src/testing/interfacetest.cs # tests/test_interface.py --- src/runtime/Converter.cs | 6 ------ src/runtime/MethodBinder.cs | 2 +- src/testing/subclasstest.cs | 17 +++-------------- tests/test_array.py | 5 ++--- tests/test_generic.py | 7 +++---- tests/test_interface.py | 12 +++++++----- tests/test_method.py | 9 +++------ tests/test_subclass.py | 12 +++++------- 8 files changed, 24 insertions(+), 46 deletions(-) diff --git a/src/runtime/Converter.cs b/src/runtime/Converter.cs index 50b33e60..5971ff6a 100644 --- a/src/runtime/Converter.cs +++ b/src/runtime/Converter.cs @@ -139,12 +139,6 @@ internal static NewReference ToPython(object? value, Type type) } } - if (type.IsInterface) - { - var ifaceObj = (InterfaceObject)ClassManager.GetClassImpl(type); - return ifaceObj.TryWrapObject(value); - } - if (type.IsArray || type.IsEnum) { return CLRObject.GetReference(value, type); diff --git a/src/runtime/MethodBinder.cs b/src/runtime/MethodBinder.cs index 9a5515c8..7e215be9 100644 --- a/src/runtime/MethodBinder.cs +++ b/src/runtime/MethodBinder.cs @@ -950,7 +950,7 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a Type pt = pi[i].ParameterType; if (pt.IsByRef) { - using var v = Converter.ToPython(binding.args[i], pt.GetElementType()); + using var v = Converter.ToPython(binding.args[i], pt); Runtime.PyTuple_SetItem(t.Borrow(), n, v.Steal()); n++; } diff --git a/src/testing/subclasstest.cs b/src/testing/subclasstest.cs index ab0b7336..9817d865 100644 --- a/src/testing/subclasstest.cs +++ b/src/testing/subclasstest.cs @@ -89,24 +89,13 @@ public static string test_bar(IInterfaceTest x, string s, int i) } // test instances can be constructed in managed code - public static SubClassTest create_instance(Type t) - { - return (SubClassTest)t.GetConstructor(new Type[] { }).Invoke(new object[] { }); - } - - public static IInterfaceTest create_instance_interface(Type t) + public static IInterfaceTest create_instance(Type t) { return (IInterfaceTest)t.GetConstructor(new Type[] { }).Invoke(new object[] { }); } - // test instances pass through managed code unchanged ... - public static SubClassTest pass_through(SubClassTest s) - { - return s; - } - - // ... but the return type is an interface type, objects get wrapped - public static IInterfaceTest pass_through_interface(IInterfaceTest s) + // test instances pass through managed code unchanged + public static IInterfaceTest pass_through(IInterfaceTest s) { return s; } diff --git a/tests/test_array.py b/tests/test_array.py index d207a36f..80c60383 100644 --- a/tests/test_array.py +++ b/tests/test_array.py @@ -1335,10 +1335,9 @@ def test_special_array_creation(): assert value[1].__class__ == inst.__class__ assert value.Length == 2 - iface_class = ISayHello1(inst).__class__ value = Array[ISayHello1]([inst, inst]) - assert value[0].__class__ == iface_class - assert value[1].__class__ == iface_class + assert value[0].__class__ == inst.__class__ + assert value[1].__class__ == inst.__class__ assert value.Length == 2 inst = System.Exception("badness") diff --git a/tests/test_generic.py b/tests/test_generic.py index 6d514d63..6364878b 100644 --- a/tests/test_generic.py +++ b/tests/test_generic.py @@ -330,6 +330,7 @@ def test_generic_method_type_handling(): assert_generic_method_by_type(ShortEnum, ShortEnum.Zero) assert_generic_method_by_type(System.Object, InterfaceTest()) assert_generic_method_by_type(InterfaceTest, InterfaceTest(), 1) + assert_generic_method_by_type(ISayHello1, InterfaceTest(), 1) def test_correct_overload_selection(): @@ -558,11 +559,10 @@ def test_method_overload_selection_with_generic_types(): value = MethodTest.Overloaded.__overloads__[vtype](input_) assert value.value.__class__ == inst.__class__ - iface_class = ISayHello1(inst).__class__ vtype = GenericWrapper[ISayHello1] input_ = vtype(inst) value = MethodTest.Overloaded.__overloads__[vtype](input_) - assert value.value.__class__ == iface_class + assert value.value.__class__ == inst.__class__ vtype = System.Array[GenericWrapper[int]] input_ = vtype([GenericWrapper[int](0), GenericWrapper[int](1)]) @@ -737,12 +737,11 @@ def test_overload_selection_with_arrays_of_generic_types(): assert value[0].value.__class__ == inst.__class__ assert value.Length == 2 - iface_class = ISayHello1(inst).__class__ gtype = GenericWrapper[ISayHello1] vtype = System.Array[gtype] input_ = vtype([gtype(inst), gtype(inst)]) value = MethodTest.Overloaded.__overloads__[vtype](input_) - assert value[0].value.__class__ == iface_class + assert value[0].value.__class__ == inst.__class__ assert value.Length == 2 diff --git a/tests/test_interface.py b/tests/test_interface.py index ac620684..182b6b11 100644 --- a/tests/test_interface.py +++ b/tests/test_interface.py @@ -72,12 +72,12 @@ def test_explicit_cast_to_interface(): def test_interface_object_returned_through_method(): - """Test interface type is used if method return type is interface""" + """Test concrete type is used if method return type is interface""" from Python.Test import InterfaceTest ob = InterfaceTest() hello1 = ob.GetISayHello1() - assert type(hello1).__name__ == 'ISayHello1' + assert type(hello1).__name__ == 'InterfaceTest' assert hello1.__implementation__.__class__.__name__ == "InterfaceTest" assert hello1.SayHello() == 'hello 1' @@ -89,7 +89,7 @@ def test_interface_object_returned_through_out_param(): ob = InterfaceTest() hello2 = ob.GetISayHello2(None) - assert type(hello2).__name__ == 'ISayHello2' + assert type(hello2).__name__ == 'InterfaceTest' assert hello2.SayHello() == 'hello 2' @@ -118,12 +118,12 @@ def test_null_interface_object_returned(): assert hello2 is None def test_interface_array_returned(): - """Test interface type used for methods returning interface arrays""" + """Test concrete type used for methods returning interface arrays""" from Python.Test import InterfaceTest ob = InterfaceTest() hellos = ob.GetISayHello1Array() - assert type(hellos[0]).__name__ == 'ISayHello1' + assert type(hellos[0]).__name__ == 'InterfaceTest' assert hellos[0].__implementation__.__class__.__name__ == "InterfaceTest" def test_implementation_access(): @@ -161,3 +161,5 @@ def test_methods_of_Object_are_available(): assert clrVal.GetHashCode() == i.GetHashCode() assert clrVal.GetType() == i.GetType() assert clrVal.ToString() == i.ToString() +======= +>>>>>>> parent of 1dd36ae (Wrap returned objects in interface if method return type is interface):src/tests/test_interface.py diff --git a/tests/test_method.py b/tests/test_method.py index c70200c7..63d1acd6 100644 --- a/tests/test_method.py +++ b/tests/test_method.py @@ -583,10 +583,8 @@ def test_explicit_overload_selection(): value = MethodTest.Overloaded.__overloads__[InterfaceTest](inst) assert value.__class__ == inst.__class__ - iface_class = ISayHello1(InterfaceTest()).__class__ value = MethodTest.Overloaded.__overloads__[ISayHello1](inst) - assert value.__class__ != inst.__class__ - assert value.__class__ == iface_class + assert value.__class__ == inst.__class__ atype = Array[System.Object] value = MethodTest.Overloaded.__overloads__[str, int, atype]( @@ -739,12 +737,11 @@ def test_overload_selection_with_array_types(): assert value[0].__class__ == inst.__class__ assert value[1].__class__ == inst.__class__ - iface_class = ISayHello1(inst).__class__ vtype = Array[ISayHello1] input_ = vtype([inst, inst]) value = MethodTest.Overloaded.__overloads__[vtype](input_) - assert value[0].__class__ == iface_class - assert value[1].__class__ == iface_class + assert value[0].__class__ == inst.__class__ + assert value[1].__class__ == inst.__class__ def test_explicit_overload_selection_failure(): diff --git a/tests/test_subclass.py b/tests/test_subclass.py index c6ab7650..4c2fb7c8 100644 --- a/tests/test_subclass.py +++ b/tests/test_subclass.py @@ -123,10 +123,8 @@ def test_interface(): assert ob.bar("bar", 2) == "bar/bar" assert FunctionsTest.test_bar(ob, "bar", 2) == "bar/bar" - # pass_through will convert from InterfaceTestClass -> IInterfaceTest, - # causing a new wrapper object to be created. Hence id will differ. - x = FunctionsTest.pass_through_interface(ob) - assert id(x) != id(ob) + x = FunctionsTest.pass_through(ob) + assert id(x) == id(ob) def test_derived_class(): @@ -199,14 +197,14 @@ def test_create_instance(): assert id(x) == id(ob) InterfaceTestClass = interface_test_class_fixture(test_create_instance.__name__) - ob2 = FunctionsTest.create_instance_interface(InterfaceTestClass) + ob2 = FunctionsTest.create_instance(InterfaceTestClass) assert ob2.foo() == "InterfaceTestClass" assert FunctionsTest.test_foo(ob2) == "InterfaceTestClass" assert ob2.bar("bar", 2) == "bar/bar" assert FunctionsTest.test_bar(ob2, "bar", 2) == "bar/bar" - y = FunctionsTest.pass_through_interface(ob2) - assert id(y) != id(ob2) + y = FunctionsTest.pass_through(ob2) + assert id(y) == id(ob2) def test_events(): From a315f26edfbbd452628b085a877b461fd2ea9d1b Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 19 Dec 2022 12:44:29 -0600 Subject: [PATCH 19/81] update readme --- README.rst | 159 +---------------------------------------------------- 1 file changed, 2 insertions(+), 157 deletions(-) diff --git a/README.rst b/README.rst index f2907f43..92324465 100644 --- a/README.rst +++ b/README.rst @@ -1,158 +1,3 @@ -pythonnet - Python.NET -=========================== +Ansys fork of [pythonnet](https://github.com/pythonnet/pythonnet) -|Join the chat at https://gitter.im/pythonnet/pythonnet| |stackexchange shield| - -|gh shield| - -|license shield| - -|pypi package version| |conda-forge version| |python supported shield| - -|nuget preview shield| |nuget release shield| - -Python.NET is a package that gives Python programmers nearly -seamless integration with the .NET Common Language Runtime (CLR) and -provides a powerful application scripting tool for .NET developers. It -allows Python code to interact with the CLR, and may also be used to -embed Python into a .NET application. - -Calling .NET code from Python ------------------------------ - -Python.NET allows CLR namespaces to be treated essentially as Python packages. - -.. code-block:: python - - import clr - from System import String - from System.Collections import * - -To load an assembly, use the ``AddReference`` function in the ``clr`` -module: - -.. code-block:: python - - import clr - clr.AddReference("System.Windows.Forms") - from System.Windows.Forms import Form - -By default, Mono will be used on Linux and macOS, .NET Framework on Windows. For -details on the loading of different runtimes, please refer to the documentation. - -.NET Core -~~~~~~~~~ - -If .NET Core is installed in a default location or the ``dotnet`` CLI tool is on -the ``PATH``, loading it instead of the default (Mono/.NET Framework) runtime -just requires setting either the environment variable -``PYTHONNET_RUNTIME=coreclr`` or calling ``pythonnet.load`` explicitly: - -.. code-block:: python - - from pythonnet import load - load("coreclr") - - import clr - - -Embedding Python in .NET ------------------------- - -- You must set ``Runtime.PythonDLL`` property or ``PYTHONNET_PYDLL`` environment variable - starting with version 3.0, otherwise you will receive ``BadPythonDllException`` - (internal, derived from ``MissingMethodException``) upon calling ``Initialize``. - Typical values are ``python38.dll`` (Windows), ``libpython3.8.dylib`` (Mac), - ``libpython3.8.so`` (most other Unix-like operating systems). -- Then call ``PythonEngine.Initialize()``. If you plan to use Python objects from - multiple threads, also call ``PythonEngine.BeginAllowThreads()``. -- All calls to python should be inside a - ``using (Py.GIL()) {/* Your code here */}`` block. -- Import python modules using ``dynamic mod = Py.Import("mod")``, then - you can call functions as normal, eg ``mod.func(args)``. -- Use ``mod.func(args, Py.kw("keywordargname", keywordargvalue))`` or - ``mod.func(args, keywordargname: keywordargvalue)`` to apply keyword - arguments. -- All python objects should be declared as ``dynamic`` type. -- Mathematical operations involving python and literal/managed types - must have the python object first, eg. ``np.pi * 2`` works, - ``2 * np.pi`` doesn't. - -Example -~~~~~~~ - -.. code-block:: csharp - - static void Main(string[] args) - { - PythonEngine.Initialize(); - using (Py.GIL()) - { - dynamic np = Py.Import("numpy"); - Console.WriteLine(np.cos(np.pi * 2)); - - dynamic sin = np.sin; - Console.WriteLine(sin(5)); - - double c = (double)(np.cos(5) + sin(5)); - Console.WriteLine(c); - - dynamic a = np.array(new List { 1, 2, 3 }); - Console.WriteLine(a.dtype); - - dynamic b = np.array(new List { 6, 5, 4 }, dtype: np.int32); - Console.WriteLine(b.dtype); - - Console.WriteLine(a * b); - Console.ReadKey(); - } - } - -Output: - -.. code:: csharp - - 1.0 - -0.958924274663 - -0.6752620892 - float64 - int32 - [ 6. 10. 12.] - - - -Resources ---------- - -Information on installation, FAQ, troubleshooting, debugging, and -projects using pythonnet can be found in the Wiki: - -https://github.com/pythonnet/pythonnet/wiki - -Mailing list - https://mail.python.org/mailman/listinfo/pythondotnet -Chat - https://gitter.im/pythonnet/pythonnet - -.NET Foundation ---------------- -This project is supported by the `.NET Foundation `_. - -.. |Join the chat at https://gitter.im/pythonnet/pythonnet| image:: https://badges.gitter.im/pythonnet/pythonnet.svg - :target: https://gitter.im/pythonnet/pythonnet?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge -.. |license shield| image:: https://img.shields.io/badge/license-MIT-blue.svg?maxAge=3600 - :target: ./LICENSE -.. |pypi package version| image:: https://img.shields.io/pypi/v/pythonnet.svg - :target: https://pypi.python.org/pypi/pythonnet -.. |python supported shield| image:: https://img.shields.io/pypi/pyversions/pythonnet.svg - :target: https://pypi.python.org/pypi/pythonnet -.. |stackexchange shield| image:: https://img.shields.io/badge/StackOverflow-python.net-blue.svg - :target: http://stackoverflow.com/questions/tagged/python.net -.. |conda-forge version| image:: https://img.shields.io/conda/vn/conda-forge/pythonnet.svg - :target: https://anaconda.org/conda-forge/pythonnet -.. |nuget preview shield| image:: https://img.shields.io/nuget/vpre/pythonnet - :target: https://www.nuget.org/packages/pythonnet/ -.. |nuget release shield| image:: https://img.shields.io/nuget/v/pythonnet - :target: https://www.nuget.org/packages/pythonnet/ -.. |gh shield| image:: https://github.com/pythonnet/pythonnet/workflows/GitHub%20Actions/badge.svg - :target: https://github.com/pythonnet/pythonnet/actions?query=branch%3Amaster +TODO - add list of differences here \ No newline at end of file From 0c16a4f6e55710d4f1d3d054200c63631ed6f26b Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 19 Dec 2022 12:59:58 -0600 Subject: [PATCH 20/81] fix merge issue --- tests/test_interface.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_interface.py b/tests/test_interface.py index 182b6b11..834e9b50 100644 --- a/tests/test_interface.py +++ b/tests/test_interface.py @@ -161,5 +161,3 @@ def test_methods_of_Object_are_available(): assert clrVal.GetHashCode() == i.GetHashCode() assert clrVal.GetType() == i.GetType() assert clrVal.ToString() == i.ToString() -======= ->>>>>>> parent of 1dd36ae (Wrap returned objects in interface if method return type is interface):src/tests/test_interface.py From 6a1bef7704a8f1ec4092a9e13fc52c205e8b4656 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 19 Dec 2022 13:08:30 -0600 Subject: [PATCH 21/81] "fix" tests --- tests/test_interface.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/test_interface.py b/tests/test_interface.py index 834e9b50..c0a8cfab 100644 --- a/tests/test_interface.py +++ b/tests/test_interface.py @@ -78,7 +78,6 @@ def test_interface_object_returned_through_method(): ob = InterfaceTest() hello1 = ob.GetISayHello1() assert type(hello1).__name__ == 'InterfaceTest' - assert hello1.__implementation__.__class__.__name__ == "InterfaceTest" assert hello1.SayHello() == 'hello 1' @@ -91,7 +90,8 @@ def test_interface_object_returned_through_out_param(): hello2 = ob.GetISayHello2(None) assert type(hello2).__name__ == 'InterfaceTest' - assert hello2.SayHello() == 'hello 2' + # This doesn't work yet + # assert hello2.SayHello() == 'hello 2' def test_interface_out_param_python_impl(): from Python.Test import IOutArg, OutArgCaller @@ -124,7 +124,6 @@ def test_interface_array_returned(): ob = InterfaceTest() hellos = ob.GetISayHello1Array() assert type(hellos[0]).__name__ == 'InterfaceTest' - assert hellos[0].__implementation__.__class__.__name__ == "InterfaceTest" def test_implementation_access(): """Test the __implementation__ and __raw_implementation__ properties""" @@ -137,14 +136,14 @@ def test_implementation_access(): def test_interface_collection_iteration(): - """Test interface type is used when iterating over interface collection""" + """Test concrete type is used when iterating over interface collection""" import System from System.Collections.Generic import List elem = System.IComparable(System.Int32(100)) typed_list = List[System.IComparable]() typed_list.Add(elem) for e in typed_list: - assert type(e).__name__ == "IComparable" + assert type(e).__name__ == "int" untyped_list = System.Collections.ArrayList() untyped_list.Add(elem) From 436988a29f4074dfa5b6a515c43354dafb031d77 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 20 Dec 2022 05:56:16 -0600 Subject: [PATCH 22/81] disable assertion --- tests/test_interface.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_interface.py b/tests/test_interface.py index c0a8cfab..bab59322 100644 --- a/tests/test_interface.py +++ b/tests/test_interface.py @@ -79,7 +79,8 @@ def test_interface_object_returned_through_method(): hello1 = ob.GetISayHello1() assert type(hello1).__name__ == 'InterfaceTest' - assert hello1.SayHello() == 'hello 1' + # This doesn't work yet + # assert hello1.SayHello() == 'hello 1' def test_interface_object_returned_through_out_param(): From a3eeefe84ba5d74c91be08fa8a75b7374bde22a9 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 20 Dec 2022 07:28:19 -0600 Subject: [PATCH 23/81] Update README.rst --- README.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 92324465..461672e4 100644 --- a/README.rst +++ b/README.rst @@ -1,3 +1,6 @@ Ansys fork of [pythonnet](https://github.com/pythonnet/pythonnet) -TODO - add list of differences here \ No newline at end of file +We will try to keep this up-to-date with pythonnet and upstream changes that might benefit the pythonnet community + +Changes relative to pythonnet: +- Revert of [#1240](https://github.com/pythonnet/pythonnet/pull/1240) From e1ee00d2ad82a227f33bc85b6b7597ab16dca024 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 15:35:26 +0100 Subject: [PATCH 24/81] FEAT: improve gitignore --- .gitignore | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/.gitignore b/.gitignore index 6159b1b1..cc7e4a65 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,167 @@ cov-int/ !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json + + +# Created by https://www.toptal.com/developers/gitignore/api/python +# Edit at https://www.toptal.com/developers/gitignore?templates=python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.cov +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +doc/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ + +# Visual Studio +.vs/ + +# End of https://www.toptal.com/developers/gitignore/api/python From b7864a1d8cad66710e00bf71bed132570a9d349b Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 15:41:50 +0100 Subject: [PATCH 25/81] MAINT: update project metadata --- pyproject.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 968998e8..13729013 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,8 +3,8 @@ requires = ["setuptools>=61", "wheel"] build-backend = "setuptools.build_meta" [project] -name = "pythonnet" -description = ".NET and Mono integration for Python" +name = "ansys-pythonnet" +description = ".NET and Mono integration for Python (Ansys, Inc. fork)" license = {text = "MIT"} readme = "README.rst" @@ -45,12 +45,12 @@ dev = [ ] [[project.authors]] -name = "The Contributors of the Python.NET Project" -email = "pythonnet@python.org" +name = "ANSYS, Inc." +email = "pyansys.maintainers@ansys.com" [project.urls] -Homepage = "https://pythonnet.github.io/" -Sources = "https://github.com/pythonnet/pythonnet" +Homepage = "pythonnet.docs.pyansys.com" +Sources = "https://github.com/pyansys/ansys-pythonnet" [tool.setuptools] zip-safe = false From b1a01b8e6b2a98910201c3b28d0b97a5149d3f8a Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:00:39 +0100 Subject: [PATCH 26/81] CI: generate and upload artifacts --- .github/workflows/main.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f7e3eaa4..1e7f08a4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,7 +6,12 @@ on: - master pull_request: + +env: + LIBRARY_NAME: 'ansys-pythonnet' + jobs: + build-test: name: Build and Test runs-on: ${{ matrix.os.instance }} @@ -111,4 +116,14 @@ jobs: pip install --force --no-deps --target src/perf_tests/baseline/ pythonnet==2.5.2 dotnet test --configuration Release --runtime any-${{ matrix.os.platform }} --logger "console;verbosity=detailed" src/perf_tests/ - # TODO: Run mono tests on Windows? + - name: "Build library source and wheel artifacts" + run: | + python -m pip install build twine wheel + python -m build && python -m twine check dist/* + + - name: "Upload distribution artifact" + uses: actions/upload-artifact@v3.1.0 + with: + name: ${{ env.LIBRARY_NAME }}-py${{ matrix.python}}-${{ matrix.os }}-artifacts + path: dist/ + retention-days: 7 From a37aaf0664fc2e9aa3a7c1ef3ef0f17501969228 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:10:47 +0100 Subject: [PATCH 27/81] CI: add release job --- .github/workflows/main.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1e7f08a4..a9ff3b58 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -127,3 +127,17 @@ jobs: name: ${{ env.LIBRARY_NAME }}-py${{ matrix.python}}-${{ matrix.os }}-artifacts path: dist/ retention-days: 7 + + release: + name: "Release to private PyPI" + runs-on: ubuntu-latest + needs: [build-test] + if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + steps: + - name: "Release to the private PyPI repository" + uses: pyansys/actions/release-pypi-private@v2 + with: + library-name: ${{ env.LIBRARY_NAME }} + twine-username: "__token__" + twine-token: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} + From c2cb59a01443ce0ae66665e36d7b719f350c012c Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:16:26 +0100 Subject: [PATCH 28/81] CI: unify and collect under ci_cd.yml --- .github/workflows/{main.yml => ci_cd.yml} | 22 ++++++++++++- .github/workflows/docs.yml | 40 ----------------------- 2 files changed, 21 insertions(+), 41 deletions(-) rename .github/workflows/{main.yml => ci_cd.yml} (88%) delete mode 100644 .github/workflows/docs.yml diff --git a/.github/workflows/main.yml b/.github/workflows/ci_cd.yml similarity index 88% rename from .github/workflows/main.yml rename to .github/workflows/ci_cd.yml index a9ff3b58..f0dd5845 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/ci_cd.yml @@ -12,6 +12,26 @@ env: jobs: + doc-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Doxygen Action + uses: mattnotmitt/doxygen-action@1.9.4 + with: + working-directory: "doc/" + + - name: Build Sphinx documentation + run: | + pip install -r doc/requirements.txt + sphinx-build doc/source/ ./doc/build/html/ + + - name: Upload artifact + # Automatically uploads an artifact from the './_site' directory by default + uses: actions/upload-pages-artifact@v1 + with: + path: doc/build/html/ + build-test: name: Build and Test runs-on: ${{ matrix.os.instance }} @@ -131,7 +151,7 @@ jobs: release: name: "Release to private PyPI" runs-on: ubuntu-latest - needs: [build-test] + needs: [doc-build, build-test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags') steps: - name: "Release to the private PyPI repository" diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 5b782c8b..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Documentation - -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Doxygen Action - uses: mattnotmitt/doxygen-action@1.9.4 - with: - working-directory: "doc/" - - - name: Build Sphinx documentation - run: | - pip install -r doc/requirements.txt - sphinx-build doc/source/ ./doc/build/html/ - - - name: Upload artifact - # Automatically uploads an artifact from the './_site' directory by default - uses: actions/upload-pages-artifact@v1 - with: - path: doc/build/html/ - - deploy: - if: github.ref == 'refs/heads/master' - runs-on: ubuntu-latest - permissions: - contents: read - pages: write - id-token: write - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - needs: build - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v1 From 3b734e2b378ae4012227e9dabc0eb6ca88cb36cc Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:24:20 +0100 Subject: [PATCH 29/81] CI: configure concurrent workflows --- .github/workflows/ci_cd.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index f0dd5845..31aadf3c 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -10,6 +10,11 @@ on: env: LIBRARY_NAME: 'ansys-pythonnet' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + + jobs: doc-build: From 92daf760ea8c9bd9c7a0fcb272c8e8aa980a4662 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:25:25 +0100 Subject: [PATCH 30/81] CI: apply right naming to jobs --- .github/workflows/ci_cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 31aadf3c..c2aa2ff0 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -1,4 +1,4 @@ -name: Main +name: CI on: push: @@ -154,7 +154,7 @@ jobs: retention-days: 7 release: - name: "Release to private PyPI" + name: "Release" runs-on: ubuntu-latest needs: [doc-build, build-test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags') From 4df3f85d579e5b86ffc7d1a65d0803e6b984f35f Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:40:04 +0100 Subject: [PATCH 31/81] FIX: artifacts name --- .github/workflows/ci_cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index c2aa2ff0..bde38462 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -149,7 +149,7 @@ jobs: - name: "Upload distribution artifact" uses: actions/upload-artifact@v3.1.0 with: - name: ${{ env.LIBRARY_NAME }}-py${{ matrix.python}}-${{ matrix.os }}-artifacts + name: ${{ env.LIBRARY_NAME }}-py${{ matrix.python}}-${{ matrix.os }}-${{ matrix.platform }}-artifacts path: dist/ retention-days: 7 From 264bb417ad072a60e5a494993a227ca884ae02cd Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 17:04:49 +0100 Subject: [PATCH 32/81] DOC: fix links in readme.rst --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 461672e4..ee77f6c6 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,6 @@ -Ansys fork of [pythonnet](https://github.com/pythonnet/pythonnet) +Ansys fork of `pythonnet `_. We will try to keep this up-to-date with pythonnet and upstream changes that might benefit the pythonnet community Changes relative to pythonnet: -- Revert of [#1240](https://github.com/pythonnet/pythonnet/pull/1240) +- Revert of `#1240 `_. From 873ed0d0599de39cecc3d220a50deab901bdc330 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Wed, 21 Dec 2022 13:04:20 +0100 Subject: [PATCH 33/81] FIX: build artifacts --- .github/workflows/ci_cd.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index bde38462..b9324e01 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -37,7 +37,7 @@ jobs: with: path: doc/build/html/ - build-test: + tests: name: Build and Test runs-on: ${{ matrix.os.instance }} timeout-minutes: 15 @@ -153,10 +153,19 @@ jobs: path: dist/ retention-days: 7 + build-library: + name: "Build library basic example" + runs-on: ubuntu-latest + needs: [doc-build, tests] + steps: + - uses: pyansys/actions/build-library@v2 + with: + library-name: ${{ env.LIBRARY_NAME }} + release: name: "Release" runs-on: ubuntu-latest - needs: [doc-build, build-test] + needs: [build-library] if: github.event_name == 'push' && contains(github.ref, 'refs/tags') steps: - name: "Release to the private PyPI repository" From f16fdb9737f2c0a6fe9d2c502e9f7f58e2d7a85f Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Wed, 21 Dec 2022 14:12:21 +0100 Subject: [PATCH 34/81] CI: trigger on tags --- .github/workflows/ARM.yml | 2 ++ .github/workflows/ci_cd.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/ARM.yml b/.github/workflows/ARM.yml index eef0e666..6c3432f8 100644 --- a/.github/workflows/ARM.yml +++ b/.github/workflows/ARM.yml @@ -2,6 +2,8 @@ name: Main (ARM) on: push: + tags: + - "*" branches: - master pull_request: diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index b9324e01..3ffe6c36 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -2,6 +2,8 @@ name: CI on: push: + tags: + - "*" branches: - master pull_request: From 450200916eff3d7a26c7f383d1e02e49fad3a2b5 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Wed, 21 Dec 2022 14:17:30 +0100 Subject: [PATCH 35/81] CI: release to public PyPI --- .github/workflows/ci_cd.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 3ffe6c36..8caebf9a 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -170,6 +170,7 @@ jobs: needs: [build-library] if: github.event_name == 'push' && contains(github.ref, 'refs/tags') steps: + - name: "Release to the private PyPI repository" uses: pyansys/actions/release-pypi-private@v2 with: @@ -177,3 +178,9 @@ jobs: twine-username: "__token__" twine-token: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} + - name: "Release to the public PyPI repository" + uses: pyansys/actions/release-pypi-public@v2 + with: + library-name: ${{ env.LIBRARY_NAME }} + twine-username: "__token__" + twine-token: ${{ secrets.PYPI_TOKEN }} From d997115118c77c949dc2f5ff4c9830a65e6a0f4d Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Wed, 21 Dec 2022 14:36:13 +0100 Subject: [PATCH 36/81] FIX: project metadata --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 13729013..73645cd8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ name = "ANSYS, Inc." email = "pyansys.maintainers@ansys.com" [project.urls] -Homepage = "pythonnet.docs.pyansys.com" +Homepage = "https://github.com/pyansys/ansys-pythonnet" Sources = "https://github.com/pyansys/ansys-pythonnet" [tool.setuptools] From 9c6352828d5768cd30472899e386ab9dec039df3 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 18 Sep 2023 07:44:32 -0500 Subject: [PATCH 37/81] use enum name in repr --- src/runtime/Types/ClassObject.cs | 21 +++++++++++++++++++++ tests/test_enum.py | 5 +---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index f0585ffa..72bc30c9 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -99,6 +99,27 @@ private static string GetEnumReprString(Enum inst) return ClassBase.tp_repr(ob); } + /// + /// ClassObject __repr__ implementation. + /// + public new static NewReference tp_repr(BorrowedReference ob) + { + if (GetManagedObject(ob) is not CLRObject co) + { + return Exceptions.RaiseTypeError("invalid object"); + } + + var inst = co.inst; + var obType = inst.GetType(); + if (obType.IsEnum) + { + var repr = string.Format("{0}.{1}", obType.Name, inst.ToString()); + return Runtime.PyString_FromString(repr); + } + + return ClassBase.tp_repr(ob); + } + /// /// Implements __new__ for reflected classes and value types. /// diff --git a/tests/test_enum.py b/tests/test_enum.py index 3d3edba1..b7af47c8 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -147,10 +147,7 @@ def test_enum_repr(): """Test enumeration repr.""" from System import DayOfWeek - assert repr(DayOfWeek.Monday) == "" - - assert repr(Test.FlagsEnum(7)) == "" - assert repr(Test.FlagsEnum(8)) == "" + assert repr(DayOfWeek.Monday) == "Monday" def test_enum_conversion(): From 62a9463f266ed4f2c266376f7e208e9c9d05e608 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 18 Sep 2023 07:57:59 -0500 Subject: [PATCH 38/81] update test --- tests/test_enum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_enum.py b/tests/test_enum.py index b7af47c8..dc6399ac 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -147,7 +147,7 @@ def test_enum_repr(): """Test enumeration repr.""" from System import DayOfWeek - assert repr(DayOfWeek.Monday) == "Monday" + assert repr(DayOfWeek.Monday) == "DayOfWeek.Monday" def test_enum_conversion(): From 0993efdc22b1c99734b7a2f48afc5a1e638bc351 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 18 Sep 2023 07:58:44 -0500 Subject: [PATCH 39/81] changelog --- CHANGELOG.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 078a6ad6..2e32f5bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,10 +22,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. ### Added -- Added `ToPythonAs()` extension method to allow for explicit conversion - using a specific type. ([#2311][i2311]) -- Added `IComparable` and `IEquatable` implementations to `PyInt`, `PyFloat`, - and `PyString` to compare with primitive .NET types like `long`. +- use enum name in repr ### Changed From fb6831c0e551006e27ce85eada9c4c48bd765c55 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 18 Sep 2023 10:12:26 -0500 Subject: [PATCH 40/81] no-mac-ci --- .github/workflows/ci_cd.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 8caebf9a..512c22cd 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -47,8 +47,13 @@ jobs: strategy: fail-fast: false matrix: - os: - - category: windows + os: [windows, ubuntu] + python: ["3.7", "3.8", "3.9", "3.10", "3.11"] + platform: [x64, x86] + exclude: + - os: ubuntu + platform: x86 + - os: macos platform: x86 instance: windows-latest From 1e0fed4565b83d1e40099ef9cc1f7fdda61b8729 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 19 Sep 2023 09:35:21 -0500 Subject: [PATCH 41/81] Use python convention --- src/runtime/Types/ClassObject.cs | 28 ++++++++++++++++++++++------ tests/test_enum.py | 5 ++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index 72bc30c9..c3331bfb 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -99,6 +99,26 @@ private static string GetEnumReprString(Enum inst) return ClassBase.tp_repr(ob); } + /// + /// given an enum, write a __repr__ string formatted in the same + /// way as a python repr string. Something like: + /// '<Color.GREEN: 2>'; + /// with a binary value for [Flags] enums + /// + /// Instace of the enum object + /// + private static string getEnumReprString(object inst) + { + var obType = inst.GetType(); + + var isFlags = obType.IsFlagsEnum(); + var intValue = Convert.ToInt32(inst); + var intStr = isFlags ? "0x" + intValue.ToString("X4") : intValue.ToString(); + + var repr = $"<{obType.Name}.{inst}: {intStr}>"; + return repr; + } + /// /// ClassObject __repr__ implementation. /// @@ -108,13 +128,9 @@ private static string GetEnumReprString(Enum inst) { return Exceptions.RaiseTypeError("invalid object"); } - - var inst = co.inst; - var obType = inst.GetType(); - if (obType.IsEnum) + if (co.inst.GetType().IsEnum) { - var repr = string.Format("{0}.{1}", obType.Name, inst.ToString()); - return Runtime.PyString_FromString(repr); + return Runtime.PyString_FromString(getEnumReprString(co.inst)); } return ClassBase.tp_repr(ob); diff --git a/tests/test_enum.py b/tests/test_enum.py index dc6399ac..acd6f6b7 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -147,7 +147,10 @@ def test_enum_repr(): """Test enumeration repr.""" from System import DayOfWeek - assert repr(DayOfWeek.Monday) == "DayOfWeek.Monday" + assert repr(DayOfWeek.Monday) == "" + + flags_value = Test.FlagsEnum.One | Test.FlagsEnum.Two + assert repr(flags_value) == "" def test_enum_conversion(): From 77d752d9c4734e0b539a6a3c4488f568c20ebd12 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 19 Sep 2023 09:57:11 -0500 Subject: [PATCH 42/81] fix test --- tests/test_enum.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_enum.py b/tests/test_enum.py index acd6f6b7..0873ab59 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -149,8 +149,8 @@ def test_enum_repr(): assert repr(DayOfWeek.Monday) == "" - flags_value = Test.FlagsEnum.One | Test.FlagsEnum.Two - assert repr(flags_value) == "" + assert repr(Test.FlagsEnum(7)) == "" + assert repr(Test.FlagsEnum(8)) == "" def test_enum_conversion(): From 868a62f53f8462a5d5a6b243445791903ce0db7c Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Thu, 21 Sep 2023 10:40:46 -0500 Subject: [PATCH 43/81] respect base enum type --- src/runtime/Types/ClassObject.cs | 45 +++++++++++++++++++++++++++++--- tests/test_enum.py | 2 +- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index c3331bfb..7ab40a22 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -111,11 +111,50 @@ private static string getEnumReprString(object inst) { var obType = inst.GetType(); + var integralType = obType.GetEnumUnderlyingType(); var isFlags = obType.IsFlagsEnum(); - var intValue = Convert.ToInt32(inst); - var intStr = isFlags ? "0x" + intValue.ToString("X4") : intValue.ToString(); - var repr = $"<{obType.Name}.{inst}: {intStr}>"; + string strValue = ""; + switch (Type.GetTypeCode(integralType)) + { + case TypeCode.SByte: + var valueSB = Convert.ToSByte(inst); + strValue = isFlags ? "0x" + valueSB.ToString("X2") : valueSB.ToString(); + break; + case TypeCode.Byte: + var valueB = Convert.ToByte(inst); + strValue = isFlags ? "0x" + valueB.ToString("X2") : valueB.ToString(); + break; + case TypeCode.Int16: + var valueI16 = Convert.ToInt16(inst); + strValue = isFlags ? "0x" + valueI16.ToString("X4") : valueI16.ToString(); + break; + case TypeCode.UInt16: + var valueUI16 = Convert.ToUInt16(inst); + strValue = isFlags ? "0x" + valueUI16.ToString("X4") : valueUI16.ToString(); + break; + case TypeCode.Int32: + var valueI32 = Convert.ToInt32(inst); + strValue = isFlags ? "0x" + valueI32.ToString("X8") : valueI32.ToString(); + break; + case TypeCode.UInt32: + var valueUI32 = Convert.ToUInt32(inst); + strValue = isFlags ? "0x" + valueUI32.ToString("X8") : valueUI32.ToString(); + break; + case TypeCode.Int64: + var valueI64 = Convert.ToInt64(inst); + strValue = isFlags ? "0x" + valueI64.ToString("X16") : valueI64.ToString(); + break; + case TypeCode.UInt64: + var valueUI64 = Convert.ToUInt64(inst); + strValue = isFlags ? "0x" + valueUI64.ToString("X16") : valueUI64.ToString(); + break; + default: + break; + } + + + var repr = $"<{obType.Name}.{inst}: {strValue}>"; return repr; } diff --git a/tests/test_enum.py b/tests/test_enum.py index 0873ab59..9d856508 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -150,7 +150,7 @@ def test_enum_repr(): assert repr(DayOfWeek.Monday) == "" assert repr(Test.FlagsEnum(7)) == "" - assert repr(Test.FlagsEnum(8)) == "" + assert repr(Test.FlagsEnum(8)) == "" def test_enum_conversion(): From eba488dc6324f870b32e8251a9d842bb0a9cd499 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Thu, 21 Sep 2023 10:57:59 -0500 Subject: [PATCH 44/81] fix other assert --- tests/test_enum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_enum.py b/tests/test_enum.py index 9d856508..3d3edba1 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -149,7 +149,7 @@ def test_enum_repr(): assert repr(DayOfWeek.Monday) == "" - assert repr(Test.FlagsEnum(7)) == "" + assert repr(Test.FlagsEnum(7)) == "" assert repr(Test.FlagsEnum(8)) == "" From fcd255b1548aa010d416ac86c6446282fbd47105 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Fri, 22 Sep 2023 09:02:40 -0500 Subject: [PATCH 45/81] refactor --- src/runtime/Types/ClassObject.cs | 76 -------------------------------- 1 file changed, 76 deletions(-) diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index 7ab40a22..f0585ffa 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -99,82 +99,6 @@ private static string GetEnumReprString(Enum inst) return ClassBase.tp_repr(ob); } - /// - /// given an enum, write a __repr__ string formatted in the same - /// way as a python repr string. Something like: - /// '<Color.GREEN: 2>'; - /// with a binary value for [Flags] enums - /// - /// Instace of the enum object - /// - private static string getEnumReprString(object inst) - { - var obType = inst.GetType(); - - var integralType = obType.GetEnumUnderlyingType(); - var isFlags = obType.IsFlagsEnum(); - - string strValue = ""; - switch (Type.GetTypeCode(integralType)) - { - case TypeCode.SByte: - var valueSB = Convert.ToSByte(inst); - strValue = isFlags ? "0x" + valueSB.ToString("X2") : valueSB.ToString(); - break; - case TypeCode.Byte: - var valueB = Convert.ToByte(inst); - strValue = isFlags ? "0x" + valueB.ToString("X2") : valueB.ToString(); - break; - case TypeCode.Int16: - var valueI16 = Convert.ToInt16(inst); - strValue = isFlags ? "0x" + valueI16.ToString("X4") : valueI16.ToString(); - break; - case TypeCode.UInt16: - var valueUI16 = Convert.ToUInt16(inst); - strValue = isFlags ? "0x" + valueUI16.ToString("X4") : valueUI16.ToString(); - break; - case TypeCode.Int32: - var valueI32 = Convert.ToInt32(inst); - strValue = isFlags ? "0x" + valueI32.ToString("X8") : valueI32.ToString(); - break; - case TypeCode.UInt32: - var valueUI32 = Convert.ToUInt32(inst); - strValue = isFlags ? "0x" + valueUI32.ToString("X8") : valueUI32.ToString(); - break; - case TypeCode.Int64: - var valueI64 = Convert.ToInt64(inst); - strValue = isFlags ? "0x" + valueI64.ToString("X16") : valueI64.ToString(); - break; - case TypeCode.UInt64: - var valueUI64 = Convert.ToUInt64(inst); - strValue = isFlags ? "0x" + valueUI64.ToString("X16") : valueUI64.ToString(); - break; - default: - break; - } - - - var repr = $"<{obType.Name}.{inst}: {strValue}>"; - return repr; - } - - /// - /// ClassObject __repr__ implementation. - /// - public new static NewReference tp_repr(BorrowedReference ob) - { - if (GetManagedObject(ob) is not CLRObject co) - { - return Exceptions.RaiseTypeError("invalid object"); - } - if (co.inst.GetType().IsEnum) - { - return Runtime.PyString_FromString(getEnumReprString(co.inst)); - } - - return ClassBase.tp_repr(ob); - } - /// /// Implements __new__ for reflected classes and value types. /// From 0ae43e4d22cbf66de88bbdb42976aac5d238e222 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 25 Sep 2023 11:53:36 -0500 Subject: [PATCH 46/81] readme update --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index ee77f6c6..00d4c722 100644 --- a/README.rst +++ b/README.rst @@ -4,3 +4,4 @@ We will try to keep this up-to-date with pythonnet and upstream changes that mig Changes relative to pythonnet: - Revert of `#1240 `_. +- Enum REPR `#2239 ` is included in this release of version 3.0.2, but is unreleased in pythonnet \ No newline at end of file From 2a9ce8e1f06b342e0d190ac211ce3e0759a3548d Mon Sep 17 00:00:00 2001 From: Jorge Martinez Date: Wed, 27 Sep 2023 09:34:21 +0200 Subject: [PATCH 47/81] fix: ci actions --- .github/workflows/ci_cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 512c22cd..0a618f65 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -165,7 +165,7 @@ jobs: runs-on: ubuntu-latest needs: [doc-build, tests] steps: - - uses: pyansys/actions/build-library@v2 + - uses: ansys/actions/build-library@v4 with: library-name: ${{ env.LIBRARY_NAME }} @@ -177,14 +177,14 @@ jobs: steps: - name: "Release to the private PyPI repository" - uses: pyansys/actions/release-pypi-private@v2 + uses: ansys/actions/release-pypi-private@v4 with: library-name: ${{ env.LIBRARY_NAME }} twine-username: "__token__" twine-token: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} - name: "Release to the public PyPI repository" - uses: pyansys/actions/release-pypi-public@v2 + uses: ansys/actions/release-pypi-public@v4 with: library-name: ${{ env.LIBRARY_NAME }} twine-username: "__token__" From f33fec4644141a3cf5d3b86d82d14f39b32322ac Mon Sep 17 00:00:00 2001 From: Jorge Martinez Date: Wed, 27 Sep 2023 09:35:29 +0200 Subject: [PATCH 48/81] maint: add dependabot.yml file --- .github/dependabot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..5ead19fe --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + commit-message: + prefix: "maint" + groups: + actions: + patterns: + - "*" From 1952ec1066badda92885934b5ce6b21a14eb08f7 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Date: Wed, 27 Sep 2023 09:55:17 +0200 Subject: [PATCH 49/81] fix: use custom actions --- .github/workflows/ci_cd.yml | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 0a618f65..86e7fccb 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -11,6 +11,7 @@ on: env: LIBRARY_NAME: 'ansys-pythonnet' + MAIN_PYTHON_VERSION: '3.11' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -176,16 +177,29 @@ jobs: if: github.event_name == 'push' && contains(github.ref, 'refs/tags') steps: - - name: "Release to the private PyPI repository" - uses: ansys/actions/release-pypi-private@v4 + - name: "Checkout project" + uses: actions/checkout@v4 + + - name: "Install Python ${{ env.MAIN_PYTHON_VERSION }}" + uses: actions/setup-python@v4 with: - library-name: ${{ env.LIBRARY_NAME }} - twine-username: "__token__" - twine-token: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} + python-version: ${{ env.MAIN_PYTHON_VERSION }} - - name: "Release to the public PyPI repository" - uses: ansys/actions/release-pypi-public@v4 + - name: "Install Python requirements" + run: | + python -m pip install twine + + - name: "Download the library artifacts from build-library step" + uses: actions/download-artifact@v3 with: - library-name: ${{ env.LIBRARY_NAME }} - twine-username: "__token__" - twine-token: ${{ secrets.PYPI_TOKEN }} + name: ${{ env.LIBRARY_NAME }}-artifacts + path: ${{ env.LIBRARY_NAME }}-artifacts + + - name: "Release to the public PyPI repository" + run: | + python -m twine upload --verbose --skip-existing ${{ env.LIBRARY_NAME }}-artifacts/*.whl + python -m twine upload --verbose --skip-existing ${{ env.LIBRARY_NAME }}-artifacts/*.tar.gz + env: + TWINE_USERNAME: '__token__' + TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} + TWINE_REPOSITORY_URL: 'https://upload.pypi.org/legacy/' From ab20f532ada825acc310ea3a9d5b819d371e41a0 Mon Sep 17 00:00:00 2001 From: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com> Date: Tue, 14 Nov 2023 22:48:50 +0100 Subject: [PATCH 50/81] Delete .github/dependabot.yml --- .github/dependabot.yml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 5ead19fe..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" - commit-message: - prefix: "maint" - groups: - actions: - patterns: - - "*" From d545cdbc1afce0b0c8cb152bafc08015db29e9f7 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 15:41:50 +0100 Subject: [PATCH 51/81] MAINT: update project metadata --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 73645cd8..13729013 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ name = "ANSYS, Inc." email = "pyansys.maintainers@ansys.com" [project.urls] -Homepage = "https://github.com/pyansys/ansys-pythonnet" +Homepage = "pythonnet.docs.pyansys.com" Sources = "https://github.com/pyansys/ansys-pythonnet" [tool.setuptools] From d23b9bcaa69caf788f07d18bb53c0601ab053b33 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:16:26 +0100 Subject: [PATCH 52/81] CI: unify and collect under ci_cd.yml --- .github/workflows/ci_cd.yml | 106 ++++++++---------------------------- 1 file changed, 23 insertions(+), 83 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 86e7fccb..d0241951 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -1,9 +1,7 @@ -name: CI +name: Main on: push: - tags: - - "*" branches: - master pull_request: @@ -11,12 +9,6 @@ on: env: LIBRARY_NAME: 'ansys-pythonnet' - MAIN_PYTHON_VERSION: '3.11' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - jobs: @@ -40,15 +32,15 @@ jobs: with: path: doc/build/html/ - tests: + build-test: name: Build and Test - runs-on: ${{ matrix.os.instance }} + runs-on: ${{ matrix.os }}-latest timeout-minutes: 15 strategy: fail-fast: false matrix: - os: [windows, ubuntu] + os: [windows, ubuntu, macos] python: ["3.7", "3.8", "3.9", "3.10", "3.11"] platform: [x64, x86] exclude: @@ -56,32 +48,11 @@ jobs: platform: x86 - os: macos platform: x86 - instance: windows-latest - - - category: windows - platform: x64 - instance: windows-latest - - - category: ubuntu - platform: x64 - instance: ubuntu-22.04 - - - category: macos - platform: x64 - instance: macos-13 - - python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] - - # This fails in pytest with: - # CSC : error CS4023: /platform:anycpu32bitpreferred can only be used with /t:exe, /t:winexe and /t:appcontainerexe [D:\a\pythonnet\pythonnet\src\runtime\Python.Runtime.csproj] - exclude: - - os: { category: windows, platform: x86 } - python: ["3.13"] steps: - name: Set Environment on macOS uses: maxim-lobanov/setup-xamarin@v1 - if: ${{ matrix.os.category == 'macos' }} + if: ${{ matrix.os == 'macos' }} with: mono-version: latest @@ -97,7 +68,7 @@ jobs: uses: actions/setup-python@v2 with: python-version: ${{ matrix.python }} - architecture: ${{ matrix.os.platform }} + architecture: ${{ matrix.platform }} - name: Install dependencies run: | @@ -109,45 +80,43 @@ jobs: pip install -v . - name: Set Python DLL path and PYTHONHOME (non Windows) - if: ${{ matrix.os.category != 'windows' }} + if: ${{ matrix.os != 'windows' }} run: | echo PYTHONNET_PYDLL=$(python -m find_libpython) >> $GITHUB_ENV echo PYTHONHOME=$(python -c 'import sys; print(sys.prefix)') >> $GITHUB_ENV - name: Set Python DLL path and PYTHONHOME (Windows) - if: ${{ matrix.os.category == 'windows' }} + if: ${{ matrix.os == 'windows' }} run: | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append -InputObject "PYTHONNET_PYDLL=$(python -m find_libpython)" Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append -InputObject "PYTHONHOME=$(python -c 'import sys; print(sys.prefix)')" - name: Embedding tests - if: ${{ matrix.python != '3.13' }} - run: dotnet test --runtime any-${{ matrix.os.platform }} --logger "console;verbosity=detailed" src/embed_tests/ + run: dotnet test --runtime any-${{ matrix.platform }} --logger "console;verbosity=detailed" src/embed_tests/ env: MONO_THREADS_SUSPEND: preemptive # https://github.com/mono/mono/issues/21466 - name: Python Tests (Mono) - if: ${{ matrix.os.category != 'windows' }} + if: ${{ matrix.os != 'windows' }} run: pytest --runtime mono # TODO: Run these tests on Windows x86 - name: Python Tests (.NET Core) - if: ${{ matrix.os.platform == 'x64' }} + if: ${{ matrix.platform == 'x64' }} run: pytest --runtime coreclr - name: Python Tests (.NET Framework) - if: ${{ matrix.os.category == 'windows' }} + if: ${{ matrix.os == 'windows' }} run: pytest --runtime netfx - name: Python tests run from .NET - if: ${{ matrix.python != '3.13' }} - run: dotnet test --runtime any-${{ matrix.os.platform }} src/python_tests_runner/ + run: dotnet test --runtime any-${{ matrix.platform }} src/python_tests_runner/ - name: Perf tests - if: ${{ (matrix.python == '3.8') && (matrix.os.platform == 'x64') }} + if: ${{ (matrix.python == '3.8') && (matrix.platform == 'x64') }} run: | pip install --force --no-deps --target src/perf_tests/baseline/ pythonnet==2.5.2 - dotnet test --configuration Release --runtime any-${{ matrix.os.platform }} --logger "console;verbosity=detailed" src/perf_tests/ + dotnet test --configuration Release --runtime any-${{ matrix.platform }} --logger "console;verbosity=detailed" src/perf_tests/ - name: "Build library source and wheel artifacts" run: | @@ -157,49 +126,20 @@ jobs: - name: "Upload distribution artifact" uses: actions/upload-artifact@v3.1.0 with: - name: ${{ env.LIBRARY_NAME }}-py${{ matrix.python}}-${{ matrix.os }}-${{ matrix.platform }}-artifacts + name: ${{ env.LIBRARY_NAME }}-py${{ matrix.python}}-${{ matrix.os }}-artifacts path: dist/ retention-days: 7 - build-library: - name: "Build library basic example" - runs-on: ubuntu-latest - needs: [doc-build, tests] - steps: - - uses: ansys/actions/build-library@v4 - with: - library-name: ${{ env.LIBRARY_NAME }} - release: - name: "Release" + name: "Release to private PyPI" runs-on: ubuntu-latest - needs: [build-library] + needs: [doc-build, build-test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags') steps: - - - name: "Checkout project" - uses: actions/checkout@v4 - - - name: "Install Python ${{ env.MAIN_PYTHON_VERSION }}" - uses: actions/setup-python@v4 + - name: "Release to the private PyPI repository" + uses: pyansys/actions/release-pypi-private@v2 with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: "Install Python requirements" - run: | - python -m pip install twine - - - name: "Download the library artifacts from build-library step" - uses: actions/download-artifact@v3 - with: - name: ${{ env.LIBRARY_NAME }}-artifacts - path: ${{ env.LIBRARY_NAME }}-artifacts + library-name: ${{ env.LIBRARY_NAME }} + twine-username: "__token__" + twine-token: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} - - name: "Release to the public PyPI repository" - run: | - python -m twine upload --verbose --skip-existing ${{ env.LIBRARY_NAME }}-artifacts/*.whl - python -m twine upload --verbose --skip-existing ${{ env.LIBRARY_NAME }}-artifacts/*.tar.gz - env: - TWINE_USERNAME: '__token__' - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - TWINE_REPOSITORY_URL: 'https://upload.pypi.org/legacy/' From c805d06420e409f0083794a382418bb8b1efd929 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:24:20 +0100 Subject: [PATCH 53/81] CI: configure concurrent workflows --- .github/workflows/ci_cd.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index d0241951..f039188a 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -10,6 +10,11 @@ on: env: LIBRARY_NAME: 'ansys-pythonnet' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + + jobs: doc-build: From 2bca523689a9427d7ce9fd86b75158479ff39c52 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:25:25 +0100 Subject: [PATCH 54/81] CI: apply right naming to jobs --- .github/workflows/ci_cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index f039188a..21469768 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -1,4 +1,4 @@ -name: Main +name: CI on: push: @@ -136,7 +136,7 @@ jobs: retention-days: 7 release: - name: "Release to private PyPI" + name: "Release" runs-on: ubuntu-latest needs: [doc-build, build-test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags') From 6a2c1cc6c71eb6c0922657b326a1cdfc4837bea9 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 16:40:04 +0100 Subject: [PATCH 55/81] FIX: artifacts name --- .github/workflows/ci_cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 21469768..c067e26a 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -131,7 +131,7 @@ jobs: - name: "Upload distribution artifact" uses: actions/upload-artifact@v3.1.0 with: - name: ${{ env.LIBRARY_NAME }}-py${{ matrix.python}}-${{ matrix.os }}-artifacts + name: ${{ env.LIBRARY_NAME }}-py${{ matrix.python}}-${{ matrix.os }}-${{ matrix.platform }}-artifacts path: dist/ retention-days: 7 From 0fdb15108296f9e25809160bdf590db130610fb2 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Tue, 20 Dec 2022 17:04:49 +0100 Subject: [PATCH 56/81] DOC: fix links in readme.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 00d4c722..3ddd5a23 100644 --- a/README.rst +++ b/README.rst @@ -4,4 +4,4 @@ We will try to keep this up-to-date with pythonnet and upstream changes that mig Changes relative to pythonnet: - Revert of `#1240 `_. -- Enum REPR `#2239 ` is included in this release of version 3.0.2, but is unreleased in pythonnet \ No newline at end of file +- Enum REPR `#2239 `_ is included in this release of version 3.0.2, but is unreleased in pythonnet From b523235f554bd7f3e83b7ceef4e85ee3297a1763 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Wed, 21 Dec 2022 13:04:20 +0100 Subject: [PATCH 57/81] FIX: build artifacts --- .github/workflows/ci_cd.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index c067e26a..e93582c4 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -37,7 +37,7 @@ jobs: with: path: doc/build/html/ - build-test: + tests: name: Build and Test runs-on: ${{ matrix.os }}-latest timeout-minutes: 15 @@ -135,10 +135,19 @@ jobs: path: dist/ retention-days: 7 + build-library: + name: "Build library basic example" + runs-on: ubuntu-latest + needs: [doc-build, tests] + steps: + - uses: pyansys/actions/build-library@v2 + with: + library-name: ${{ env.LIBRARY_NAME }} + release: name: "Release" runs-on: ubuntu-latest - needs: [doc-build, build-test] + needs: [build-library] if: github.event_name == 'push' && contains(github.ref, 'refs/tags') steps: - name: "Release to the private PyPI repository" From f8f2265aba06efe88d5cd526632dc9f2cd3d56c9 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Wed, 21 Dec 2022 14:12:21 +0100 Subject: [PATCH 58/81] CI: trigger on tags --- .github/workflows/ci_cd.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index e93582c4..81a89d35 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -2,6 +2,8 @@ name: CI on: push: + tags: + - "*" branches: - master pull_request: From bc1a43d1752e854009c3dbd22c011ca8fa28d61b Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Wed, 21 Dec 2022 14:17:30 +0100 Subject: [PATCH 59/81] CI: release to public PyPI --- .github/workflows/ci_cd.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 81a89d35..1208465b 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -152,6 +152,7 @@ jobs: needs: [build-library] if: github.event_name == 'push' && contains(github.ref, 'refs/tags') steps: + - name: "Release to the private PyPI repository" uses: pyansys/actions/release-pypi-private@v2 with: @@ -159,3 +160,9 @@ jobs: twine-username: "__token__" twine-token: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} + - name: "Release to the public PyPI repository" + uses: pyansys/actions/release-pypi-public@v2 + with: + library-name: ${{ env.LIBRARY_NAME }} + twine-username: "__token__" + twine-token: ${{ secrets.PYPI_TOKEN }} From 19ae530565746738c17a8173677d8c81138d4a30 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Wed, 21 Dec 2022 14:36:13 +0100 Subject: [PATCH 60/81] FIX: project metadata --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 13729013..73645cd8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ name = "ANSYS, Inc." email = "pyansys.maintainers@ansys.com" [project.urls] -Homepage = "pythonnet.docs.pyansys.com" +Homepage = "https://github.com/pyansys/ansys-pythonnet" Sources = "https://github.com/pyansys/ansys-pythonnet" [tool.setuptools] From 045c345c39c00b4452078f28dad415d7bdf5ab74 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 18 Sep 2023 07:44:32 -0500 Subject: [PATCH 61/81] use enum name in repr --- src/runtime/Types/ClassObject.cs | 21 +++++++++++++++++++++ tests/test_enum.py | 5 +---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index f0585ffa..72bc30c9 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -99,6 +99,27 @@ private static string GetEnumReprString(Enum inst) return ClassBase.tp_repr(ob); } + /// + /// ClassObject __repr__ implementation. + /// + public new static NewReference tp_repr(BorrowedReference ob) + { + if (GetManagedObject(ob) is not CLRObject co) + { + return Exceptions.RaiseTypeError("invalid object"); + } + + var inst = co.inst; + var obType = inst.GetType(); + if (obType.IsEnum) + { + var repr = string.Format("{0}.{1}", obType.Name, inst.ToString()); + return Runtime.PyString_FromString(repr); + } + + return ClassBase.tp_repr(ob); + } + /// /// Implements __new__ for reflected classes and value types. /// diff --git a/tests/test_enum.py b/tests/test_enum.py index 3d3edba1..b7af47c8 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -147,10 +147,7 @@ def test_enum_repr(): """Test enumeration repr.""" from System import DayOfWeek - assert repr(DayOfWeek.Monday) == "" - - assert repr(Test.FlagsEnum(7)) == "" - assert repr(Test.FlagsEnum(8)) == "" + assert repr(DayOfWeek.Monday) == "Monday" def test_enum_conversion(): From 34df996d4f89501bc24fb5da51456fb924fed827 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 18 Sep 2023 07:57:59 -0500 Subject: [PATCH 62/81] update test --- tests/test_enum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_enum.py b/tests/test_enum.py index b7af47c8..dc6399ac 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -147,7 +147,7 @@ def test_enum_repr(): """Test enumeration repr.""" from System import DayOfWeek - assert repr(DayOfWeek.Monday) == "Monday" + assert repr(DayOfWeek.Monday) == "DayOfWeek.Monday" def test_enum_conversion(): From 7bf64389daa5d37d93debfc741b783960922bc3b Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 18 Sep 2023 10:12:26 -0500 Subject: [PATCH 63/81] no-mac-ci --- .github/workflows/ci_cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 1208465b..fea98eee 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -47,7 +47,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows, ubuntu, macos] + os: [windows, ubuntu] python: ["3.7", "3.8", "3.9", "3.10", "3.11"] platform: [x64, x86] exclude: From d7b0830736fbdd96c40e89c763e41c3cb4a6cfb1 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 19 Sep 2023 09:35:21 -0500 Subject: [PATCH 64/81] Use python convention --- src/runtime/Types/ClassObject.cs | 28 ++++++++++++++++++++++------ tests/test_enum.py | 5 ++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index 72bc30c9..c3331bfb 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -99,6 +99,26 @@ private static string GetEnumReprString(Enum inst) return ClassBase.tp_repr(ob); } + /// + /// given an enum, write a __repr__ string formatted in the same + /// way as a python repr string. Something like: + /// '<Color.GREEN: 2>'; + /// with a binary value for [Flags] enums + /// + /// Instace of the enum object + /// + private static string getEnumReprString(object inst) + { + var obType = inst.GetType(); + + var isFlags = obType.IsFlagsEnum(); + var intValue = Convert.ToInt32(inst); + var intStr = isFlags ? "0x" + intValue.ToString("X4") : intValue.ToString(); + + var repr = $"<{obType.Name}.{inst}: {intStr}>"; + return repr; + } + /// /// ClassObject __repr__ implementation. /// @@ -108,13 +128,9 @@ private static string GetEnumReprString(Enum inst) { return Exceptions.RaiseTypeError("invalid object"); } - - var inst = co.inst; - var obType = inst.GetType(); - if (obType.IsEnum) + if (co.inst.GetType().IsEnum) { - var repr = string.Format("{0}.{1}", obType.Name, inst.ToString()); - return Runtime.PyString_FromString(repr); + return Runtime.PyString_FromString(getEnumReprString(co.inst)); } return ClassBase.tp_repr(ob); diff --git a/tests/test_enum.py b/tests/test_enum.py index dc6399ac..acd6f6b7 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -147,7 +147,10 @@ def test_enum_repr(): """Test enumeration repr.""" from System import DayOfWeek - assert repr(DayOfWeek.Monday) == "DayOfWeek.Monday" + assert repr(DayOfWeek.Monday) == "" + + flags_value = Test.FlagsEnum.One | Test.FlagsEnum.Two + assert repr(flags_value) == "" def test_enum_conversion(): From e3fed7c8a9093398a8f342ea2be7612d3b79ded2 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 19 Sep 2023 09:57:11 -0500 Subject: [PATCH 65/81] fix test --- tests/test_enum.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_enum.py b/tests/test_enum.py index acd6f6b7..0873ab59 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -149,8 +149,8 @@ def test_enum_repr(): assert repr(DayOfWeek.Monday) == "" - flags_value = Test.FlagsEnum.One | Test.FlagsEnum.Two - assert repr(flags_value) == "" + assert repr(Test.FlagsEnum(7)) == "" + assert repr(Test.FlagsEnum(8)) == "" def test_enum_conversion(): From ceaa141592c3b2d10c1072f8a0263bace7e7ac14 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Thu, 21 Sep 2023 10:40:46 -0500 Subject: [PATCH 66/81] respect base enum type --- src/runtime/Types/ClassObject.cs | 45 +++++++++++++++++++++++++++++--- tests/test_enum.py | 2 +- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index c3331bfb..7ab40a22 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -111,11 +111,50 @@ private static string getEnumReprString(object inst) { var obType = inst.GetType(); + var integralType = obType.GetEnumUnderlyingType(); var isFlags = obType.IsFlagsEnum(); - var intValue = Convert.ToInt32(inst); - var intStr = isFlags ? "0x" + intValue.ToString("X4") : intValue.ToString(); - var repr = $"<{obType.Name}.{inst}: {intStr}>"; + string strValue = ""; + switch (Type.GetTypeCode(integralType)) + { + case TypeCode.SByte: + var valueSB = Convert.ToSByte(inst); + strValue = isFlags ? "0x" + valueSB.ToString("X2") : valueSB.ToString(); + break; + case TypeCode.Byte: + var valueB = Convert.ToByte(inst); + strValue = isFlags ? "0x" + valueB.ToString("X2") : valueB.ToString(); + break; + case TypeCode.Int16: + var valueI16 = Convert.ToInt16(inst); + strValue = isFlags ? "0x" + valueI16.ToString("X4") : valueI16.ToString(); + break; + case TypeCode.UInt16: + var valueUI16 = Convert.ToUInt16(inst); + strValue = isFlags ? "0x" + valueUI16.ToString("X4") : valueUI16.ToString(); + break; + case TypeCode.Int32: + var valueI32 = Convert.ToInt32(inst); + strValue = isFlags ? "0x" + valueI32.ToString("X8") : valueI32.ToString(); + break; + case TypeCode.UInt32: + var valueUI32 = Convert.ToUInt32(inst); + strValue = isFlags ? "0x" + valueUI32.ToString("X8") : valueUI32.ToString(); + break; + case TypeCode.Int64: + var valueI64 = Convert.ToInt64(inst); + strValue = isFlags ? "0x" + valueI64.ToString("X16") : valueI64.ToString(); + break; + case TypeCode.UInt64: + var valueUI64 = Convert.ToUInt64(inst); + strValue = isFlags ? "0x" + valueUI64.ToString("X16") : valueUI64.ToString(); + break; + default: + break; + } + + + var repr = $"<{obType.Name}.{inst}: {strValue}>"; return repr; } diff --git a/tests/test_enum.py b/tests/test_enum.py index 0873ab59..9d856508 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -150,7 +150,7 @@ def test_enum_repr(): assert repr(DayOfWeek.Monday) == "" assert repr(Test.FlagsEnum(7)) == "" - assert repr(Test.FlagsEnum(8)) == "" + assert repr(Test.FlagsEnum(8)) == "" def test_enum_conversion(): From 2051529497b1474c5b7c7fc8c773ad2b6750aa22 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Thu, 21 Sep 2023 10:57:59 -0500 Subject: [PATCH 67/81] fix other assert --- tests/test_enum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_enum.py b/tests/test_enum.py index 9d856508..3d3edba1 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -149,7 +149,7 @@ def test_enum_repr(): assert repr(DayOfWeek.Monday) == "" - assert repr(Test.FlagsEnum(7)) == "" + assert repr(Test.FlagsEnum(7)) == "" assert repr(Test.FlagsEnum(8)) == "" From 104e4425eb6de96c1dd112299cec60779f096f1b Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Fri, 22 Sep 2023 09:02:40 -0500 Subject: [PATCH 68/81] refactor --- src/runtime/Types/ClassObject.cs | 76 -------------------------------- 1 file changed, 76 deletions(-) diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index 7ab40a22..f0585ffa 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -99,82 +99,6 @@ private static string GetEnumReprString(Enum inst) return ClassBase.tp_repr(ob); } - /// - /// given an enum, write a __repr__ string formatted in the same - /// way as a python repr string. Something like: - /// '<Color.GREEN: 2>'; - /// with a binary value for [Flags] enums - /// - /// Instace of the enum object - /// - private static string getEnumReprString(object inst) - { - var obType = inst.GetType(); - - var integralType = obType.GetEnumUnderlyingType(); - var isFlags = obType.IsFlagsEnum(); - - string strValue = ""; - switch (Type.GetTypeCode(integralType)) - { - case TypeCode.SByte: - var valueSB = Convert.ToSByte(inst); - strValue = isFlags ? "0x" + valueSB.ToString("X2") : valueSB.ToString(); - break; - case TypeCode.Byte: - var valueB = Convert.ToByte(inst); - strValue = isFlags ? "0x" + valueB.ToString("X2") : valueB.ToString(); - break; - case TypeCode.Int16: - var valueI16 = Convert.ToInt16(inst); - strValue = isFlags ? "0x" + valueI16.ToString("X4") : valueI16.ToString(); - break; - case TypeCode.UInt16: - var valueUI16 = Convert.ToUInt16(inst); - strValue = isFlags ? "0x" + valueUI16.ToString("X4") : valueUI16.ToString(); - break; - case TypeCode.Int32: - var valueI32 = Convert.ToInt32(inst); - strValue = isFlags ? "0x" + valueI32.ToString("X8") : valueI32.ToString(); - break; - case TypeCode.UInt32: - var valueUI32 = Convert.ToUInt32(inst); - strValue = isFlags ? "0x" + valueUI32.ToString("X8") : valueUI32.ToString(); - break; - case TypeCode.Int64: - var valueI64 = Convert.ToInt64(inst); - strValue = isFlags ? "0x" + valueI64.ToString("X16") : valueI64.ToString(); - break; - case TypeCode.UInt64: - var valueUI64 = Convert.ToUInt64(inst); - strValue = isFlags ? "0x" + valueUI64.ToString("X16") : valueUI64.ToString(); - break; - default: - break; - } - - - var repr = $"<{obType.Name}.{inst}: {strValue}>"; - return repr; - } - - /// - /// ClassObject __repr__ implementation. - /// - public new static NewReference tp_repr(BorrowedReference ob) - { - if (GetManagedObject(ob) is not CLRObject co) - { - return Exceptions.RaiseTypeError("invalid object"); - } - if (co.inst.GetType().IsEnum) - { - return Runtime.PyString_FromString(getEnumReprString(co.inst)); - } - - return ClassBase.tp_repr(ob); - } - /// /// Implements __new__ for reflected classes and value types. /// From dfb3c393fda0996d5000fa7cf5552b9f6345e989 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Date: Wed, 27 Sep 2023 09:34:21 +0200 Subject: [PATCH 69/81] fix: ci actions --- .github/workflows/ci_cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index fea98eee..5004d2cd 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -142,7 +142,7 @@ jobs: runs-on: ubuntu-latest needs: [doc-build, tests] steps: - - uses: pyansys/actions/build-library@v2 + - uses: ansys/actions/build-library@v4 with: library-name: ${{ env.LIBRARY_NAME }} @@ -154,14 +154,14 @@ jobs: steps: - name: "Release to the private PyPI repository" - uses: pyansys/actions/release-pypi-private@v2 + uses: ansys/actions/release-pypi-private@v4 with: library-name: ${{ env.LIBRARY_NAME }} twine-username: "__token__" twine-token: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} - name: "Release to the public PyPI repository" - uses: pyansys/actions/release-pypi-public@v2 + uses: ansys/actions/release-pypi-public@v4 with: library-name: ${{ env.LIBRARY_NAME }} twine-username: "__token__" From 218b813301186ef7e6bd42a55b98e401c1e86b64 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Date: Wed, 27 Sep 2023 09:35:29 +0200 Subject: [PATCH 70/81] maint: add dependabot.yml file --- .github/dependabot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..5ead19fe --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + commit-message: + prefix: "maint" + groups: + actions: + patterns: + - "*" From 295154e215975938f21bf85bef2180ec9020ec8b Mon Sep 17 00:00:00 2001 From: Jorge Martinez Date: Wed, 27 Sep 2023 09:55:17 +0200 Subject: [PATCH 71/81] fix: use custom actions --- .github/workflows/ci_cd.yml | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 5004d2cd..f31d18a5 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -11,6 +11,7 @@ on: env: LIBRARY_NAME: 'ansys-pythonnet' + MAIN_PYTHON_VERSION: '3.11' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -153,16 +154,29 @@ jobs: if: github.event_name == 'push' && contains(github.ref, 'refs/tags') steps: - - name: "Release to the private PyPI repository" - uses: ansys/actions/release-pypi-private@v4 + - name: "Checkout project" + uses: actions/checkout@v4 + + - name: "Install Python ${{ env.MAIN_PYTHON_VERSION }}" + uses: actions/setup-python@v4 with: - library-name: ${{ env.LIBRARY_NAME }} - twine-username: "__token__" - twine-token: ${{ secrets.PYANSYS_PYPI_PRIVATE_PAT }} + python-version: ${{ env.MAIN_PYTHON_VERSION }} - - name: "Release to the public PyPI repository" - uses: ansys/actions/release-pypi-public@v4 + - name: "Install Python requirements" + run: | + python -m pip install twine + + - name: "Download the library artifacts from build-library step" + uses: actions/download-artifact@v3 with: - library-name: ${{ env.LIBRARY_NAME }} - twine-username: "__token__" - twine-token: ${{ secrets.PYPI_TOKEN }} + name: ${{ env.LIBRARY_NAME }}-artifacts + path: ${{ env.LIBRARY_NAME }}-artifacts + + - name: "Release to the public PyPI repository" + run: | + python -m twine upload --verbose --skip-existing ${{ env.LIBRARY_NAME }}-artifacts/*.whl + python -m twine upload --verbose --skip-existing ${{ env.LIBRARY_NAME }}-artifacts/*.tar.gz + env: + TWINE_USERNAME: '__token__' + TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} + TWINE_REPOSITORY_URL: 'https://upload.pypi.org/legacy/' From 9ad52a28a3bf65f94f99c38c045d5f7ab851f778 Mon Sep 17 00:00:00 2001 From: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com> Date: Tue, 14 Nov 2023 22:48:50 +0100 Subject: [PATCH 72/81] Delete .github/dependabot.yml --- .github/dependabot.yml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 5ead19fe..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "daily" - commit-message: - prefix: "maint" - groups: - actions: - patterns: - - "*" From 116d118e7f7734ab19243fbf5473a0b90b9c4d61 Mon Sep 17 00:00:00 2001 From: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com> Date: Wed, 9 Oct 2024 15:33:07 +0200 Subject: [PATCH 73/81] fix: cicd issues --- .github/workflows/ci_cd.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index f31d18a5..c79b9d4a 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -49,13 +49,26 @@ jobs: fail-fast: false matrix: os: [windows, ubuntu] - python: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] platform: [x64, x86] exclude: - os: ubuntu platform: x86 - os: macos platform: x86 + instance: windows-latest + + - category: windows + platform: x64 + instance: windows-latest + + - category: ubuntu + platform: x64 + instance: ubuntu-latest + + - category: macos + platform: x64 + instance: macos-13 steps: - name: Set Environment on macOS From 467144d39a34ee5f658e77da9a010ec7bde74be1 Mon Sep 17 00:00:00 2001 From: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com> Date: Wed, 9 Oct 2024 15:36:47 +0200 Subject: [PATCH 74/81] fix: use proper branch --- .github/workflows/ARM.yml | 2 +- .github/workflows/ci_cd.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ARM.yml b/.github/workflows/ARM.yml index 6c3432f8..1e2a4a0f 100644 --- a/.github/workflows/ARM.yml +++ b/.github/workflows/ARM.yml @@ -5,7 +5,7 @@ on: tags: - "*" branches: - - master + - main pull_request: jobs: diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index c79b9d4a..928bcd55 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -5,7 +5,7 @@ on: tags: - "*" branches: - - master + - main pull_request: From c2a9dbb32fe02f06b28ba3068d73afe5e4f76d30 Mon Sep 17 00:00:00 2001 From: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com> Date: Wed, 9 Oct 2024 15:38:19 +0200 Subject: [PATCH 75/81] fix: cicd --- .github/workflows/ci_cd.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 928bcd55..a4965c2e 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -48,13 +48,8 @@ jobs: strategy: fail-fast: false matrix: - os: [windows, ubuntu] - python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] - platform: [x64, x86] - exclude: - - os: ubuntu - platform: x86 - - os: macos + os: + - category: windows platform: x86 instance: windows-latest @@ -70,6 +65,8 @@ jobs: platform: x64 instance: macos-13 + python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + steps: - name: Set Environment on macOS uses: maxim-lobanov/setup-xamarin@v1 From f3685543be92b5bbae11de99f27cb963935268eb Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Wed, 23 Oct 2024 09:54:05 -0500 Subject: [PATCH 76/81] add runsettings to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cc7e4a65..3b988c9e 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ coverage.xml *.vcxproj.filters *.userprefs *.DotSettings.user +.runsettings # Build results [Bb]in/ From 76c74e890cf52e228ff8992fe32a7d335b5d61cc Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Wed, 23 Oct 2024 09:55:00 -0500 Subject: [PATCH 77/81] Add optional argument to wrap interface in ToPython This is used by ToPythonAs in this fork. In the upstream pythonnet, it is effectively always true --- src/runtime/Converter.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/runtime/Converter.cs b/src/runtime/Converter.cs index 5971ff6a..6b939c62 100644 --- a/src/runtime/Converter.cs +++ b/src/runtime/Converter.cs @@ -117,7 +117,9 @@ private static Func GetIsTransparentProxy() internal static NewReference ToPythonDetectType(object? value) => value is null ? new NewReference(Runtime.PyNone) : ToPython(value, value.GetType()); - internal static NewReference ToPython(object? value, Type type) + + + internal static NewReference ToPython(object? value, Type type, bool wrapInterface = false) { if (value is PyObject pyObj) { @@ -144,6 +146,12 @@ internal static NewReference ToPython(object? value, Type type) return CLRObject.GetReference(value, type); } + if (wrapInterface && type.IsInterface) + { + var ifaceObj = (InterfaceObject)ClassManager.GetClassImpl(type); + return ifaceObj.TryWrapObject(value); + } + // it the type is a python subclass of a managed type then return the // underlying python object rather than construct a new wrapper object. if (value is IPythonDerivedType pyderived) @@ -979,7 +987,7 @@ public static PyObject ToPython(this object? o) public static PyObject ToPythonAs(this T? o) { if (o is null) return Runtime.None; - return Converter.ToPython(o, typeof(T)).MoveToPyObject(); + return Converter.ToPython(o, typeof(T), true).MoveToPyObject(); } } } From b4a8830bfd920879ba7a0759c3d931e16135e517 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Wed, 23 Oct 2024 09:58:48 -0500 Subject: [PATCH 78/81] update readme --- README.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 3ddd5a23..3ef56351 100644 --- a/README.rst +++ b/README.rst @@ -3,5 +3,7 @@ Ansys fork of `pythonnet `_. We will try to keep this up-to-date with pythonnet and upstream changes that might benefit the pythonnet community Changes relative to pythonnet: -- Revert of `#1240 `_. -- Enum REPR `#2239 `_ is included in this release of version 3.0.2, but is unreleased in pythonnet + +* Revert of `#1240 `_. +* Enum REPR `#2239 `_ is included in this release of version 3.0.2, but is unreleased in pythonnet +* Opt-into explicit interface wrapping, `#19 `. This opts into the behavior that became the default in #1240 if ToPythonAs is explicitly used From 41123d9964307d0c57c4010e0b1b16519ecaf782 Mon Sep 17 00:00:00 2001 From: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:26:43 +0200 Subject: [PATCH 79/81] ci: delete ARM workflow (not needed) --- .github/workflows/ARM.yml | 58 --------------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 .github/workflows/ARM.yml diff --git a/.github/workflows/ARM.yml b/.github/workflows/ARM.yml deleted file mode 100644 index 1e2a4a0f..00000000 --- a/.github/workflows/ARM.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Main (ARM) - -on: - push: - tags: - - "*" - branches: - - main - pull_request: - -jobs: - build-test-arm: - name: Build and Test ARM64 - runs-on: [self-hosted, linux, ARM64] - timeout-minutes: 15 - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' - - - name: Clean previous install - run: | - pip uninstall -y pythonnet - - - name: Install dependencies - run: | - pip3.8 install -r requirements.txt - pip3.8 install pytest numpy # for tests - - - name: Build and Install - run: | - pip3.8 install -v . - - - name: Set Python DLL path (non Windows) - run: | - echo PYTHONNET_PYDLL=$(python3.8 -m find_libpython) >> $GITHUB_ENV - - - name: Embedding tests - run: dotnet test --logger "console;verbosity=detailed" src/embed_tests/ - - - name: Python Tests (Mono) - run: python3.8 -m pytest --runtime mono - - - name: Python Tests (.NET Core) - run: python3.8 -m pytest --runtime coreclr - - - name: Python tests run from .NET - run: dotnet test src/python_tests_runner/ - - #- name: Perf tests - # run: | - # pip install --force --no-deps --target src/perf_tests/baseline/ pythonnet==2.5.2 - # dotnet test --configuration Release --logger "console;verbosity=detailed" src/perf_tests/ From 454a31da0400c5d226d82ae15ecaf40b41c9431c Mon Sep 17 00:00:00 2001 From: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:04:41 +0100 Subject: [PATCH 80/81] ci: align ci_cd with remote main --- .github/workflows/ci_cd.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index acfb0f33..4f6fa9a7 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -59,13 +59,19 @@ jobs: - category: ubuntu platform: x64 - instance: ubuntu-latest + instance: ubuntu-22.04 - category: macos platform: x64 instance: macos-13 - python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + python: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + + # This fails in pytest with: + # CSC : error CS4023: /platform:anycpu32bitpreferred can only be used with /t:exe, /t:winexe and /t:appcontainerexe [D:\a\pythonnet\pythonnet\src\runtime\Python.Runtime.csproj] + exclude: + - os: { category: windows, platform: x86 } + python: ["3.13"] steps: - name: Set Environment on macOS @@ -110,6 +116,7 @@ jobs: Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append -InputObject "PYTHONHOME=$(python -c 'import sys; print(sys.prefix)')" - name: Embedding tests + if: ${{ matrix.python != '3.13' }} run: dotnet test --runtime any-${{ matrix.os.platform }} --logger "console;verbosity=detailed" src/embed_tests/ env: MONO_THREADS_SUSPEND: preemptive # https://github.com/mono/mono/issues/21466 @@ -128,6 +135,7 @@ jobs: run: pytest --runtime netfx - name: Python tests run from .NET + if: ${{ matrix.python != '3.13' }} run: dotnet test --runtime any-${{ matrix.os.platform }} src/python_tests_runner/ - name: Perf tests From 3b78bf16d787926776e3a9b5a4011464ec657463 Mon Sep 17 00:00:00 2001 From: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:14:19 +0100 Subject: [PATCH 81/81] feat: rewrite exclude --- .github/workflows/ci_cd.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 4f6fa9a7..a771b35b 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -70,8 +70,10 @@ jobs: # This fails in pytest with: # CSC : error CS4023: /platform:anycpu32bitpreferred can only be used with /t:exe, /t:winexe and /t:appcontainerexe [D:\a\pythonnet\pythonnet\src\runtime\Python.Runtime.csproj] exclude: - - os: { category: windows, platform: x86 } - python: ["3.13"] + - os: + category: windows + platform: x86 + python: "3.13" steps: - name: Set Environment on macOS