| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,7 +31,6 @@ static void TupleConversionsGeneric<T, TTuple>() | |||
| 31 | 31 | TupleCodec<TTuple>.Register(); | |
| 32 | 32 | var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object()); | |
| 33 | 33 | T restored = default; | |
| 34 | - using (Py.GIL()) | ||
| 35 | 34 | using (var scope = Py.CreateScope()) | |
| 36 | 35 | { | |
| 37 | 36 | void Accept(T value) => restored = value; | |
@@ -53,7 +52,6 @@ static void TupleConversionsObject<T, TTuple>() | |||
| 53 | 52 | TupleCodec<TTuple>.Register(); | |
| 54 | 53 | var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object()); | |
| 55 | 54 | T restored = default; | |
| 56 | - using (Py.GIL()) | ||
| 57 | 55 | using (var scope = Py.CreateScope()) | |
| 58 | 56 | { | |
| 59 | 57 | void Accept(object value) => restored = (T)value; | |
@@ -73,12 +71,9 @@ public void TupleRoundtripObject() | |||
| 73 | 71 | static void TupleRoundtripObject<T, TTuple>() | |
| 74 | 72 | { | |
| 75 | 73 | 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); | ||
| 82 | 77 | } | |
| 83 | 78 | ||
| 84 | 79 | [Test] | |
@@ -90,21 +85,12 @@ public void TupleRoundtripGeneric() | |||
| 90 | 85 | static void TupleRoundtripGeneric<T, TTuple>() | |
| 91 | 86 | { | |
| 92 | 87 | 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); | ||
| 99 | 91 | } | |
| 100 | 92 | ||
| 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])"); | ||
| 108 | 94 | ||
| 109 | 95 | [Test] | |
| 110 | 96 | public void ListDecoderTest() | |
@@ -330,7 +316,6 @@ public void ExceptionEncoded() | |||
| 330 | 316 | PyObjectConversions.RegisterEncoder(new ValueErrorCodec()); | |
| 331 | 317 | void CallMe() => throw new ValueErrorWrapper(TestExceptionMessage); | |
| 332 | 318 | var callMeAction = new Action(CallMe); | |
| 333 | - using var _ = Py.GIL(); | ||
| 334 | 319 | using var scope = Py.CreateScope(); | |
| 335 | 320 | scope.Exec(@" | |
| 336 | 321 | def call(func): | |
@@ -348,7 +333,6 @@ def call(func): | |||
| 348 | 333 | public void ExceptionDecoded() | |
| 349 | 334 | { | |
| 350 | 335 | PyObjectConversions.RegisterDecoder(new ValueErrorCodec()); | |
| 351 | - using var _ = Py.GIL(); | ||
| 352 | 336 | using var scope = Py.CreateScope(); | |
| 353 | 337 | var error = Assert.Throws<ValueErrorWrapper>(() | |
| 354 | 338 | => PythonEngine.Exec($"raise ValueError('{TestExceptionMessage}')")); | |
@@ -371,6 +355,16 @@ from datetime import datetime | |||
| 371 | 355 | scope.Exec("Codecs.AcceptsDateTime(datetime(2021, 1, 22))"); | |
| 372 | 356 | } | |
| 373 | 357 | ||
| 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 | + | ||
| 374 | 368 | public static void AcceptsDateTime(DateTime v) {} | |
| 375 | 369 | ||
| 376 | 370 | [Test] | |
@@ -406,7 +400,8 @@ public ValueErrorWrapper(string message) : base(message) { } | |||
| 406 | 400 | class ValueErrorCodec : IPyObjectEncoder, IPyObjectDecoder | |
| 407 | 401 | { | |
| 408 | 402 | 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")); | ||
| 410 | 405 | ||
| 411 | 406 | public bool CanEncode(Type type) => type == typeof(ValueErrorWrapper) | |
| 412 | 407 | || typeof(ValueErrorWrapper).IsSubclassOf(type); | |
@@ -424,6 +419,26 @@ public PyObject TryEncode(object value) | |||
| 424 | 419 | return PythonEngine.Eval("ValueError").Invoke(error.Message.ToPython()); | |
| 425 | 420 | } | |
| 426 | 421 | } | |
| 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 | + } | ||
| 427 | 442 | } | |
| 428 | 443 | ||
| 429 | 444 | /// <summary> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,18 +5,16 @@ namespace Python.EmbeddingTest | |||
| 5 | 5 | ||
| 6 | 6 | public class References | |
| 7 | 7 | { | |
| 8 | - private Py.GILState _gs; | ||
| 9 | - | ||
| 10 | - [SetUp] | ||
| 8 | + [OneTimeSetUp] | ||
| 11 | 9 | public void SetUp() | |
| 12 | 10 | { | |
| 13 | - _gs = Py.GIL(); | ||
| 11 | + PythonEngine.Initialize(); | ||
| 14 | 12 | } | |
| 15 | 13 | ||
| 16 | - [TearDown] | ||
| 14 | + [OneTimeTearDown] | ||
| 17 | 15 | public void Dispose() | |
| 18 | 16 | { | |
| 19 | - _gs.Dispose(); | ||
| 17 | + PythonEngine.Shutdown(); | ||
| 20 | 18 | } | |
| 21 | 19 | ||
| 22 | 20 | [Test] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,18 +13,16 @@ namespace Python.EmbeddingTest | |||
| 13 | 13 | { | |
| 14 | 14 | public class TestNativeTypeOffset | |
| 15 | 15 | { | |
| 16 | - private Py.GILState _gs; | ||
| 17 | - | ||
| 18 | - [SetUp] | ||
| 16 | + [OneTimeSetUp] | ||
| 19 | 17 | public void SetUp() | |
| 20 | 18 | { | |
| 21 | - _gs = Py.GIL(); | ||
| 19 | + PythonEngine.Initialize(); | ||
| 22 | 20 | } | |
| 23 | 21 | ||
| 24 | - [TearDown] | ||
| 22 | + [OneTimeTearDown] | ||
| 25 | 23 | public void Dispose() | |
| 26 | 24 | { | |
| 27 | - _gs.Dispose(); | ||
| 25 | + PythonEngine.Shutdown(); | ||
| 28 | 26 | } | |
| 29 | 27 | ||
| 30 | 28 | /// <summary> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,19 +6,15 @@ namespace Python.EmbeddingTest | |||
| 6 | 6 | { | |
| 7 | 7 | public class TestPythonException | |
| 8 | 8 | { | |
| 9 | - private IntPtr _gs; | ||
| 10 | - | ||
| 11 | - [SetUp] | ||
| 9 | + [OneTimeSetUp] | ||
| 12 | 10 | public void SetUp() | |
| 13 | 11 | { | |
| 14 | 12 | PythonEngine.Initialize(); | |
| 15 | - _gs = PythonEngine.AcquireLock(); | ||
| 16 | 13 | } | |
| 17 | 14 | ||
| 18 | - [TearDown] | ||
| 15 | + [OneTimeTearDown] | ||
| 19 | 16 | public void Dispose() | |
| 20 | 17 | { | |
| 21 | - PythonEngine.ReleaseLock(_gs); | ||
| 22 | 18 | PythonEngine.Shutdown(); | |
| 23 | 19 | } | |
| 24 | 20 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,28 +7,16 @@ namespace Python.EmbeddingTest | |||
| 7 | 7 | { | |
| 8 | 8 | public class DynamicTest | |
| 9 | 9 | { | |
| 10 | - private Py.GILState _gs; | ||
| 11 | - | ||
| 12 | - [SetUp] | ||
| 10 | + [OneTimeSetUp] | ||
| 13 | 11 | public void SetUp() | |
| 14 | 12 | { | |
| 15 | - try { | ||
| 16 | - _gs = Py.GIL(); | ||
| 17 | - } catch (Exception e) { | ||
| 18 | - Console.WriteLine($"exception in SetUp: {e}"); | ||
| 19 | - throw; | ||
| 20 | - } | ||
| 13 | + PythonEngine.Initialize(); | ||
| 21 | 14 | } | |
| 22 | 15 | ||
| 23 | - [TearDown] | ||
| 16 | + [OneTimeTearDown] | ||
| 24 | 17 | public void Dispose() | |
| 25 | 18 | { | |
| 26 | - try { | ||
| 27 | - _gs.Dispose(); | ||
| 28 | - } catch(Exception e) { | ||
| 29 | - Console.WriteLine($"exception in TearDown: {e}"); | ||
| 30 | - throw; | ||
| 31 | - } | ||
| 19 | + PythonEngine.Shutdown(); | ||
| 32 | 20 | } | |
| 33 | 21 | ||
| 34 | 22 | /// <summary> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,13 +19,10 @@ namespace Python.EmbeddingTest | |||
| 19 | 19 | /// </remarks> | |
| 20 | 20 | public class PyImportTest | |
| 21 | 21 | { | |
| 22 | - private IntPtr _gs; | ||
| 23 | - | ||
| 24 | - [SetUp] | ||
| 22 | + [OneTimeSetUp] | ||
| 25 | 23 | public void SetUp() | |
| 26 | 24 | { | |
| 27 | 25 | PythonEngine.Initialize(); | |
| 28 | - _gs = PythonEngine.AcquireLock(); | ||
| 29 | 26 | ||
| 30 | 27 | /* Append the tests directory to sys.path | |
| 31 | 28 | * using reflection to circumvent the private | |
@@ -41,10 +38,9 @@ public void SetUp() | |||
| 41 | 38 | Runtime.Runtime.XDecref(str); | |
| 42 | 39 | } | |
| 43 | 40 | ||
| 44 | - [TearDown] | ||
| 41 | + [OneTimeTearDown] | ||
| 45 | 42 | public void Dispose() | |
| 46 | 43 | { | |
| 47 | - PythonEngine.ReleaseLock(_gs); | ||
| 48 | 44 | PythonEngine.Shutdown(); | |
| 49 | 45 | } | |
| 50 | 46 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,18 +6,16 @@ namespace Python.EmbeddingTest | |||
| 6 | 6 | { | |
| 7 | 7 | public class RunStringTest | |
| 8 | 8 | { | |
| 9 | - private Py.GILState _gs; | ||
| 10 | - | ||
| 11 | - [SetUp] | ||
| 9 | + [OneTimeSetUp] | ||
| 12 | 10 | public void SetUp() | |
| 13 | 11 | { | |
| 14 | - _gs = Py.GIL(); | ||
| 12 | + PythonEngine.Initialize(); | ||
| 15 | 13 | } | |
| 16 | 14 | ||
| 17 | - [TearDown] | ||
| 15 | + [OneTimeTearDown] | ||
| 18 | 16 | public void Dispose() | |
| 19 | 17 | { | |
| 20 | - _gs.Dispose(); | ||
| 18 | + PythonEngine.Shutdown(); | ||
| 21 | 19 | } | |
| 22 | 20 | ||
| 23 | 21 | [Test] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -42,6 +42,9 @@ | |||
| 42 | 42 | <EmbeddedResource Include="resources\clr.py"> | |
| 43 | 43 | <LogicalName>clr.py</LogicalName> | |
| 44 | 44 | </EmbeddedResource> | |
| 45 | + <EmbeddedResource Include="resources\interop.py"> | ||
| 46 | + <LogicalName>interop.py</LogicalName> | ||
| 47 | + </EmbeddedResource> | ||
| 45 | 48 | <EmbeddedResource Include="Mixins\*.py" /> | |
| 46 | 49 | </ItemGroup> | |
| 47 | 50 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,6 @@ | |||
| 1 | + #nullable enable | ||
| 1 | 2 | using System; | |
| 3 | + using System.IO; | ||
| 2 | 4 | using System.Runtime.InteropServices; | |
| 3 | 5 | ||
| 4 | 6 | namespace Python.Runtime | |
@@ -48,13 +50,23 @@ internal static IntPtr Coalesce(this IntPtr primary, IntPtr fallback) | |||
| 48 | 50 | /// <summary> | |
| 49 | 51 | /// Gets substring after last occurrence of <paramref name="symbol"/> | |
| 50 | 52 | /// </summary> | |
| 51 | - internal static string AfterLast(this string str, char symbol) | ||
| 53 | + internal static string? AfterLast(this string str, char symbol) | ||
| 52 | 54 | { | |
| 53 | 55 | if (str is null) | |
| 54 | 56 | throw new ArgumentNullException(nameof(str)); | |
| 55 | 57 | ||
| 56 | 58 | int last = str.LastIndexOf(symbol); | |
| 57 | 59 | return last >= 0 ? str.Substring(last + 1) : null; | |
| 58 | 60 | } | |
| 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 | + } | ||
| 59 | 71 | } | |
| 60 | 72 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -395,7 +395,6 @@ static int ClearImpl(IntPtr ob, ManagedType self) | |||
| 395 | 395 | ||
| 396 | 396 | ClearObjectDict(ob); | |
| 397 | 397 | } | |
| 398 | - if (self is not null) self.tpHandle = IntPtr.Zero; | ||
| 399 | 398 | return 0; | |
| 400 | 399 | } | |
| 401 | 400 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments