8000 merge latest master · pythonnet/pythonnet@6ae373c · GitHub
[go: up one dir, main page]

Skip to content

Commit 6ae373c

Browse files
committed
merge latest master
2 parents 197689e + 2b0e322 commit 6ae373c

16 files changed

+204
-99
lines changed

src/embed_tests/Codecs.cs

+39Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ static void TupleConversionsGeneric<T, TTuple>()
3131
TupleCodec<TTuple>.Register();
3232
var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object());
3333
T restored = default;
34-
using (Py.GIL())
3534
using (var scope = Py.CreateScope())
3635
{
3736
void Accept(T value) => restored = value;
@@ -53,7 +52,6 @@ static void TupleConversionsObject<T, TTuple>()
5352
TupleCodec<TTuple>.Register();
5453
var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object());
5554
T restored = default;
56-
using (Py.GIL())
5755
using (var scope = Py.CreateScope())
5856
{
5957
void Accept(object value) => restored = (T)value;
@@ -73,12 +71,9 @@ public void TupleRoundtripObject()
7371
static void TupleRoundtripObject<T, TTuple>()
7472
{
7573
var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object());
76-
using (Py.GIL())
77-
{
78-
var pyTuple = TupleCodec<TTuple>.Instance.TryEncode(tuple);
79-
Assert.IsTrue(TupleCodec<TTuple>.Instance.TryDecode(pyTuple, out object restored));
80-
Assert.AreEqual(expected: tuple, actual: restored);
81-
}
74+
var pyTuple = TupleCodec<TTuple>.Instance.TryEncode(tuple);
75+
Assert.IsTrue(TupleCodec<TTuple>.Instance.TryDecode(pyTuple, out object restored));
76+
Assert.AreEqual(expected: tuple, actual: restored);
8277
}
8378

8479
[Test]
@@ -90,21 +85,12 @@ public void TupleRoundtripGeneric()
9085
static void TupleRoundtripGeneric<T, TTuple>()
9186
{
9287
var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object());
93-
using (Py.GIL())
94-
{
95-
var pyTuple = TupleCodec<TTuple>.Instance.TryEncode(tuple);
96-
Assert.IsTrue(TupleCodec<TTuple>.Instance.TryDecode(pyTuple, out T restored));
97-
Assert.AreEqual(expected: tuple, actual: restored);
98-
}
88+
var pyTuple = TupleCodec<TTuple>.Instance.TryEncode(tuple);
89+
Assert.IsTrue(TupleCodec<TTuple>.Instance.TryDecode(pyTuple, out T restored));
90+
Assert.AreEqual(expected: tuple, actual: restored);
9991
}
10092

101-
static PyObject GetPythonIterable()
102-
{
103-
using (Py.GIL())
104-
{
105-
return PythonEngine.Eval("map(lambda x: x, [1,2,3])");
106-
}
107-
}
93+
static PyObject GetPythonIterable() => PythonEngine.Eval("map(lambda x: x, [1,2,3])");
10894

10995
[Test]
11096
public void ListDecoderTest()
@@ -330,7 +316,6 @@ public void ExceptionEncoded()
330316
PyObjectConversions.RegisterEncoder(new ValueErrorCodec());
331317
void CallMe() => throw new ValueErrorWrapper(TestExceptionMessage);
332318
var callMeAction = new Action(CallMe);
333-
using var _ = Py.GIL();
334319
using var scope = Py.CreateScope();
335320
scope.Exec(@"
336321
def call(func):
@@ -348,7 +333,6 @@ def call(func):
348333
public void ExceptionDecoded()
349334
{
350335
PyObjectConversions.RegisterDecoder(new ValueErrorCodec());
351-
using var _ = Py.GIL();
352336
using var scope = Py.CreateScope();
353337
var error = Assert.Throws<ValueErrorWrapper>(()
354338
=> PythonEngine.Exec($"raise ValueError('{TestExceptionMessage}')"));
@@ -371,6 +355,16 @@ from datetime import datetime
371355
scope.Exec("Codecs.AcceptsDateTime(datetime(2021, 1, 22))");
372356
}
373357

358+
[Test]
359+
public void ExceptionDecodedNoInstance()
360+
{
361+
PyObjectConversions.RegisterDecoder(new InstancelessExceptionDecoder());
362+
using var scope = Py.CreateScope();
363+
var error = Assert.Throws<ValueErrorWrapper>(() => PythonEngine.Exec(
364+
$"[].__iter__().__next__()"));
365+
Assert.AreEqual(TestExceptionMessage, error.Message);
366+
}
367+
374368
public static void AcceptsDateTime(DateTime v) {}
375369

376370
[Test]
@@ -406,7 +400,8 @@ public ValueErrorWrapper(string message) : base(message) { }
406400
class ValueErrorCodec : IPyObjectEncoder, IPyObjectDecoder
407401
{
408402
public bool CanDecode(PyObject objectType, Type targetType)
409-
=> this.CanEncode(targetType) && objectType.Equals(PythonEngine.Eval("ValueError"));
403+
=> this.CanEncode(targetType)
404+
&& PythonReferenceComparer.Instance.Equals(objectType, PythonEngine.Eval("ValueError"));
410405

411406
public bool CanEncode(Type type) => type == typeof(ValueErrorWrapper)
412407
|| typeof(ValueErrorWrapper).IsSubclassOf(type);
@@ -424,6 +419,26 @@ public PyObject TryEncode(object value)
424419
return PythonEngine.Eval("ValueError").Invoke(error.Message.ToPython());
425420
}
426421
}
422+
423+
class InstancelessExceptionDecoder : IPyObjectDecoder
424+
{
425+
readonly PyObject PyErr = Py.Import("clr.interop").GetAttr("PyErr");
426+
427+
public bool CanDecode(PyObject objectType, Type targetType)
428+
=> PythonReferenceComparer.Instance.Equals(PyErr, objectType);
429+
430+
public bool TryDecode<T>(PyObject pyObj, out T value)
431+
{
432+
if (pyObj.HasAttr("value"))
433+
{
434+
value = default;
435+
return false;
436+
}
437+
438+
value = (T)(object)new ValueErrorWrapper(TestExceptionMessage);
439+
return true;
440+
}
441+
}
427442
}
428443

429444
/// <summary>

src/embed_tests/References.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,16 @@ namespace Python.EmbeddingTest
55

66
public class References
77
{
8-
private Py.GILState _gs;
9-
10-
[SetUp]
8+
[OneTimeSetUp]
119
public void SetUp()
1210
{
13-
_gs = Py.GIL();
11+
PythonEngine.Initialize();
1412
}
1513

16-
[TearDown]
14+
[OneTimeTearDown]
1715
public void Dispose()
1816
{
19-
_gs.Dispose();
17+
PythonEngine.Shutdown();
2018
}
2119

2220
[Test]

src/embed_tests/TestNativeTypeOffset.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,16 @@ namespace Python.EmbeddingTest
1313
{
1414
public class TestNativeTypeOffset
1515
{
16-
private Py.GILState _gs;
17-
18-
[SetUp]
16+
[OneTimeSetUp]
1917
public void SetUp()
2018
{
21-
_gs = Py.GIL();
19+
PythonEngine.Initialize();
2220
}
2321

24-
[TearDown]
22+
[OneTimeTearDown]
2523
public void Dispose()
2624
{
27-
_gs.Dispose();
25+
PythonEngine.Shutdown();
2826
}
2927

3028
/// <summary>

src/embed_tests/TestPythonException.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,15 @@ namespace Python.EmbeddingTest
66
{
77
public class TestPythonException
88
{
9-
private IntPtr _gs;
10-
11-
[SetUp]
9+
[OneTimeSetUp]
1210
public void SetUp()
1311
{
1412
PythonEngine.Initialize();
15-
_gs = PythonEngine.AcquireLock();
1613
}
1714

18-
[TearDown]
15+
[OneTimeTearDown]
1916
public void Dispose()
2017
{
21-
PythonEngine.ReleaseLock(_gs);
2218
PythonEngine.Shutdown();
2319
}
2420

src/embed_tests/dynamic.cs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,16 @@ namespace Python.EmbeddingTest
77
{
88
public class DynamicTest
99
{
10-
private Py.GILState _gs;
11-
12-
[SetUp]
10+
[OneTimeSetUp]
1311
public void SetUp()
1412
{
15-
try {
16-
_gs = Py.GIL();
17-
} catch (Exception e) {
18-
Console.WriteLine($"exception in SetUp: {e}");
19-
throw;
20-
}
13+
PythonEngine.Initialize();
2114
}
2215

23-
[TearDown]
16+
[OneTimeTearDown]
2417
public void Dispose()
2518
{
26-
try {
27-
_gs.Dispose();
28-
} catch(Exception e) {
29-
Console.WriteLine($"exception in TearDown: {e}");
30-
throw;
31-
}
19+
PythonEngine.Shutdown();
3220
}
3321

3422
/// <summary>

src/embed_tests/pyimport.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,10 @@ namespace Python.EmbeddingTest
1919
/// </remarks>
2020
public class PyImportTest
2121
{
22-
private IntPtr _gs;
23-
24-
[SetUp]
22+
[OneTimeSetUp]
2523
public void SetUp()
2624
{
2725
PythonEngine.Initialize();
28-
_gs = PythonEngine.AcquireLock();
2926

3027
/* Append the tests directory to sys.path
3128
* using reflection to circumvent the private
@@ -41,10 +38,9 @@ public void SetUp()
4138
Runtime.Runtime.XDecref(str);
4239
}
4340

44-
[TearDown]
41+
[OneTimeTearDown]
4542
public void Dispose()
4643
{
47-
PythonEngine.ReleaseLock(_gs);
4844
PythonEngine.Shutdown();
4945
}
5046

src/embed_tests/pyrunstring.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,16 @@ namespace Python.EmbeddingTest
66
{
77
public class RunStringTest
88
{
9-
private Py.GILState _gs;
10-
11-
[SetUp]
9+
[OneTimeSetUp]
1210
public void SetUp()
1311
{
14-
_gs = Py.GIL();
12+
PythonEngine.Initialize();
1513
}
1614

17-
[TearDown]
15+
[OneTimeTearDown]
1816
public void Dispose()
1917
{
20-
_gs.Dispose();
18+
PythonEngine.Shutdown();
2119
}
2220

2321
[Test]

src/runtime/Python.Runtime.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
<EmbeddedResource Include="resources\clr.py">
4343
<LogicalName>clr.py</LogicalName>
4444
</EmbeddedResource>
45+
<EmbeddedResource Include="resources\interop.py">
46+
<LogicalName>interop.py</LogicalName>
47+
</EmbeddedResource>
4548
<EmbeddedResource Include="Mixins\*.py" />
4649
</ItemGroup>
4750

src/runtime/Util.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
#nullable enable
12
using System;
3+
using System.IO;
24
using System.Runtime.InteropServices;
35

46
namespace Python.Runtime
@@ -48,13 +50,23 @@ internal static IntPtr Coalesce(this IntPtr primary, IntPtr fallback)
4850
/// <summary>
4951
/// Gets substring after last occurrence of <paramref name="symbol"/>
5052
/// </summary>
51-
internal static string AfterLast(this string str, char symbol)
53+
internal static string? AfterLast(this string str, char symbol)
5254
{
5355
if (str is null)
5456
throw new ArgumentNullException(nameof(str));
5557

5658
int last = str.LastIndexOf(symbol);
5759
return last >= 0 ? str.Substring(last + 1) : null;
5860
}
61+
62+
internal static string ReadStringResource(this System.Reflection.Assembly assembly, string resourceName)
63+
{
64+
if (assembly is null) throw new ArgumentNullException(nameof(assembly));
65+
if (string.IsNullOrEmpty(resourceName)) throw new ArgumentNullException(nameof(resourceName));
66+
67+
using var stream = assembly.GetManifestResourceStream(resourceName);
68+
using var reader = new StreamReader(stream);
69+
return reader.ReadToEnd();
70+
}
5971
}
6072
}

src/runtime/classbase.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,6 @@ static int ClearImpl(IntPtr ob, ManagedType self)
395395

396396
ClearObjectDict(ob);
397397
}
398-
if (self is not null) self.tpHandle = IntPtr.Zero;
399398
return 0;
400399
}
401400

src/runtime/managedtype.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,23 @@ internal enum TrackTypes
3030

3131
internal bool clearReentryGuard;
3232

33-
internal BorrowedReference ObjectReference => new(pyHandle);
34-
internal BorrowedReference TypeReference => new(tpHandle);
33+
internal BorrowedReference ObjectReference
34+
{
35+
get
36+
{
37+
Debug.Assert(pyHandle != IntPtr.Zero);
38+
return new(pyHandle);
39+
}
40+
}
41+
42+
internal BorrowedReference TypeReference
43+
{
44+
get
45+
{
46+
Debug.Assert(tpHandle != IntPtr.Zero);
47+
return new(tpHandle);
48+
}
49+
}
3550

3651
private static readonly Dictionary<ManagedType, TrackTypes> _managedObjs = new Dictionary<ManagedType, TrackTypes>();
3752

@@ -312,6 +327,8 @@ internal static void InitGCHandle(BorrowedReference reflectedClrObject, GCHandle
312327

313328
internal static void SetGCHandle(BorrowedReference reflectedClrObject, BorrowedReference type, GCHandle newHandle)
314329
{
330+
Debug.Assert(type != null);
331+
Debug.Assert(reflectedClrObject != null);
315332
Debug.Assert(Runtime.PyObject_TypeCheck(reflectedClrObject, type));
316333

317334
int offset = Marshal.ReadInt32(type.DangerousGetAddress(), Offsets.tp_clr_inst_offset);

0 commit comments

Comments
 (0)
0