diff --git a/.travis.yml b/.travis.yml index d728d9a2d..2062a35da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,11 @@ dist: xenial sudo: false language: python python: - - 2.7 - - 3.5 - - 3.6 + - 3.8 - 3.7 + - 3.6 + - 3.5 + - 2.7 env: matrix: diff --git a/CHANGELOG.md b/CHANGELOG.md index f3f801841..3cbf85d45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Added PythonException.Format method to format exceptions the same as traceback.format_exception - Added Runtime.None to be able to pass None as parameter into Python from .NET - Added PyObject.IsNone() to check if a Python object is None in .NET. +- Support for Python 3.8 ### Changed @@ -29,6 +30,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Added support for kwarg parameters when calling .NET methods from Python - Changed method for finding MSBuild using vswhere - Reworked `Finalizer`. Now objects drop into its queue upon finalization, which is periodically drained when new objects are created. +- Marked `Runtime.OperatingSystemName` and `Runtime.MachineName` as `Obsolete`, should never have been `public` in the first place. They also don't necessarily return a result that matches the `platform` module's. ### Fixed @@ -37,6 +39,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Fixes bug where delegates get casts (dotnetcore) - Determine size of interpreter longs at runtime - Handling exceptions ocurred in ModuleObject's getattribute +- Fill `__classcell__` correctly for Python subclasses of .NET types ## [2.4.0][] diff --git a/appveyor.yml b/appveyor.yml index 445f9bb5a..363e67389 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,24 +15,21 @@ environment: CODECOV_ENV: PYTHON_VERSION, PLATFORM matrix: - - PYTHON_VERSION: 2.7 + - PYTHON_VERSION: 3.8 BUILD_OPTS: --xplat - - PYTHON_VERSION: 3.5 + - PYTHON_VERSION: 3.7 BUILD_OPTS: --xplat - PYTHON_VERSION: 3.6 BUILD_OPTS: --xplat - - PYTHON_VERSION: 3.7 - BUILD_OPTS: --xplat - - PYTHON_VERSION: 2.7 - PYTHON_VERSION: 3.5 - - PYTHON_VERSION: 3.6 + BUILD_OPTS: --xplat + - PYTHON_VERSION: 2.7 + BUILD_OPTS: --xplat + - PYTHON_VERSION: 3.8 - PYTHON_VERSION: 3.7 - -matrix: - allow_failures: - - PYTHON_VERSION: 3.4 - BUILD_OPTS: --xplat - - PYTHON_VERSION: 3.4 + - PYTHON_VERSION: 3.6 + - PYTHON_VERSION: 3.5 + - PYTHON_VERSION: 2.7 init: # Update Environment Variables based on matrix/platform diff --git a/src/embed_tests/TestRuntime.cs b/src/embed_tests/TestRuntime.cs index 157fe4cb7..4129d3df3 100644 --- a/src/embed_tests/TestRuntime.cs +++ b/src/embed_tests/TestRuntime.cs @@ -29,10 +29,7 @@ public static void PlatformCache() Runtime.Runtime.Initialize(); Assert.That(Runtime.Runtime.Machine, Is.Not.EqualTo(MachineType.Other)); - Assert.That(!string.IsNullOrEmpty(Runtime.Runtime.MachineName)); - Assert.That(Runtime.Runtime.OperatingSystem, Is.Not.EqualTo(OperatingSystemType.Other)); - Assert.That(!string.IsNullOrEmpty(Runtime.Runtime.OperatingSystemName)); // Don't shut down the runtime: if the python engine was initialized // but not shut down by another test, we'd end up in a bad state. diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 3d2610fea..0e391a134 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1,3 +1,4 @@ +using System.Reflection.Emit; using System; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; @@ -118,16 +119,16 @@ public class Runtime { "Linux", OperatingSystemType.Linux }, }; - /// - /// Gets the operating system as reported by python's platform.system(). - /// - public static OperatingSystemType OperatingSystem { get; private set; } + [Obsolete] + public static string OperatingSystemName => OperatingSystem.ToString(); + + [Obsolete] + public static string MachineName => Machine.ToString(); /// /// Gets the operating system as reported by python's platform.system(). /// - public static string OperatingSystemName { get; private set; } - + public static OperatingSystemType OperatingSystem { get; private set; } /// /// Map lower-case version of the python machine name to the processor @@ -154,11 +155,6 @@ public class Runtime /// public static MachineType Machine { get; private set; }/* set in Initialize using python's platform.machine */ - /// - /// Gets the machine architecture as reported by python's platform.machine(). - /// - public static string MachineName { get; private set; } - internal static bool IsPython2 = pyversionnumber < 30; internal static bool IsPython3 = pyversionnumber >= 30; @@ -356,6 +352,7 @@ internal static void Initialize(bool initSigs = false) /// private static void InitializePlatformData() { +#if !NETSTANDARD IntPtr op; IntPtr fn; IntPtr platformModule = PyImport_ImportModule("platform"); @@ -363,13 +360,13 @@ private static void InitializePlatformData() fn = PyObject_GetAttrString(platformModule, "system"); op = PyObject_Call(fn, emptyTuple, IntPtr.Zero); - OperatingSystemName = GetManagedString(op); + string operatingSystemName = GetManagedString(op); XDecref(op); XDecref(fn); fn = PyObject_GetAttrString(platformModule, "machine"); op = PyObject_Call(fn, emptyTuple, IntPtr.Zero); - MachineName = GetManagedString(op); + string machineName = GetManagedString(op); XDecref(op); XDecref(fn); @@ -379,18 +376,47 @@ private static void InitializePlatformData() // Now convert the strings into enum values so we can do switch // statements rather than constant parsing. OperatingSystemType OSType; - if (!OperatingSystemTypeMapping.TryGetValue(OperatingSystemName, out OSType)) + if (!OperatingSystemTypeMapping.TryGetValue(operatingSystemName, out OSType)) { OSType = OperatingSystemType.Other; } OperatingSystem = OSType; MachineType MType; - if (!MachineTypeMapping.TryGetValue(MachineName.ToLower(), out MType)) + if (!MachineTypeMapping.TryGetValue(machineName.ToLower(), out MType)) { MType = MachineType.Other; } Machine = MType; +#else + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + OperatingSystem = OperatingSystemType.Linux; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + OperatingSystem = OperatingSystemType.Darwin; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + OperatingSystem = OperatingSystemType.Windows; + else + OperatingSystem = OperatingSystemType.Other; + + switch (RuntimeInformation.ProcessArchitecture) + { + case Architecture.X86: + Machine = MachineType.i386; + break; + case Architecture.X64: + Machine = MachineType.x86_64; + break; + case Architecture.Arm: + Machine = MachineType.armv7l; + break; + case Architecture.Arm64: + Machine = MachineType.aarch64; + break; + default: + Machine = MachineType.Other; + break; + } +#endif } internal static void Shutdown() @@ -1966,6 +1992,15 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyErr_Print(); + //==================================================================== + // Cell API + //==================================================================== + + [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern NewReference PyCell_Get(BorrowedReference cell); + + [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern int PyCell_Set(BorrowedReference cell, IntPtr value); //==================================================================== // Miscellaneous diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index bb920b74f..7d73b0138 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -280,6 +280,14 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr IntPtr cls_dict = Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict); Runtime.PyDict_Update(cls_dict, py_dict); + // Update the __classcell__ if it exists + var cell = new BorrowedReference(Runtime.PyDict_GetItemString(cls_dict, "__classcell__")); + if (!cell.IsNull) + { + Runtime.PyCell_Set(cell, py_type); + Runtime.PyDict_DelItemString(cls_dict, "__classcell__"); + } + return py_type; } catch (Exception e) @@ -617,7 +625,9 @@ int MAP_ANONYMOUS case OperatingSystemType.Linux: return 0x20; default: - throw new NotImplementedException($"mmap is not supported on {Runtime.OperatingSystemName}"); + throw new NotImplementedException( + $"mmap is not supported on {Runtime.OperatingSystem}" + ); } } } @@ -651,7 +661,9 @@ internal static IMemoryMapper CreateMemoryMapper() case OperatingSystemType.Windows: return new WindowsMemoryMapper(); default: - throw new NotImplementedException($"No support for {Runtime.OperatingSystemName}"); + throw new NotImplementedException( + $"No support for {Runtime.OperatingSystem}" + ); } }