From eca999b8fdec417febceb3450bafd018d3b82237 Mon Sep 17 00:00:00 2001 From: Pavel Koneski Date: Wed, 28 Jan 2026 16:14:58 -0800 Subject: [PATCH 1/3] Upgrade to target net10.0 --- .editorconfig | 1 + IronPython.sln | 2 + README.md | 2 +- eng/net10.0-windows.props | 9 +++++ eng/net10.0.props | 38 +++++++++++++++++++ eng/package/nuget/IronPython.nuspec | 4 ++ make.ps1 | 2 +- .../IronPython.Modules.csproj | 4 +- src/core/IronPython.Modules/_ssl.cs | 31 +++++++++++++-- src/core/IronPython.Modules/fcntl.cs | 4 +- src/core/IronPython/IronPython.csproj | 6 +-- src/core/IronPython/Runtime/Importer.cs | 4 +- .../IronPython.Console.csproj | 4 +- .../IronPython.Console32.csproj | 4 +- .../IronPython.SQLite.csproj | 4 +- .../IronPython.Wpf/IronPython.Wpf.csproj | 4 +- tests/IronPython.Tests/AttrInjectorTest.cs | 3 +- .../IronPython.Tests/IronPython.Tests.csproj | 4 +- 18 files changed, 103 insertions(+), 27 deletions(-) create mode 100644 eng/net10.0-windows.props create mode 100644 eng/net10.0.props diff --git a/.editorconfig b/.editorconfig index f7658ff73..4a7fd19de 100644 --- a/.editorconfig +++ b/.editorconfig @@ -95,6 +95,7 @@ dotnet_diagnostic.CA2211.severity = none # CA2211: Non-constant fields sh dotnet_diagnostic.CA2219.severity = suggestion # CA2219: Do not raise exceptions in finally clauses dotnet_diagnostic.CA2229.severity = suggestion # CA2229: Implement serialization constructors dotnet_diagnostic.CA2249.severity = suggestion # CA2249: Consider using 'string.Contains' instead of 'string.IndexOf' +dotnet_diagnostic.CA2263.severity = none # CA2263: Prefer generic overload when type is known dotnet_diagnostic.CA3075.severity = suggestion # CA3075: Insecure DTD processing in XML dotnet_diagnostic.CA5350.severity = suggestion # CA5350: Do Not Use Weak Cryptographic Algorithms dotnet_diagnostic.CA5351.severity = suggestion # CA5351: Do Not Use Broken Cryptographic Algorithms diff --git a/IronPython.sln b/IronPython.sln index 2a77b6b94..d4427d78c 100644 --- a/IronPython.sln +++ b/IronPython.sln @@ -41,6 +41,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{17737ACB eng\net8.0.props = eng\net8.0.props eng\net9.0-windows.props = eng\net9.0-windows.props eng\net9.0.props = eng\net9.0.props + eng\net10.0-windows.props = eng\net10.0-windows.props + eng\net10.0.props = eng\net10.0.props eng\netstandard2.0.props = eng\netstandard2.0.props eng\Tasks.Targets = eng\Tasks.Targets EndProjectSection diff --git a/README.md b/README.md index 44353a451..62f95d27d 100644 --- a/README.md +++ b/README.md @@ -152,4 +152,4 @@ See the [building document](https://github.com/IronLanguages/ironpython3/wiki/Bu ## Supported Platforms -IronPython 3 targets .NET Framework 4.6.2, .NET Standard 2.0, .NET 6.0 and .NET 8.0. The support for .NET and .NET Core follow the lifecycle defined on [.NET and .NET Core Support Policy](https://dotnet.microsoft.com/platform/support/policy/dotnet-core). +IronPython 3 targets .NET Framework 4.6.2, .NET Standard 2.0, .NET 6.0, .NET 8.0, and .NET 10.0. The support for .NET and .NET Core follow the lifecycle defined on [.NET and .NET Core Support Policy](https://dotnet.microsoft.com/platform/support/policy/dotnet-core). diff --git a/eng/net10.0-windows.props b/eng/net10.0-windows.props new file mode 100644 index 000000000..821e22cdc --- /dev/null +++ b/eng/net10.0-windows.props @@ -0,0 +1,9 @@ + + + false + $(BaseIntermediateOutputPath)$(Configuration)\net10.0 + $(BaseOutputPath)\net10.0 + + + + diff --git a/eng/net10.0.props b/eng/net10.0.props new file mode 100644 index 000000000..926dadc14 --- /dev/null +++ b/eng/net10.0.props @@ -0,0 +1,38 @@ + + + + false + + + + $(Features);FEATURE_APARTMENTSTATE + $(Features);FEATURE_ASSEMBLY_GETFORWARDEDTYPES + $(Features);FEATURE_ASSEMBLY_RESOLVE + $(Features);FEATURE_ASSEMBLYBUILDER_DEFINEDYNAMICASSEMBLY + $(Features);FEATURE_CODEDOM + $(Features);FEATURE_COM + $(Features);FEATURE_CONFIGURATION + $(Features);FEATURE_CTYPES + $(Features);FEATURE_CUSTOM_TYPE_DESCRIPTOR + $(Features);FEATURE_EXCEPTION_STATE + $(Features);FEATURE_FILESYSTEM + $(Features);FEATURE_FULL_CRYPTO + $(Features);FEATURE_FULL_NET + $(Features);FEATURE_LCG + $(Features);FEATURE_LOADWITHPARTIALNAME + $(Features);FEATURE_METADATA_READER + $(Features);FEATURE_MMAP + $(Features);FEATURE_NATIVE + $(Features);FEATURE_OSPLATFORMATTRIBUTE + $(Features);FEATURE_PIPES + $(Features);FEATURE_PROCESS + $(Features);FEATURE_REFEMIT + $(Features);FEATURE_REGISTRY + $(Features);FEATURE_RUNTIMEINFORMATION + $(Features);FEATURE_SECURITY_RULES + $(Features);FEATURE_STACK_TRACE + $(Features);FEATURE_SYNC_SOCKETS + $(Features);FEATURE_THREAD + $(Features);FEATURE_XMLDOC + + diff --git a/eng/package/nuget/IronPython.nuspec b/eng/package/nuget/IronPython.nuspec index 1c3b0e0cd..5aaf7f951 100644 --- a/eng/package/nuget/IronPython.nuspec +++ b/eng/package/nuget/IronPython.nuspec @@ -33,6 +33,10 @@ This package contains the IronPython interpreter engine. + + + + diff --git a/make.ps1 b/make.ps1 index 16c41b673..bcf210273 100755 --- a/make.ps1 +++ b/make.ps1 @@ -4,7 +4,7 @@ Param( [Parameter(Position=1)] [String] $target = "build", [String] $configuration = "Release", - [String[]] $frameworks=@('net462','net6.0','net8.0'), + [String[]] $frameworks=@('net462','net6.0','net8.0','net10.0'), [String] $platform = $null, # auto-detect [switch] $runIgnored, [int] $jobs = [System.Environment]::ProcessorCount diff --git a/src/core/IronPython.Modules/IronPython.Modules.csproj b/src/core/IronPython.Modules/IronPython.Modules.csproj index 1f6f3c1a8..ca88b2b9f 100644 --- a/src/core/IronPython.Modules/IronPython.Modules.csproj +++ b/src/core/IronPython.Modules/IronPython.Modules.csproj @@ -1,7 +1,7 @@ - + - net462;netstandard2.0;net6.0;net8.0 + net462;netstandard2.0;net6.0;net8.0;net10.0 885063680 true true diff --git a/src/core/IronPython.Modules/_ssl.cs b/src/core/IronPython.Modules/_ssl.cs index 08ade85f6..8887134dd 100644 --- a/src/core/IronPython.Modules/_ssl.cs +++ b/src/core/IronPython.Modules/_ssl.cs @@ -252,7 +252,9 @@ public void load_verify_locations(CodeContext context, object cafile = null, str using IPythonBuffer buf = cabuf.GetBuffer(); var contents = buf.AsReadOnlySpan(); while (contents.Length > 0) { -#if NET +#if NET10_0_OR_GREATER + var cert = X509CertificateLoader.LoadCertificate(contents); +#elif NET var cert = new X509Certificate2(contents); #else var cert = new X509Certificate2(contents.ToArray()); @@ -449,7 +451,12 @@ public void do_handshake() { if (_serverSide) { var _cert = context._cert; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - _cert = new X509Certificate2(_cert.Export(X509ContentType.Pkcs12)); + byte[] certData = _cert.Export(X509ContentType.Pkcs12); +#if NET10_0_OR_GREATER + _cert = X509CertificateLoader.LoadCertificate(certData); +#else + _cert = new X509Certificate2(certData); +#endif } _sslStream.AuthenticateAsServer(_cert, _certsMode == PythonSsl.CERT_REQUIRED, enabledSslProtocols, false); } else { @@ -527,6 +534,8 @@ private static SslProtocols GetProtocolType(int protocol, int options) { #pragma warning restore CS0618 // Type or member is obsolete #pragma warning restore CA5397 // Do not use deprecated SslProtocols values +#pragma warning disable SYSLIB0058 // Certain SslStream properties are obsolete + public PythonTuple cipher() { if (_sslStream != null && _sslStream.IsAuthenticated) { return PythonTuple.MakeTuple( @@ -540,6 +549,8 @@ public PythonTuple cipher() { public object compression() => null; // TODO +#pragma warning restore SYSLIB0058 // Certain SslStream properties are obsolete + #pragma warning disable CA5397 // Do not use deprecated SslProtocols values #pragma warning disable CS0618 // Type or member is obsolete #pragma warning disable SYSLIB0039 // Type or member is obsolete @@ -876,7 +887,14 @@ public static PythonDictionary _test_decode_cert(CodeContext context, string pat private static PythonDictionary CertificateToPython(CodeContext context, X509Certificate cert) { if (cert is X509Certificate2 cert2) return CertificateToPython(context, cert2); - return CertificateToPython(context, new X509Certificate2(cert.GetRawCertData())); + + byte[] certData = cert.GetRawCertData(); +#if NET10_0_OR_GREATER + cert2 = X509CertificateLoader.LoadCertificate(certData); +#else + cert2 = new X509Certificate2(certData); +#endif + return CertificateToPython(context, cert2); } private static PythonDictionary CertificateToPython(CodeContext context, X509Certificate2 cert) { @@ -1030,7 +1048,12 @@ private static X509Certificate2 ReadCertificate(CodeContext context, string file var certStr = ReadToEnd(lines, ref i, "-----END CERTIFICATE-----"); try { - cert = new X509Certificate2(Convert.FromBase64String(certStr.ToString())); + byte[] certData = Convert.FromBase64String(certStr.ToString()); +#if NET10_0_OR_GREATER + cert = X509CertificateLoader.LoadCertificate(certData); +#else + cert = new X509Certificate2(certData); +#endif } catch (Exception e) { throw ErrorDecoding(context, filename, e); } diff --git a/src/core/IronPython.Modules/fcntl.cs b/src/core/IronPython.Modules/fcntl.cs index ed9189858..2380d13dd 100644 --- a/src/core/IronPython.Modules/fcntl.cs +++ b/src/core/IronPython.Modules/fcntl.cs @@ -117,11 +117,11 @@ public static object fcntl(CodeContext context, object? fd, int cmd, [Optional] // // int ioctl(int, unsigned long, ...) // - // but .NET, as of Jan 2025, still does not support varargs in P/Invoke [1] + // but .NET, as of Jan 2026, still does not support varargs in P/Invoke [1] // so as a workaround, nonvararg prototypes are defined for each architecture. // [1]: https://github.com/dotnet/runtime/issues/48796 -#if NET10_0_OR_GREATER +#if NET11_0_OR_GREATER #error Check if this version of .NET supports P/Invoke of variadic functions; if not, change the condition to recheck at next major .NET version #endif diff --git a/src/core/IronPython/IronPython.csproj b/src/core/IronPython/IronPython.csproj index 8f0689fa8..576fdc725 100644 --- a/src/core/IronPython/IronPython.csproj +++ b/src/core/IronPython/IronPython.csproj @@ -1,7 +1,7 @@ - + - net462;netstandard2.0;net6.0;net8.0 + net462;netstandard2.0;net6.0;net8.0;net10.0 879755264 true true @@ -30,7 +30,7 @@ - + diff --git a/src/core/IronPython/Runtime/Importer.cs b/src/core/IronPython/Runtime/Importer.cs index 2cbfa997b..6f3db9812 100644 --- a/src/core/IronPython/Runtime/Importer.cs +++ b/src/core/IronPython/Runtime/Importer.cs @@ -769,9 +769,9 @@ private static bool IsReflected(object module) { private static string CreateFullName(string/*!*/ baseName, ArraySegment parts) { if (baseName == null || baseName.Length == 0 || baseName == "__main__") { - return string.Join(".", parts); + return string.Join(".", (IEnumerable)parts); } - return baseName + "." + string.Join(".", parts); + return baseName + "." + string.Join(".", (IEnumerable)parts); } #endregion diff --git a/src/executables/IronPython.Console/IronPython.Console.csproj b/src/executables/IronPython.Console/IronPython.Console.csproj index 3c75121b2..15afa70ae 100644 --- a/src/executables/IronPython.Console/IronPython.Console.csproj +++ b/src/executables/IronPython.Console/IronPython.Console.csproj @@ -1,7 +1,7 @@ - + - net462;net6.0;net8.0 + net462;net6.0;net8.0;net10.0 Exe IronPython.Console ipy diff --git a/src/executables/IronPython.Console32/IronPython.Console32.csproj b/src/executables/IronPython.Console32/IronPython.Console32.csproj index c8b938c10..cf041671b 100644 --- a/src/executables/IronPython.Console32/IronPython.Console32.csproj +++ b/src/executables/IronPython.Console32/IronPython.Console32.csproj @@ -1,7 +1,7 @@ - + - net462 + net462;net6.0;net8.0;net10.0 x86 Exe IronPython.Console32 diff --git a/src/extensions/IronPython.SQLite/IronPython.SQLite.csproj b/src/extensions/IronPython.SQLite/IronPython.SQLite.csproj index 8354aee5c..5e6209d8b 100644 --- a/src/extensions/IronPython.SQLite/IronPython.SQLite.csproj +++ b/src/extensions/IronPython.SQLite/IronPython.SQLite.csproj @@ -1,7 +1,7 @@ - + - net462;netstandard2.0;net6.0;net8.0 + net462;netstandard2.0;net6.0;net8.0;net10.0 true SQLITE_DEBUG;TRUE;WIN32;_MSC_VER;SQLITE_ASCII;SQLITE_MEM_POOL;SQLITE_ENABLE_COLUMN_METADATA;SQLITE_OS_WIN;SQLITE_SYSTEM_MALLOC;VDBE_PROFILE_OFF SQLITE_OMIT_AUTHORIZATION;SQLITE_OMIT_DEPRECATED;SQLITE_OMIT_GET_TABLE;SQLITE_OMIT_INCRBLOB;SQLITE_OMIT_LOOKASIDE;SQLITE_OMIT_SHARED_CACHE;SQLITE_OMIT_UTF16;SQLITE_OMIT_WAL diff --git a/src/extensions/IronPython.Wpf/IronPython.Wpf.csproj b/src/extensions/IronPython.Wpf/IronPython.Wpf.csproj index 53618a818..0b810f59f 100644 --- a/src/extensions/IronPython.Wpf/IronPython.Wpf.csproj +++ b/src/extensions/IronPython.Wpf/IronPython.Wpf.csproj @@ -1,7 +1,7 @@ - + - net462;net6.0-windows;net8.0-windows + net462;net6.0-windows;net8.0-windows;net10.0-windows true true true diff --git a/tests/IronPython.Tests/AttrInjectorTest.cs b/tests/IronPython.Tests/AttrInjectorTest.cs index 421e9a7f1..7ab969f02 100644 --- a/tests/IronPython.Tests/AttrInjectorTest.cs +++ b/tests/IronPython.Tests/AttrInjectorTest.cs @@ -49,7 +49,6 @@ public static object GetBoundMember(object obj, string name) { } else { return n; } - } } } @@ -59,4 +58,4 @@ public static object GetBoundMember(object obj, string name) { } } -} \ No newline at end of file +} diff --git a/tests/IronPython.Tests/IronPython.Tests.csproj b/tests/IronPython.Tests/IronPython.Tests.csproj index 6ff811e82..f9dca9eaa 100644 --- a/tests/IronPython.Tests/IronPython.Tests.csproj +++ b/tests/IronPython.Tests/IronPython.Tests.csproj @@ -1,7 +1,7 @@ - + - net462;net6.0;net8.0 + net462;net6.0;net8.0;net10.0 IronPythonTest true From 5bef11938bd8ccfa4690b7694d8834ee749b974a Mon Sep 17 00:00:00 2001 From: Pavel Koneski Date: Fri, 6 Feb 2026 14:13:50 -0800 Subject: [PATCH 2/3] Enable CI tests for net10.0 --- .github/workflows/main.yml | 26 +++++++++++++++++--------- .vsts-ci.yml | 12 ++++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e44d936df..e43e3cf9b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,18 +21,22 @@ jobs: submodules: true # Setup .NET - - name: Setup .NET 6.0 + - name: Setup .NET 10.0 uses: actions/setup-dotnet@v4 with: - dotnet-version: '6.0.x' + dotnet-version: '10.0.x' + - name: Setup .NET 9.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '9.0.x' - name: Setup .NET 8.0 uses: actions/setup-dotnet@v4 with: dotnet-version: '8.0.x' - - name: Setup .NET 9.0 + - name: Setup .NET 6.0 uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.0.x' + dotnet-version: '6.0.x' # CI debug information - name: Version Information @@ -61,7 +65,7 @@ jobs: fail-fast: false matrix: os: [windows-latest, ubuntu-22.04, macos-14] - framework: ['net462', 'net6.0', 'net8.0'] + framework: ['net462', 'net6.0', 'net8.0', 'net10.0'] steps: # Prerequisites @@ -70,18 +74,22 @@ jobs: submodules: true # Setup .NET - - name: Setup .NET 6.0 + - name: Setup .NET 10.0 uses: actions/setup-dotnet@v4 with: - dotnet-version: '6.0.x' + dotnet-version: '10.0.x' + - name: Setup .NET 9.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '9.0.x' - name: Setup .NET 8.0 uses: actions/setup-dotnet@v4 with: dotnet-version: '8.0.x' - - name: Setup .NET 9.0 + - name: Setup .NET 6.0 uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.0.x' + dotnet-version: '6.0.x' # Build & Test - name: Build diff --git a/.vsts-ci.yml b/.vsts-ci.yml index 98ff4c5fb..14a5acb2a 100644 --- a/.vsts-ci.yml +++ b/.vsts-ci.yml @@ -120,6 +120,18 @@ jobs: osName: Windows imageName: windows-latest framework: net8.0 + linux_net10_0: + osName: Linux + imageName: ubuntu-22.04 + framework: net10.0 + macos_net10_0: + osName: macOS + imageName: macOS-14 + framework: net10.0 + windows_net10_0: + osName: Windows + imageName: windows-latest + framework: net10.0 displayName: Test timeoutInMinutes: 180 From b758013ba38d796562715b10929781f989cca0cb Mon Sep 17 00:00:00 2001 From: Pavel Koneski Date: Fri, 6 Feb 2026 14:41:26 -0800 Subject: [PATCH 3/3] Fix test_reachtype --- tests/suite/interop/net/type/test_reachtype.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suite/interop/net/type/test_reachtype.py b/tests/suite/interop/net/type/test_reachtype.py index 7abedc02b..6e020c870 100644 --- a/tests/suite/interop/net/type/test_reachtype.py +++ b/tests/suite/interop/net/type/test_reachtype.py @@ -95,7 +95,7 @@ def test_generic_types(self): self.assertEqual(G2[int, int].A, 40) self.assertRaisesRegex(ValueError, - re.compile(r"(?s)The number of generic arguments provided doesn't equal the arity of the generic type definition\..*Parameter.*instantiation", re.M), + re.compile(r"(?s)The number of generic arguments provided doesn't equal the arity of the generic type definition\..*Parameter.*", re.M), lambda: G3[()]) if is_mono: