diff --git a/src/embed_tests/TestConverter.cs b/src/embed_tests/TestConverter.cs
index 40219973b..875adf8ef 100644
--- a/src/embed_tests/TestConverter.cs
+++ b/src/embed_tests/TestConverter.cs
@@ -1,12 +1,27 @@
using System;
using System.Collections.Generic;
+using System.Linq;
+
using NUnit.Framework;
+
using Python.Runtime;
+using PyRuntime = Python.Runtime.Runtime;
+
namespace Python.EmbeddingTest
{
public class TestConverter
{
+ static readonly Type[] _numTypes = new Type[]
+ {
+ typeof(short),
+ typeof(ushort),
+ typeof(int),
+ typeof(uint),
+ typeof(long),
+ typeof(ulong)
+ };
+
[OneTimeSetUp]
public void SetUp()
{
@@ -47,6 +62,60 @@ public void TestConvertDoubleToManaged(
Assert.IsTrue(((double) convertedValue).Equals(testValue));
}
+ [Test]
+ public void CovertTypeError()
+ {
+ Type[] floatTypes = new Type[]
+ {
+ typeof(float),
+ typeof(double)
+ };
+ using (var s = new PyString("abc"))
+ {
+ foreach (var type in _numTypes.Union(floatTypes))
+ {
+ object value;
+ try
+ {
+ bool res = Converter.ToManaged(s.Handle, type, out value, true);
+ Assert.IsFalse(res);
+ var bo = Exceptions.ExceptionMatches(Exceptions.TypeError);
+ Assert.IsTrue(Exceptions.ExceptionMatches(Exceptions.TypeError)
+ || Exceptions.ExceptionMatches(Exceptions.ValueError));
+ }
+ finally
+ {
+ Exceptions.Clear();
+ }
+ }
+ }
+ }
+
+ [Test]
+ public void ConvertOverflow()
+ {
+ using (var num = new PyLong(ulong.MaxValue))
+ {
+ IntPtr largeNum = PyRuntime.PyNumber_Add(num.Handle, num.Handle);
+ try
+ {
+ object value;
+ foreach (var type in _numTypes)
+ {
+ bool res = Converter.ToManaged(largeNum, type, out value, true);
+ Assert.IsFalse(res);
+ Assert.IsTrue(Exceptions.ExceptionMatches(Exceptions.OverflowError));
+ Exceptions.Clear();
+ }
+ }
+ finally
+ {
+ Exceptions.Clear();
+ PyRuntime.XDecref(largeNum);
+ }
+ }
+ }
+
[Test]
public void RawListProxy()
{
diff --git a/src/runtime/NewReference.cs b/src/runtime/NewReference.cs
index 6e66232d0..89d53bb36 100644
--- a/src/runtime/NewReference.cs
+++ b/src/runtime/NewReference.cs
@@ -27,14 +27,18 @@ public PyObject MoveToPyObject()
this.pointer = IntPtr.Zero;
return result;
}
+
///
/// Removes this reference to a Python object, and sets it to null.
///
public void Dispose()
{
- if (!this.IsNull())
- Runtime.XDecref(this.pointer);
- this.pointer = IntPtr.Zero;
+ if (this.IsNull())
+ {
+ return;
+ }
+ Runtime.XDecref(pointer);
+ pointer = IntPtr.Zero;
}
///
diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs
index 734422ed0..58b372fa1 100644
--- a/src/runtime/converter.cs
+++ b/src/runtime/converter.cs
@@ -1,11 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Globalization;
-using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
-using System.ComponentModel;
namespace Python.Runtime
{
@@ -477,11 +476,9 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
///
private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError)
{
- IntPtr overflow = Exceptions.OverflowError;
TypeCode tc = Type.GetTypeCode(obType);
result = null;
- IntPtr op;
- int ival;
+ IntPtr op = IntPtr.Zero;
switch (tc)
{
@@ -495,312 +492,278 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo
return true;
case TypeCode.Int32:
- // Python3 always use PyLong API
- op = Runtime.PyNumber_Long(value);
- if (op == IntPtr.Zero)
{
- Exceptions.Clear();
- if (Exceptions.ExceptionMatches(overflow))
+ // Python3 always use PyLong API
+ long num = Runtime.PyLong_AsLongLong(value);
+ if (num == -1 && Exceptions.ErrorOccurred())
+ {
+ goto convert_error;
+ }
+ if (num > Int32.MaxValue || num < Int32.MinValue)
{
goto overflow;
}
- goto type_error;
- }
- long ll = (long)Runtime.PyLong_AsLongLong(op);
- Runtime.XDecref(op);
- if (ll == -1 && Exceptions.ErrorOccurred())
- {
- goto overflow;
- }
- if (ll > Int32.MaxValue || ll < Int32.MinValue)
- {
- goto overflow;
+ result = (int)num;
+ return true;
}
- result = (int)ll;
- return true;
case TypeCode.Boolean:
result = Runtime.PyObject_IsTrue(value) != 0;
return true;
case TypeCode.Byte:
- if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
{
- if (Runtime.PyBytes_Size(value) == 1)
+ if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
{
- op = Runtime.PyBytes_AS_STRING(value);
- result = (byte)Marshal.ReadByte(op);
- return true;
+ if (Runtime.PyBytes_Size(value) == 1)
+ {
+ op = Runtime.PyBytes_AS_STRING(value);
+ result = (byte)Marshal.ReadByte(op);
+ return true;
+ }
+ goto type_error;
}
- goto type_error;
- }
- op = Runtime.PyNumber_Int(value);
- if (op == IntPtr.Zero)
- {
- if (Exceptions.ExceptionMatches(overflow))
+ int num = Runtime.PyLong_AsLong(value);
+ if (num == -1 && Exceptions.ErrorOccurred())
+ {
+ goto convert_error;
+ }
+ if (num > Byte.MaxValue || num < Byte.MinValue)
{
goto overflow;
}
- goto type_error;
+ result = (byte)num;
+ return true;
}
- ival = (int)Runtime.PyInt_AsLong(op);
- Runtime.XDecref(op);
-
- if (ival > Byte.MaxValue || ival < Byte.MinValue)
- {
- goto overflow;
- }
- byte b = (byte)ival;
- result = b;
- return true;
case TypeCode.SByte:
- if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
{
- if (Runtime.PyBytes_Size(value) == 1)
+ if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
{
- op = Runtime.PyBytes_AS_STRING(value);
- result = (byte)Marshal.ReadByte(op);
- return true;
+ if (Runtime.PyBytes_Size(value) == 1)
+ {
+ op = Runtime.PyBytes_AS_STRING(value);
+ result = (byte)Marshal.ReadByte(op);
+ return true;
+ }
+ goto type_error;
}
- goto type_error;
- }
- op = Runtime.PyNumber_Int(value);
- if (op == IntPtr.Zero)
- {
- if (Exceptions.ExceptionMatches(overflow))
+ int num = Runtime.PyLong_AsLong(value);
+ if (num == -1 && Exceptions.ErrorOccurred())
+ {
+ goto convert_error;
+ }
+ if (num > SByte.MaxValue || num < SByte.MinValue)
{
goto overflow;
}
- goto type_error;
- }
- ival = (int)Runtime.PyInt_AsLong(op);
- Runtime.XDecref(op);
-
- if (ival > SByte.MaxValue || ival < SByte.MinValue)
- {
- goto overflow;
+ result = (sbyte)num;
+ return true;
}
- sbyte sb = (sbyte)ival;
- result = sb;
- return true;
case TypeCode.Char:
- if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
{
- if (Runtime.PyBytes_Size(value) == 1)
+ if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
{
- op = Runtime.PyBytes_AS_STRING(value);
- result = (byte)Marshal.ReadByte(op);
- return true;
+ if (Runtime.PyBytes_Size(value) == 1)
+ {
+ op = Runtime.PyBytes_AS_STRING(value);
+ result = (byte)Marshal.ReadByte(op);
+ return true;
+ }
+ goto type_error;
}
- goto type_error;
- }
- else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
- {
- if (Runtime.PyUnicode_GetSize(value) == 1)
+ else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
{
- op = Runtime.PyUnicode_AsUnicode(value);
- Char[] buff = new Char[1];
- Marshal.Copy(op, buff, 0, 1);
- result = buff[0];
- return true;
+ if (Runtime.PyUnicode_GetSize(value) == 1)
+ {
+ op = Runtime.PyUnicode_AsUnicode(value);
+ Char[] buff = new Char[1];
+ Marshal.Copy(op, buff, 0, 1);
+ result = buff[0];
+ return true;
+ }
+ goto type_error;
}
- goto type_error;
- }
-
- op = Runtime.PyNumber_Int(value);
- if (op == IntPtr.Zero)
- {
- goto type_error;
- }
- ival = Runtime.PyInt_AsLong(op);
- Runtime.XDecref(op);
- if (ival > Char.MaxValue || ival < Char.MinValue)
- {
- goto overflow;
+ int num = Runtime.PyLong_AsLong(value);
+ if (num == -1 && Exceptions.ErrorOccurred())
+ {
+ goto convert_error;
+ }
+ if (num > Char.MaxValue || num < Char.MinValue)
+ {
+ goto overflow;
+ }
+ result = (char)num;
+ return true;
}
- result = (char)ival;
- return true;
case TypeCode.Int16:
- op = Runtime.PyNumber_Int(value);
- if (op == IntPtr.Zero)
{
- if (Exceptions.ExceptionMatches(overflow))
+ int num = Runtime.PyLong_AsLong(value);
+ if (num == -1 && Exceptions.ErrorOccurred())
+ {
+ goto convert_error;
+ }
+ if (num > Int16.MaxValue || num < Int16.MinValue)
{
goto overflow;
}
- goto type_error;
- }
- ival = (int)Runtime.PyInt_AsLong(op);
- Runtime.XDecref(op);
- if (ival > Int16.MaxValue || ival < Int16.MinValue)
- {
- goto overflow;
+ result = (short)num;
+ return true;
}
- short s = (short)ival;
- result = s;
- return true;
case TypeCode.Int64:
- op = Runtime.PyNumber_Long(value);
- if (op == IntPtr.Zero)
{
- if (Exceptions.ExceptionMatches(overflow))
+ long num = (long)Runtime.PyLong_AsLongLong(value);
+ if (num == -1 && Exceptions.ErrorOccurred())
{
- goto overflow;
+ goto convert_error;
}
- goto type_error;
- }
- long l = (long)Runtime.PyLong_AsLongLong(op);
- Runtime.XDecref(op);
- if ((l == -1) && Exceptions.ErrorOccurred())
- {
- goto overflow;
+ result = num;
+ return true;
}
- result = l;
- return true;
case TypeCode.UInt16:
- op = Runtime.PyNumber_Int(value);
- if (op == IntPtr.Zero)
{
- if (Exceptions.ExceptionMatches(overflow))
+ long num = Runtime.PyLong_AsLong(value);
+ if (num == -1 && Exceptions.ErrorOccurred())
+ {
+ goto convert_error;
+ }
+ if (num > UInt16.MaxValue || num < UInt16.MinValue)
{
goto overflow;
}
- goto type_error;
- }
- ival = (int)Runtime.PyInt_AsLong(op);
- Runtime.XDecref(op);
- if (ival > UInt16.MaxValue || ival < UInt16.MinValue)
- {
- goto overflow;
+ result = (ushort)num;
+ return true;
}
- ushort us = (ushort)ival;
- result = us;
- return true;
case TypeCode.UInt32:
- op = Runtime.PyNumber_Long(value);
- if (op == IntPtr.Zero)
{
- if (Exceptions.ExceptionMatches(overflow))
+ op = value;
+ if (Runtime.PyObject_TYPE(value) != Runtime.PyLongType)
{
- goto overflow;
+ op = Runtime.PyNumber_Long(value);
+ if (op == IntPtr.Zero)
+ {
+ goto convert_error;
+ }
}
- goto type_error;
- }
-
- uint ui;
- try
- {
- ui = Convert.ToUInt32(Runtime.PyLong_AsUnsignedLong(op));
- } catch (OverflowException)
- {
- // Probably wasn't an overflow in python but was in C# (e.g. if cpython
- // longs are 64 bit then 0xFFFFFFFF + 1 will not overflow in
- // PyLong_AsUnsignedLong)
- Runtime.XDecref(op);
- goto overflow;
- }
-
-
- if (Exceptions.ErrorOccurred())
- {
- Runtime.XDecref(op);
- goto overflow;
- }
-
- IntPtr check = Runtime.PyLong_FromUnsignedLong(ui);
- int err = Runtime.PyObject_Compare(check, op);
- Runtime.XDecref(check);
- Runtime.XDecref(op);
- if (0 != err || Exceptions.ErrorOccurred())
- {
- goto overflow;
+ if (Runtime.Is32Bit || Runtime.IsWindows)
+ {
+ uint num = Runtime.PyLong_AsUnsignedLong32(op);
+ if (num == uint.MaxValue && Exceptions.ErrorOccurred())
+ {
+ goto convert_error;
+ }
+ result = num;
+ }
+ else
+ {
+ ulong num = Runtime.PyLong_AsUnsignedLong64(op);
+ if (num == ulong.MaxValue && Exceptions.ErrorOccurred())
+ {
+ goto convert_error;
+ }
+ try
+ {
+ result = Convert.ToUInt32(num);
+ }
+ catch (OverflowException)
+ {
+ // Probably wasn't an overflow in python but was in C# (e.g. if cpython
+ // longs are 64 bit then 0xFFFFFFFF + 1 will not overflow in
+ // PyLong_AsUnsignedLong)
+ goto overflow;
+ }
+ }
+ return true;
}
- result = ui;
- return true;
-
case TypeCode.UInt64:
- op = Runtime.PyNumber_Long(value);
- if (op == IntPtr.Zero)
{
- if (Exceptions.ExceptionMatches(overflow))
+ op = value;
+ if (Runtime.PyObject_TYPE(value) != Runtime.PyLongType)
+ {
+ op = Runtime.PyNumber_Long(value);
+ if (op == IntPtr.Zero)
+ {
+ goto convert_error;
+ }
+ }
+ ulong num = Runtime.PyLong_AsUnsignedLongLong(op);
+ if (num == ulong.MaxValue && Exceptions.ErrorOccurred())
{
goto overflow;
}
- goto type_error;
- }
- ulong ul = (ulong)Runtime.PyLong_AsUnsignedLongLong(op);
- Runtime.XDecref(op);
- if (Exceptions.ErrorOccurred())
- {
- goto overflow;
+ result = num;
+ return true;
}
- result = ul;
- return true;
-
case TypeCode.Single:
- op = Runtime.PyNumber_Float(value);
- if (op == IntPtr.Zero)
{
- if (Exceptions.ExceptionMatches(overflow))
+ double num = Runtime.PyFloat_AsDouble(value);
+ if (num == -1.0 && Exceptions.ErrorOccurred())
{
- goto overflow;
+ goto convert_error;
}
- goto type_error;
- }
- double dd = Runtime.PyFloat_AsDouble(op);
- Runtime.CheckExceptionOccurred();
- Runtime.XDecref(op);
- if (dd > Single.MaxValue || dd < Single.MinValue)
- {
- if (!double.IsInfinity(dd))
+ if (num > Single.MaxValue || num < Single.MinValue)
{
- goto overflow;
+ if (!double.IsInfinity(num))
+ {
+ goto overflow;
+ }
}
+ result = (float)num;
+ return true;
}
- result = (float)dd;
- return true;
case TypeCode.Double:
- op = Runtime.PyNumber_Float(value);
- if (op == IntPtr.Zero)
{
- goto type_error;
+ double num = Runtime.PyFloat_AsDouble(value);
+ if (num == -1.0 && Exceptions.ErrorOccurred())
+ {
+ goto convert_error;
+ }
+ result = num;
+ return true;
}
- double d = Runtime.PyFloat_AsDouble(op);
- Runtime.CheckExceptionOccurred();
- Runtime.XDecref(op);
- result = d;
- return true;
+ default:
+ goto type_error;
}
+ convert_error:
+ if (op != value)
+ {
+ Runtime.XDecref(op);
+ }
+ if (!setError)
+ {
+ Exceptions.Clear();
+ }
+ return false;
- type_error:
-
+ type_error:
if (setError)
{
string tpName = Runtime.PyObject_GetTypeName(value);
Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
}
-
return false;
- overflow:
-
+ overflow:
+ // C# level overflow error
+ if (op != value)
+ {
+ Runtime.XDecref(op);
+ }
if (setError)
{
Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
}
-
return false;
}
diff --git a/src/runtime/pyansistring.cs b/src/runtime/pyansistring.cs
index 3d1d6ab68..185cc6c94 100644
--- a/src/runtime/pyansistring.cs
+++ b/src/runtime/pyansistring.cs
@@ -45,7 +45,7 @@ public PyAnsiString(PyObject o)
public PyAnsiString(string s)
{
obj = Runtime.PyString_FromString(s);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
diff --git a/src/runtime/pyfloat.cs b/src/runtime/pyfloat.cs
index edfaca542..d6fb55f26 100644
--- a/src/runtime/pyfloat.cs
+++ b/src/runtime/pyfloat.cs
@@ -51,7 +51,7 @@ public PyFloat(PyObject o)
public PyFloat(double value)
{
obj = Runtime.PyFloat_FromDouble(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -66,7 +66,7 @@ public PyFloat(string value)
using (var s = new PyString(value))
{
obj = Runtime.PyFloat_FromString(s.obj, IntPtr.Zero);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
}
@@ -94,7 +94,7 @@ public static bool IsFloatType(PyObject value)
public static PyFloat AsFloat(PyObject value)
{
IntPtr op = Runtime.PyNumber_Float(value.obj);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(op);
return new PyFloat(op);
}
}
diff --git a/src/runtime/pyint.cs b/src/runtime/pyint.cs
index 217cf7e20..31295c899 100644
--- a/src/runtime/pyint.cs
+++ b/src/runtime/pyint.cs
@@ -51,7 +51,7 @@ public PyInt(PyObject o)
public PyInt(int value)
{
obj = Runtime.PyInt_FromInt32(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -65,7 +65,7 @@ public PyInt(int value)
public PyInt(uint value)
{
obj = Runtime.PyInt_FromInt64(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -78,7 +78,7 @@ public PyInt(uint value)
public PyInt(long value)
{
obj = Runtime.PyInt_FromInt64(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -92,7 +92,7 @@ public PyInt(long value)
public PyInt(ulong value)
{
obj = Runtime.PyInt_FromInt64((long)value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -151,7 +151,7 @@ public PyInt(sbyte value) : this((int)value)
public PyInt(string value)
{
obj = Runtime.PyInt_FromString(value, IntPtr.Zero, 0);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -178,7 +178,7 @@ public static bool IsIntType(PyObject value)
public static PyInt AsInt(PyObject value)
{
IntPtr op = Runtime.PyNumber_Int(value.obj);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(op);
return new PyInt(op);
}
diff --git a/src/runtime/pylong.cs b/src/runtime/pylong.cs
index 286af40df..fc101105f 100644
--- a/src/runtime/pylong.cs
+++ b/src/runtime/pylong.cs
@@ -51,7 +51,7 @@ public PyLong(PyObject o)
public PyLong(int value)
{
obj = Runtime.PyLong_FromLong(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -65,7 +65,7 @@ public PyLong(int value)
public PyLong(uint value)
{
obj = Runtime.PyLong_FromLong(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -78,7 +78,7 @@ public PyLong(uint value)
public PyLong(long value)
{
obj = Runtime.PyLong_FromLongLong(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -92,7 +92,7 @@ public PyLong(long value)
public PyLong(ulong value)
{
obj = Runtime.PyLong_FromUnsignedLongLong(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -105,7 +105,7 @@ public PyLong(ulong value)
public PyLong(short value)
{
obj = Runtime.PyLong_FromLong(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -119,7 +119,7 @@ public PyLong(short value)
public PyLong(ushort value)
{
obj = Runtime.PyLong_FromLong(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -132,7 +132,7 @@ public PyLong(ushort value)
public PyLong(byte value)
{
obj = Runtime.PyLong_FromLong(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -146,7 +146,7 @@ public PyLong(byte value)
public PyLong(sbyte value)
{
obj = Runtime.PyLong_FromLong(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -159,7 +159,7 @@ public PyLong(sbyte value)
public PyLong(double value)
{
obj = Runtime.PyLong_FromDouble(value);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -172,7 +172,7 @@ public PyLong(double value)
public PyLong(string value)
{
obj = Runtime.PyLong_FromString(value, IntPtr.Zero, 0);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -199,7 +199,7 @@ public static bool IsLongType(PyObject value)
public static PyLong AsLong(PyObject value)
{
IntPtr op = Runtime.PyNumber_Long(value.obj);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(op);
return new PyLong(op);
}
diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs
index 8738824f5..9b9c78bae 100644
--- a/src/runtime/pyscope.cs
+++ b/src/runtime/pyscope.cs
@@ -66,12 +66,13 @@ internal PyScope(IntPtr ptr, PyScopeManager manager)
obj = ptr;
//Refcount of the variables not increase
variables = Runtime.PyModule_GetDict(obj);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(variables);
- Runtime.PyDict_SetItemString(
+ int res = Runtime.PyDict_SetItemString(
variables, "__builtins__",
Runtime.PyEval_GetBuiltins()
);
+ PythonException.ThrowIfIsNotZero(res);
this.Name = this.Get("__name__");
}
@@ -237,7 +238,7 @@ public PyObject Execute(PyObject script, PyDict locals = null)
Check();
IntPtr _locals = locals == null ? variables : locals.obj;
IntPtr ptr = Runtime.PyEval_EvalCode(script.Handle, variables, _locals);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(ptr);
if (ptr == Runtime.PyNone)
{
Runtime.XDecref(ptr);
@@ -282,15 +283,8 @@ public PyObject Eval(string code, PyDict locals = null)
NewReference reference = Runtime.PyRun_String(
code, flag, variables, _locals
);
- try
- {
- Runtime.CheckExceptionOccurred();
- return reference.MoveToPyObject();
- }
- finally
- {
- reference.Dispose();
- }
+ PythonException.ThrowIfIsNull(reference);
+ return reference.MoveToPyObject();
}
///
@@ -327,19 +321,8 @@ private void Exec(string code, IntPtr _globals, IntPtr _locals)
NewReference reference = Runtime.PyRun_String(
code, flag, _globals, _locals
);
-
- try
- {
- Runtime.CheckExceptionOccurred();
- if (!reference.IsNone())
- {
- throw new PythonException();
- }
- }
- finally
- {
- reference.Dispose();
- }
+ PythonException.ThrowIfIsNull(reference);
+ reference.Dispose();
}
///
diff --git a/src/runtime/pystring.cs b/src/runtime/pystring.cs
index c9c4f9f5b..cb18024c5 100644
--- a/src/runtime/pystring.cs
+++ b/src/runtime/pystring.cs
@@ -54,7 +54,7 @@ public PyString(PyObject o)
public PyString(string s)
{
obj = Runtime.PyUnicode_FromUnicode(s, s.Length);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs
index 4f77bec1d..38ef2ee48 100644
--- a/src/runtime/pythonengine.cs
+++ b/src/runtime/pythonengine.cs
@@ -465,7 +465,7 @@ public static void EndAllowThreads(IntPtr ts)
public static PyObject ImportModule(string name)
{
IntPtr op = Runtime.PyImport_ImportModule(name);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(op);
return new PyObject(op);
}
@@ -480,7 +480,7 @@ public static PyObject ImportModule(string name)
public static PyObject ReloadModule(PyObject module)
{
IntPtr op = Runtime.PyImport_ReloadModule(module.Handle);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(op);
return new PyObject(op);
}
@@ -495,9 +495,9 @@ public static PyObject ReloadModule(PyObject module)
public static PyObject ModuleFromString(string name, string code)
{
IntPtr c = Runtime.Py_CompileString(code, "none", (int)RunFlagType.File);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(c);
IntPtr m = Runtime.PyImport_ExecCodeModule(name, c);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(m);
return new PyObject(m);
}
@@ -505,7 +505,7 @@ public static PyObject Compile(string code, string filename = "", RunFlagType mo
{
var flag = (int)mode;
IntPtr ptr = Runtime.Py_CompileString(code, filename, flag);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(ptr);
return new PyObject(ptr);
}
@@ -587,17 +587,8 @@ internal static PyObject RunString(string code, IntPtr? globals, IntPtr? locals,
NewReference result = Runtime.PyRun_String(
code, (IntPtr)flag, globals.Value, locals.Value
);
-
- try
- {
- Runtime.CheckExceptionOccurred();
-
- return result.MoveToPyObject();
- }
- finally
- {
- result.Dispose();
- }
+ PythonException.ThrowIfIsNull(result);
+ return result.MoveToPyObject();
}
finally
{
diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs
index 8efdccc91..b69ac34e4 100644
--- a/src/runtime/pythonexception.cs
+++ b/src/runtime/pythonexception.cs
@@ -253,6 +253,14 @@ public static void ThrowIfIsNull(IntPtr ob)
}
}
+ internal static void ThrowIfIsNull(BorrowedReference reference)
+ {
+ if (reference.IsNull)
+ {
+ throw new PythonException();
+ }
+ }
+
public static void ThrowIfIsNotZero(int value)
{
if (value != 0)
diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs
index 45f3d8350..e534ff5d5 100644
--- a/src/runtime/pytuple.cs
+++ b/src/runtime/pytuple.cs
@@ -51,7 +51,7 @@ public PyTuple(PyObject o)
public PyTuple()
{
obj = Runtime.PyTuple_New(0);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(obj);
}
@@ -72,8 +72,8 @@ public PyTuple(PyObject[] items)
{
IntPtr ptr = items[i].obj;
Runtime.XIncref(ptr);
- Runtime.PyTuple_SetItem(obj, i, ptr);
- Runtime.CheckExceptionOccurred();
+ int res = Runtime.PyTuple_SetItem(obj, i, ptr);
+ PythonException.ThrowIfIsNotZero(res);
}
}
@@ -101,7 +101,7 @@ public static bool IsTupleType(PyObject value)
public static PyTuple AsTuple(PyObject value)
{
IntPtr op = Runtime.PySequence_Tuple(value.obj);
- Runtime.CheckExceptionOccurred();
+ PythonException.ThrowIfIsNull(op);
return new PyTuple(op);
}
}
diff --git a/src/tests/test_conversion.py b/src/tests/test_conversion.py
index 74613abd1..313274647 100644
--- a/src/tests/test_conversion.py
+++ b/src/tests/test_conversion.py
@@ -343,7 +343,7 @@ def test_uint32_conversion():
ob.UInt32Field = System.UInt32(0)
assert ob.UInt32Field == 0
- with pytest.raises(TypeError):
+ with pytest.raises(ValueError):
ConversionTest().UInt32Field = "spam"
with pytest.raises(TypeError):
@@ -382,7 +382,7 @@ def test_uint64_conversion():
ob.UInt64Field = System.UInt64(0)
assert ob.UInt64Field == 0
- with pytest.raises(TypeError):
+ with pytest.raises(ValueError):
ConversionTest().UInt64Field = "spam"
with pytest.raises(TypeError):