Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5bcd708

Browse files
authored
Merge pull request pythonnet#1391 from losttech/cleanup/21-02-19
Remove Utf8Marshaler, set PyScope base class to PyObject, added PyModule
2 parents c4f2ad7 + ac68aab commit 5bcd708

20 files changed

+171
-177
lines changed

src/embed_tests/GlobalTestsSetup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Python.EmbeddingTest
77
// As the SetUpFixture, the OneTimeTearDown of this class is executed after
88
// all tests have run.
99
[SetUpFixture]
10-
public class GlobalTestsSetup
10+
public partial class GlobalTestsSetup
1111
{
1212
[OneTimeTearDown]
1313
public void FinalCleanup()

src/embed_tests/TestFinalizer.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,17 @@ public void CollectOnShutdown()
101101

102102
PythonEngine.Shutdown();
103103
garbage = Finalizer.Instance.GetCollectedObjects();
104-
Assert.IsEmpty(garbage);
104+
105+
if (garbage.Count > 0)
106+
{
107+
PythonEngine.Initialize();
108+
string objects = string.Join("\n", garbage.Select(ob =>
109+
{
110+
var obj = new PyObject(new BorrowedReference(ob));
111+
return $"{obj} [{obj.GetPythonType()}@{obj.Handle}]";
112+
}));
113+
Assert.Fail("Garbage is not empty:\n" + objects);
114+
}
105115
}
106116

107117
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] // ensure lack of references to obj
@@ -173,7 +183,7 @@ public void SimpleTestMemory()
173183
bool oldState = Finalizer.Instance.Enable;
174184
try
175185
{
176-
using (PyObject gcModule = PythonEngine.ImportModule("gc"))
186+
using (PyModule gcModule = PyModule.Import("gc"))
177187
using (PyObject pyCollect = gcModule.GetAttr("collect"))
178188
{
179189
long span1 = CompareWithFinalizerOn(pyCollect, false);

src/embed_tests/TestNativeTypeOffset.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
using Python.Runtime;
1111

12-
namespace Python.EmbeddingPythonTest
12+
namespace Python.EmbeddingTest
1313
{
1414
public class TestNativeTypeOffset
1515
{

src/embed_tests/TestPythonException.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public void TestPythonErrorTypeName()
4646
{
4747
try
4848
{
49-
var module = PythonEngine.ImportModule("really____unknown___module");
49+
var module = PyModule.Import("really____unknown___module");
5050
Assert.Fail("Unknown module should not be loaded");
5151
}
5252
catch (PythonException ex)
@@ -95,7 +95,7 @@ public void TestPythonExceptionFormatNoTraceback()
9595
{
9696
try
9797
{
98-
var module = PythonEngine.ImportModule("really____unknown___module");
98+
var module = PyModule.Import("really____unknown___module");
9999
Assert.Fail("Unknown module should not be loaded");
100100
}
101101
catch (PythonException ex)

src/embed_tests/TestRuntime.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test()
9696
// TypeFlags.HaveIter set in Python 2. This tests a different code path in PyObject_IsIterable and PyIter_Check.
9797
var threading = Runtime.Runtime.PyImport_ImportModule("threading");
9898
Exceptions.ErrorCheck(threading);
99-
var threadingDict = Runtime.Runtime.PyModule_GetDict(new BorrowedReference(threading));
99+
var threadingDict = Runtime.Runtime.PyModule_GetDict(threading);
100100
Exceptions.ErrorCheck(threadingDict);
101101
var lockType = Runtime.Runtime.PyDict_GetItemString(threadingDict, "Lock");
102102
if (lockType.IsNull)
@@ -110,6 +110,8 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test()
110110
Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance));
111111
Assert.IsFalse(Runtime.Runtime.PyIter_Check(lockInstance));
112112

113+
threading.Dispose();
114+
113115
Runtime.Runtime.Py_Finalize();
114116
}
115117
}

src/embed_tests/pyimport.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public void Dispose()
5252
[Test]
5353
public void TestDottedName()
5454
{
55-
PyObject module = PythonEngine.ImportModule("PyImportTest.test.one");
55+
var module = PyModule.Import("PyImportTest.test.one");
5656
Assert.IsNotNull(module);
5757
}
5858

@@ -62,7 +62,7 @@ public void TestDottedName()
6262
[Test]
6363
public void TestSysArgsImportException()
6464
{
65-
PyObject module = PythonEngine.ImportModule("PyImportTest.sysargv");
65+
var module = PyModule.Import("PyImportTest.sysargv");
6666
Assert.IsNotNull(module);
6767
}
6868

src/embed_tests/pyinitialize.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ public static void TestRunExitFuncs()
175175
{
176176
called = true;
177177
};
178-
atexit.InvokeMethod("register", callback.ToPython());
178+
atexit.InvokeMethod("register", callback.ToPython()).Dispose();
179+
atexit.Dispose();
179180
Runtime.Runtime.Shutdown();
180181
Assert.True(called);
181182
}

src/runtime/BorrowedReference.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ public BorrowedReference(IntPtr pointer)
2828
=> a.pointer == b.pointer;
2929
public static bool operator !=(BorrowedReference a, BorrowedReference b)
3030
=> a.pointer != b.pointer;
31+
public static bool operator ==(BorrowedReference reference, NullOnly @null)
32+
=> reference.IsNull;
33+
public static bool operator !=(BorrowedReference reference, NullOnly @null)
34+
=> !reference.IsNull;
35+
public static bool operator ==(NullOnly @null, BorrowedReference reference)
36+
=> reference.IsNull;
37+
public static bool operator !=(NullOnly @null, BorrowedReference reference)
38+
=> !reference.IsNull;
3139

3240
public override bool Equals(object obj) {
3341
if (obj is IntPtr ptr)

src/runtime/CustomMarshaler.cs

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -189,49 +189,4 @@ public static ICustomMarshaler GetInstance(string cookie)
189189
return Instance;
190190
}
191191
}
192-
193-
194-
/// <summary>
195-
/// Custom Marshaler to deal with Managed String to Native
196-
/// conversion on UTF-8. Use on functions that expect UTF-8 encoded
197-
/// strings like `PyUnicode_FromStringAndSize`
198-
/// </summary>
199-
/// <remarks>
200-
/// If instead we used `MarshalAs(UnmanagedType.LPWStr)` the output to
201-
/// `foo` would be `f\x00o\x00o\x00`.
202-
/// </remarks>
203-
internal class Utf8Marshaler : MarshalerBase
204-
{
205-
private static readonly MarshalerBase Instance = new Utf8Marshaler();
206-
private static readonly Encoding PyEncoding = Encoding.UTF8;
207-
208-
public override IntPtr MarshalManagedToNative(object managedObj)
209-
{
210-
var s = managedObj as string;
211-
212-
if (s == null)
213-
{
214-
return IntPtr.Zero;
215-
}
216-
217-
byte[] bStr = PyEncoding.GetBytes(s + "\0");
218-
IntPtr mem = Marshal.AllocHGlobal(bStr.Length);
219-
try
220-
{
221-
Marshal.Copy(bStr, 0, mem, bStr.Length);
222-
}
223-
catch (Exception)
224-
{
225-
Marshal.FreeHGlobal(mem);
226-
throw;
227-
}
228-
229-
return mem;
230-
}
231-
232-
public static ICustomMarshaler GetInstance(string cookie)
233-
{
234-
return Instance;
235-
}
236-
}
237192
}

src/runtime/exceptions.cs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -95,24 +95,21 @@ internal static Exception ToException(IntPtr ob)
9595
/// </remarks>
9696
public static class Exceptions
9797
{
98-
internal static IntPtr warnings_module;
99-
internal static IntPtr exceptions_module;
98+
internal static PyModule warnings_module;
99+
internal static PyModule exceptions_module;
100100

101101
/// <summary>
102102
/// Initialization performed on startup of the Python runtime.
103103
/// </summary>
104104
internal static void Initialize()
105105
{
106106
string exceptionsModuleName = "builtins";
107-
exceptions_module = Runtime.PyImport_ImportModule(exceptionsModuleName);
108-
109-
Exceptions.ErrorCheck(exceptions_module);
110-
warnings_module = Runtime.PyImport_ImportModule("warnings");
111-
Exceptions.ErrorCheck(warnings_module);
107+
exceptions_module = PyModule.Import(exceptionsModuleName);
108+
warnings_module = PyModule.Import("warnings");
112109
Type type = typeof(Exceptions);
113110
foreach (FieldInfo fi in type.GetFields(BindingFlags.Public | BindingFlags.Static))
114111
{
115-
IntPtr op = Runtime.PyObject_GetAttrString(exceptions_module, fi.Name);
112+
IntPtr op = Runtime.PyObject_GetAttrString(exceptions_module.obj, fi.Name);
116113
if (op != IntPtr.Zero)
117114
{
118115
fi.SetValue(type, op);
@@ -147,8 +144,8 @@ internal static void Shutdown()
147144
Runtime.XDecref(op);
148145
fi.SetValue(null, IntPtr.Zero);
149146
}
150-
Runtime.Py_CLEAR(ref exceptions_module);
151-
Runtime.Py_CLEAR(ref warnings_module);
147+
exceptions_module.Dispose();
148+
warnings_module.Dispose();
152149
}
153150

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

351-
Runtime.XIncref(warnings_module);
352-
IntPtr warn = Runtime.PyObject_GetAttrString(warnings_module, "warn");
353-
Runtime.XDecref(warnings_module);
348+
IntPtr warn = Runtime.PyObject_GetAttrString(warnings_module.obj, "warn");
354349
Exceptions.ErrorCheck(warn);
355350

356351
IntPtr args = Runtime.PyTuple_New(3);

src/runtime/importhook.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public static unsafe NewReference GetCLRModule(BorrowedReference fromList = defa
155155

156156
// find any items from the from list and get them from the root if they're not
157157
// already in the module dictionary
158-
if (fromList != null && fromList != default)
158+
if (fromList != null)
159159
{
160160
if (Runtime.PyTuple_Check(fromList))
161161
{
@@ -224,7 +224,7 @@ public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
224224
if (num_args >= 4)
225225
{
226226
fromList = Runtime.PyTuple_GetItem(args, 3);
227-
if (fromList != default &&
227+
if (fromList != null &&
228228
Runtime.PyObject_IsTrue(fromList) == 1)
229229
{
230230
fromlist = true;
@@ -297,7 +297,7 @@ public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
297297
BorrowedReference modules = Runtime.PyImport_GetModuleDict();
298298
BorrowedReference module = Runtime.PyDict_GetItem(modules, py_mod_name);
299299

300-
if (module != default)
300+
if (module != null)
301301
{
302302
if (fromlist)
303303
{

src/runtime/pymodule.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
3+
namespace Python.Runtime
4+
{
5+
public class PyModule : PyScope
6+
{
7+
internal PyModule(ref NewReference reference) : base(ref reference, PyScopeManager.Global) { }
8+
public PyModule(PyObject o) : base(o.Reference, PyScopeManager.Global) { }
9+
10+
/// <summary>
11+
/// Given a module or package name, import the
12+
/// module and return the resulting module object as a <see cref="PyModule"/>.
13+
/// </summary>
14+
/// <param name="name">Fully-qualified module or package name</param>
15+
public static PyModule Import(string name)
16+
{
17+
NewReference op = Runtime.PyImport_ImportModule(name);
18+
PythonException.ThrowIfIsNull(op);
19+
return new PyModule(ref op);
20+
}
21+
22+
/// <summary>
23+
/// Reloads the module, and returns the updated object
24+
/// </summary>
25+
public PyModule Reload()
26+
{
27+
NewReference op = Runtime.PyImport_ReloadModule(this.Reference);
28+
PythonException.ThrowIfIsNull(op);
29+
return new PyModule(ref op);
30+
}
31+
32+
public static PyModule FromString(string name, string code)
33+
{
34+
using NewReference c = Runtime.Py_CompileString(code, "none", (int)RunFlagType.File);
35+
PythonException.ThrowIfIsNull(c);
36+
NewReference m = Runtime.PyImport_ExecCodeModule(name, c);
37+
PythonException.ThrowIfIsNull(m);
38+
return new PyModule(ref m);
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)