◐ Shell
reader mode source ↗
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
14 changes: 12 additions & 2 deletions src/embed_tests/TestFinalizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,17 @@ public void CollectOnShutdown()

PythonEngine.Shutdown();
garbage = Finalizer.Instance.GetCollectedObjects();
Assert.IsEmpty(garbage);
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] // ensure lack of references to obj
Expand Down @@ -173,7 +183,7 @@ public void SimpleTestMemory()
bool oldState = Finalizer.Instance.Enable;
try
{
using (PyObject gcModule = PythonEngine.ImportModule("gc"))
using (PyObject pyCollect = gcModule.GetAttr("collect"))
{
long span1 = CompareWithFinalizerOn(pyCollect, false);
Expand Down
2 changes: 1 addition & 1 deletion src/embed_tests/TestNativeTypeOffset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

using Python.Runtime;

namespace Python.EmbeddingPythonTest
{
public class TestNativeTypeOffset
{
Expand Down
4 changes: 2 additions & 2 deletions src/embed_tests/TestPythonException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void TestPythonErrorTypeName()
{
try
{
var module = PythonEngine.ImportModule("really____unknown___module");
Assert.Fail("Unknown module should not be loaded");
}
catch (PythonException ex)
Expand Down Expand Up @@ -95,7 +95,7 @@ public void TestPythonExceptionFormatNoTraceback()
{
try
{
var module = PythonEngine.ImportModule("really____unknown___module");
Assert.Fail("Unknown module should not be loaded");
}
catch (PythonException ex)
Expand Down
4 changes: 3 additions & 1 deletion src/embed_tests/TestRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test()
// TypeFlags.HaveIter set in Python 2. This tests a different code path in PyObject_IsIterable and PyIter_Check.
var threading = Runtime.Runtime.PyImport_ImportModule("threading");
Exceptions.ErrorCheck(threading);
var threadingDict = Runtime.Runtime.PyModule_GetDict(new BorrowedReference(threading));
Exceptions.ErrorCheck(threadingDict);
var lockType = Runtime.Runtime.PyDict_GetItemString(threadingDict, "Lock");
if (lockType.IsNull)
Expand All @@ -110,6 +110,8 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test()
Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance));
Assert.IsFalse(Runtime.Runtime.PyIter_Check(lockInstance));

Runtime.Runtime.Py_Finalize();
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/embed_tests/pyimport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void Dispose()
[Test]
public void TestDottedName()
{
PyObject module = PythonEngine.ImportModule("PyImportTest.test.one");
Assert.IsNotNull(module);
}

Expand All @@ -62,7 +62,7 @@ public void TestDottedName()
[Test]
public void TestSysArgsImportException()
{
PyObject module = PythonEngine.ImportModule("PyImportTest.sysargv");
Assert.IsNotNull(module);
}

Expand Down
3 changes: 2 additions & 1 deletion src/embed_tests/pyinitialize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ public static void TestRunExitFuncs()
{
called = true;
};
atexit.InvokeMethod("register", callback.ToPython());
Runtime.Runtime.Shutdown();
Assert.True(called);
}
Expand Down
8 changes: 8 additions & 0 deletions src/runtime/BorrowedReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ public BorrowedReference(IntPtr pointer)
=> a.pointer == b.pointer;
public static bool operator !=(BorrowedReference a, BorrowedReference b)
=> a.pointer != b.pointer;

public override bool Equals(object obj) {
if (obj is IntPtr ptr)
Expand Down
45 changes: 0 additions & 45 deletions src/runtime/CustomMarshaler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,49 +189,4 @@ public static ICustomMarshaler GetInstance(string cookie)
return Instance;
}
}


/// <summary>
/// Custom Marshaler to deal with Managed String to Native
/// conversion on UTF-8. Use on functions that expect UTF-8 encoded
/// strings like `PyUnicode_FromStringAndSize`
/// </summary>
/// <remarks>
/// If instead we used `MarshalAs(UnmanagedType.LPWStr)` the output to
/// `foo` would be `f\x00o\x00o\x00`.
/// </remarks>
internal class Utf8Marshaler : MarshalerBase
{
private static readonly MarshalerBase Instance = new Utf8Marshaler();
private static readonly Encoding PyEncoding = Encoding.UTF8;

public override IntPtr MarshalManagedToNative(object managedObj)
{
var s = managedObj as string;

if (s == null)
{
return IntPtr.Zero;
}

byte[] bStr = PyEncoding.GetBytes(s + "\0");
IntPtr mem = Marshal.AllocHGlobal(bStr.Length);
try
{
Marshal.Copy(bStr, 0, mem, bStr.Length);
}
catch (Exception)
{
Marshal.FreeHGlobal(mem);
throw;
}

return mem;
}

public static ICustomMarshaler GetInstance(string cookie)
{
return Instance;
}
}
}
21 changes: 8 additions & 13 deletions src/runtime/exceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,24 +95,21 @@ internal static Exception ToException(IntPtr ob)
/// </remarks>
public static class Exceptions
{
internal static IntPtr warnings_module;
internal static IntPtr exceptions_module;

/// <summary>
/// Initialization performed on startup of the Python runtime.
/// </summary>
internal static void Initialize()
{
string exceptionsModuleName = "builtins";
exceptions_module = Runtime.PyImport_ImportModule(exceptionsModuleName);

Exceptions.ErrorCheck(exceptions_module);
warnings_module = Runtime.PyImport_ImportModule("warnings");
Exceptions.ErrorCheck(warnings_module);
Type type = typeof(Exceptions);
foreach (FieldInfo fi in type.GetFields(BindingFlags.Public | BindingFlags.Static))
{
IntPtr op = Runtime.PyObject_GetAttrString(exceptions_module, fi.Name);
if (op != IntPtr.Zero)
{
fi.SetValue(type, op);
Expand Down Expand Up @@ -147,8 +144,8 @@ internal static void Shutdown()
Runtime.XDecref(op);
fi.SetValue(null, IntPtr.Zero);
}
Runtime.Py_CLEAR(ref exceptions_module);
Runtime.Py_CLEAR(ref warnings_module);
}

/// <summary>
Expand Down Expand Up @@ -348,9 +345,7 @@ public static void warn(string message, IntPtr exception, int stacklevel)
Exceptions.RaiseTypeError("Invalid exception");
}

Runtime.XIncref(warnings_module);
IntPtr warn = Runtime.PyObject_GetAttrString(warnings_module, "warn");
Runtime.XDecref(warnings_module);
Exceptions.ErrorCheck(warn);

IntPtr args = Runtime.PyTuple_New(3);
Expand Down
6 changes: 3 additions & 3 deletions src/runtime/importhook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public static unsafe NewReference GetCLRModule(BorrowedReference fromList = defa

// find any items from the from list and get them from the root if they're not
// already in the module dictionary
if (fromList != null && fromList != default)
{
if (Runtime.PyTuple_Check(fromList))
{
Expand Down Expand Up @@ -224,7 +224,7 @@ public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
if (num_args >= 4)
{
fromList = Runtime.PyTuple_GetItem(args, 3);
if (fromList != default &&
Runtime.PyObject_IsTrue(fromList) == 1)
{
fromlist = true;
Expand Down Expand Up @@ -297,7 +297,7 @@ public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
BorrowedReference modules = Runtime.PyImport_GetModuleDict();
BorrowedReference module = Runtime.PyDict_GetItem(modules, py_mod_name);

if (module != default)
{
if (fromlist)
{
Expand Down
41 changes: 41 additions & 0 deletions src/runtime/pymodule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Loading
Toggle all file notes Toggle all file annotations