From d50021065d9cd77b185ee5941c312b94ea9e9856 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 26 May 2026 14:35:34 +0200 Subject: [PATCH 1/4] Initial Python 3.15 support --- pyproject.toml | 3 +- src/runtime/Native/TypeOffset315.cs | 154 ++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 src/runtime/Native/TypeOffset315.cs diff --git a/pyproject.toml b/pyproject.toml index 0966038cd..6af48d32f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ dependencies = [ "clr_loader>=0.3.1,<0.4.0" ] -requires-python = ">=3.10, <3.15" +requires-python = ">=3.10, <3.16" classifiers = [ "Development Status :: 5 - Production/Stable", @@ -25,6 +25,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.15", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", "Operating System :: MacOS :: MacOS X", diff --git a/src/runtime/Native/TypeOffset315.cs b/src/runtime/Native/TypeOffset315.cs new file mode 100644 index 000000000..782d6c38c --- /dev/null +++ b/src/runtime/Native/TypeOffset315.cs @@ -0,0 +1,154 @@ + +// Auto-generated by geninterop.py. +// DO NOT MODIFY BY HAND. + +// Python 3.15: 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 TypeOffset314 : GeneratedTypeOffsets, ITypeOffsets + { + public TypeOffset314() { } + // Auto-generated from PyHeapTypeObject in Python.h + public int ob_refcnt_full { 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; } + // 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_iteritem { 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 ht_token { get; private set; } + public int spec_cache_getitem { get; private set; } + public int getitem_version { get; private set; } + public int init { get; private set; } + } +} + From 36a07c4bb31284f64a19b47646f840c18a273b99 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 26 May 2026 14:46:44 +0200 Subject: [PATCH 2/4] Initial Python 3.15 support --- src/runtime/Native/TypeOffset315.cs | 4 ++-- src/runtime/Runtime.Delegates.cs | 2 -- src/runtime/Runtime.cs | 2 -- uv.lock | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/runtime/Native/TypeOffset315.cs b/src/runtime/Native/TypeOffset315.cs index 782d6c38c..69b983c9d 100644 --- a/src/runtime/Native/TypeOffset315.cs +++ b/src/runtime/Native/TypeOffset315.cs @@ -20,9 +20,9 @@ namespace Python.Runtime Scope = "type")] [StructLayout(LayoutKind.Sequential)] - internal class TypeOffset314 : GeneratedTypeOffsets, ITypeOffsets + internal class TypeOffset315 : GeneratedTypeOffsets, ITypeOffsets { - public TypeOffset314() { } + public TypeOffset315() { } // Auto-generated from PyHeapTypeObject in Python.h public int ob_refcnt_full { get; private set; } public int ob_type { get; private set; } diff --git a/src/runtime/Runtime.Delegates.cs b/src/runtime/Runtime.Delegates.cs index dc4a4b0a9..190d3d6de 100644 --- a/src/runtime/Runtime.Delegates.cs +++ b/src/runtime/Runtime.Delegates.cs @@ -245,7 +245,6 @@ static Delegates() catch (MissingMethodException) { } PyObject_GC_Track = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GC_Track), GetUnmanagedDll(_PythonDll)); PyObject_GC_UnTrack = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GC_UnTrack), GetUnmanagedDll(_PythonDll)); - _PyObject_Dump = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(_PyObject_Dump), GetUnmanagedDll(_PythonDll)); PyMem_Malloc = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMem_Malloc), GetUnmanagedDll(_PythonDll)); PyMem_Realloc = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMem_Realloc), GetUnmanagedDll(_PythonDll)); PyMem_Free = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMem_Free), GetUnmanagedDll(_PythonDll)); @@ -513,7 +512,6 @@ static Delegates() internal static delegate* unmanaged[Cdecl] PyObject_GC_IsTracked { get; } internal static delegate* unmanaged[Cdecl] PyObject_GC_Track { get; } internal static delegate* unmanaged[Cdecl] PyObject_GC_UnTrack { get; } - internal static delegate* unmanaged[Cdecl] _PyObject_Dump { get; } internal static delegate* unmanaged[Cdecl] PyMem_Malloc { get; } internal static delegate* unmanaged[Cdecl] PyMem_Realloc { get; } internal static delegate* unmanaged[Cdecl] PyMem_Free { get; } diff --git a/src/runtime/Runtime.cs b/src/runtime/Runtime.cs index 399608733..8e8c02255 100644 --- a/src/runtime/Runtime.cs +++ b/src/runtime/Runtime.cs @@ -1653,8 +1653,6 @@ internal static bool PyObject_GC_IsTracked(BorrowedReference ob) internal static void PyObject_GC_UnTrack(BorrowedReference ob) => Delegates.PyObject_GC_UnTrack(ob); - internal static void _PyObject_Dump(BorrowedReference ob) => Delegates._PyObject_Dump(ob); - //==================================================================== // Python memory API //==================================================================== diff --git a/uv.lock b/uv.lock index f007f9151..dc8660941 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,6 @@ version = 1 revision = 3 -requires-python = ">=3.10, <3.15" +requires-python = ">=3.10, <3.16" resolution-markers = [ "python_full_version >= '3.12'", "python_full_version == '3.11.*'", From f45978de92b7c0c5ba94dbe14e13c0704469d8ca Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 26 May 2026 14:50:25 +0200 Subject: [PATCH 3/4] Drop 3.10 support and add to CI --- .github/workflows/main.yml | 14 +-- pyproject.toml | 5 +- src/runtime/Native/TypeOffset310.cs | 140 ---------------------------- 3 files changed, 3 insertions(+), 156 deletions(-) delete mode 100644 src/runtime/Native/TypeOffset310.cs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7b1bee82c..e6fdb989d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -46,21 +46,9 @@ jobs: instance: macos-15 suffix: -macos-aarch64-none - python: ["3.10", "3.11", "3.12", "3.13", "3.14"] + python: ["3.11", "3.12", "3.13", "3.14", "3.15"] exclude: - # Fails with initfs_encoding error - - os: - category: windows - platform: x86 - python: "3.10" - - # Fails to find pytest - - os: - category: windows - platform: x64 - python: '3.10' - # fails to call mono methods - os: category: windows diff --git a/pyproject.toml b/pyproject.toml index 6af48d32f..db1fb1eb6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ dependencies = [ "clr_loader>=0.3.1,<0.4.0" ] -requires-python = ">=3.10, <3.16" +requires-python = ">=3.11, <3.16" classifiers = [ "Development Status :: 5 - Production/Stable", @@ -37,8 +37,7 @@ dynamic = ["version"] dev = [ "pytest >= 6", "find_libpython >= 0.3", - "numpy >=2 ; python_version >= '3.10'", - "numpy <2 ; python_version < '3.10'", + "numpy >=2", ] doc = [ "sphinx", diff --git a/src/runtime/Native/TypeOffset310.cs b/src/runtime/Native/TypeOffset310.cs deleted file mode 100644 index fc0ca1e8c..000000000 --- a/src/runtime/Native/TypeOffset310.cs +++ /dev/null @@ -1,140 +0,0 @@ - -// Auto-generated by geninterop.py. -// DO NOT MODIFY BY HAND. - -// Python 3.10: 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 TypeOffset310 : GeneratedTypeOffsets, ITypeOffsets - { - public TypeOffset310() { } - // 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 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; } - } -} - From c10c1b0861766c65f70134a29d3b01832b612ce1 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 26 May 2026 16:05:07 +0200 Subject: [PATCH 4/4] Adjust version ranges --- src/runtime/PythonEngine.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/PythonEngine.cs b/src/runtime/PythonEngine.cs index 264835fff..12413d7cb 100644 --- a/src/runtime/PythonEngine.cs +++ b/src/runtime/PythonEngine.cs @@ -134,8 +134,8 @@ public static string PythonPath } } - public static Version MinSupportedVersion => new(3, 7); - public static Version MaxSupportedVersion => new(3, 14, int.MaxValue, int.MaxValue); + public static Version MinSupportedVersion => new(3, 10); + public static Version MaxSupportedVersion => new(3, 15, int.MaxValue, int.MaxValue); public static bool IsSupportedVersion(Version version) => version >= MinSupportedVersion && version <= MaxSupportedVersion; public static string Version