Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pythonnet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def load(runtime: Union[clr_loader.Runtime, str, None] = None, **params: str) ->


def unload() -> None:
"""Explicitly unload a laoded runtime and shut down Python.NET"""
"""Explicitly unload a loaded runtime and shut down Python.NET"""

global _RUNTIME, _LOADER_ASSEMBLY
if _LOADER_ASSEMBLY is not None:
Expand Down
9 changes: 6 additions & 3 deletions src/embed_tests/TestConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public void PyIntImplicit()
{
var i = new PyInt(1);
var ni = (PyObject)i.As<object>();
Assert.AreEqual(i.rawPtr, ni.rawPtr);
Assert.IsTrue(PythonReferenceComparer.Instance.Equals(i, ni));
}

[Test]
Expand Down Expand Up @@ -178,8 +178,11 @@ public void RawPyObjectProxy()
var clrObject = (CLRObject)ManagedType.GetManagedObject(pyObjectProxy);
Assert.AreSame(pyObject, clrObject.inst);

var proxiedHandle = pyObjectProxy.GetAttr("Handle").As<IntPtr>();
Assert.AreEqual(pyObject.Handle, proxiedHandle);
#pragma warning disable CS0612 // Type or member is obsolete
const string handlePropertyName = nameof(PyObject.Handle);
#pragma warning restore CS0612 // Type or member is obsolete
var proxiedHandle = pyObjectProxy.GetAttr(handlePropertyName).As<IntPtr>();
Assert.AreEqual(pyObject.DangerousGetAddressOrNull(), proxiedHandle);
}

// regression for https://github.com/pythonnet/pythonnet/issues/451
Expand Down
3 changes: 1 addition & 2 deletions src/embed_tests/TestDomainReload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ from Python.EmbeddingTest.Domain import MyClass
{
Debug.Assert(obj.AsManagedObject(type).GetType() == type);
// We only needs its Python handle
PyRuntime.XIncref(obj);
return obj.Handle;
return new NewReference(obj).DangerousMoveToPointer();
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/embed_tests/TestFinalizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,9 @@ public void ValidateRefCount()
Assert.AreEqual(ptr, e.Handle);
Assert.AreEqual(2, e.ImpactedObjects.Count);
// Fix for this test, don't do this on general environment
#pragma warning disable CS0618 // Type or member is obsolete
Runtime.Runtime.XIncref(e.Reference);
#pragma warning restore CS0618 // Type or member is obsolete
return false;
};
Finalizer.Instance.IncorrectRefCntResolver += handler;
Expand All @@ -234,8 +236,9 @@ private static IntPtr CreateStringGarbage()
{
PyString s1 = new PyString("test_string");
// s2 steal a reference from s1
PyString s2 = new PyString(StolenReference.DangerousFromPointer(s1.Handle));
return s1.Handle;
IntPtr address = s1.Reference.DangerousGetAddress();
PyString s2 = new (StolenReference.DangerousFromPointer(address));
return address;
}
}
}
3 changes: 2 additions & 1 deletion src/embed_tests/TestNativeTypeOffset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public void LoadNativeTypeOffsetClass()
{
PyObject sys = Py.Import("sys");
// We can safely ignore the "m" abi flag
var abiflags = sys.GetAttr("abiflags", "".ToPython()).ToString().Replace("m", "");
var abiflags = sys.HasAttr("abiflags") ? sys.GetAttr("abiflags").ToString() : "";
abiflags = abiflags.Replace("m", "");
if (!string.IsNullOrEmpty(abiflags))
{
string typeName = "Python.Runtime.NativeTypeOffset, Python.Runtime";
Expand Down
2 changes: 1 addition & 1 deletion src/embed_tests/TestPythonException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def __init__(self, val):
using var tbObj = tbPtr.MoveToPyObject();
// the type returned from PyErr_NormalizeException should not be the same type since a new
// exception was raised by initializing the exception
Assert.AreNotEqual(type.Handle, typeObj.Handle);
Assert.IsFalse(PythonReferenceComparer.Instance.Equals(type, typeObj));
// the message should now be the string from the throw exception during normalization
Assert.AreEqual("invalid literal for int() with base 10: 'dummy string'", strObj.ToString());
}
Expand Down
9 changes: 9 additions & 0 deletions src/python_tests_runner/PythonTestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class PythonTestRunner
[OneTimeSetUp]
public void SetUp()
{
Python.Runtime.Runtime.PythonDLL =
"C:\\Python37.2\\python37.dll";
PythonEngine.Initialize();
}

Expand All @@ -35,6 +37,13 @@ static IEnumerable<string[]> PythonTestCases()
// Add the test that you want to debug here.
yield return new[] { "test_indexer", "test_boolean_indexer" };
yield return new[] { "test_delegate", "test_bool_delegate" };
yield return new[] { "test_subclass", "test_virtual_generic_method" };
yield return new[] { "test_subclass", "test_interface_and_class_impl2" };
yield return new[] { "test_subclass", "test_class_with_attributes" };
yield return new[] { "test_subclass", "test_class_with_advanced_attribute" };
yield return new[] { "test_subclass", "test_more_subclasses" };
yield return new[] { "test_subclass", "test_more_subclasses2" };
yield return new[] { "test_subclass", "abstract_test" };
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/InternString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static void Initialize()
Debug.Assert(name == op.As<string>());
SetIntern(name, op);
var field = type.GetField("f" + name, PyIdentifierFieldFlags)!;
field.SetValue(null, op.rawPtr);
field.SetValue(null, op.DangerousGetAddressOrNull());
}
}

Expand Down Expand Up @@ -76,7 +76,7 @@ public static bool TryGetInterned(BorrowedReference op, out string s)
private static void SetIntern(string s, PyString op)
{
_string2interns.Add(s, op);
_intern2strings.Add(op.rawPtr, s);
_intern2strings.Add(op.Reference.DangerousGetAddress(), s);
}
}
}
143 changes: 143 additions & 0 deletions src/runtime/Native/TypeOffset311.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Auto-generated by geninterop.py.
// DO NOT MODIFY BY HAND.

// Python 3.11: 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 TypeOffset311 : GeneratedTypeOffsets, ITypeOffsets
{
public TypeOffset311()
{

}
// 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; }
public int _ht_tpname { get; private set; }
public int spec_cache_getitem { get; private set; }
}
}
3 changes: 2 additions & 1 deletion src/runtime/PythonTypes/PyInt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ public BigInteger ToBigInteger()
public string ToString(string format, IFormatProvider formatProvider)
{
using var _ = Py.GIL();
return ToBigInteger().ToString(format, formatProvider);
object val = Runtime.PyLong_AsLongLong(obj);
return val?.ToString() ?? ToBigInteger().ToString(format, formatProvider);
}

public override TypeCode GetTypeCode() => TypeCode.Int64;
Expand Down
12 changes: 7 additions & 5 deletions src/runtime/PythonTypes/PyObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public partial class PyObject : DynamicObject, IDisposable, ISerializable
/// Trace stack for PyObject's construction
/// </summary>
public StackTrace Traceback { get; } = new StackTrace(1);
#endif
#endif

protected internal IntPtr rawPtr = IntPtr.Zero;
protected IntPtr rawPtr = IntPtr.Zero;
internal readonly int run = Runtime.GetRun();

internal BorrowedReference obj => new (rawPtr);
Expand Down Expand Up @@ -165,7 +165,7 @@ public static PyObject FromManagedObject(object ob)
{
if (!Converter.ToManaged(obj, t, out var result, true))
{
throw new InvalidCastException("cannot convert object to target type",
throw new InvalidCastException($"Cannot convert object to target type '{t}'.",
PythonException.FetchCurrentOrNull(out _));
}
return result;
Expand Down Expand Up @@ -235,7 +235,7 @@ public void Dispose()
{
GC.SuppressFinalize(this);
Dispose(true);

}

internal StolenReference Steal()
Expand All @@ -252,6 +252,8 @@ internal void Leak()
rawPtr = IntPtr.Zero;
}

internal IntPtr DangerousGetAddressOrNull() => rawPtr;

internal void CheckRun()
{
if (run != Runtime.GetRun())
Expand Down Expand Up @@ -1312,7 +1314,7 @@ private bool TryCompare(PyObject arg, int op, out object @out)
}
return true;
}

public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object? result)
{
using var _ = Py.GIL();
Expand Down
27 changes: 27 additions & 0 deletions src/runtime/PythonTypes/PythonTypeAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;

namespace Python.Runtime;

/// <summary>
/// Marks a property type with a specific python type. Normally, properties has .NET types, but if the property has a python type,
/// that cannot be represented in the propert type info, so this attribute is used to mark the property with the corresponding python type.
/// </summary>
public class PythonTypeAttribute : Attribute
{
/// <summary> Type name. </summary>
public string TypeName { get; }

/// <summary> Importable module name. </summary>
public string Module { get; }

/// <summary>
/// Creates a new instance of PythonTypeAttribute.
/// </summary>
/// <param name="pyTypeModule"></param>
/// <param name="pyTypeName"></param>
public PythonTypeAttribute(string pyTypeModule, string pyTypeName)
{
TypeName = pyTypeName;
Module = pyTypeModule;
}
}
Loading