diff --git a/CHANGELOG.md b/CHANGELOG.md
index db73bb629..8ba1594ca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
- `clr.AddReference` may now throw errors besides `FileNotFoundException`, that provide more
details about the cause of the failure
- `clr.AddReference` no longer adds ".dll" implicitly
+- `PyIter(PyObject)` constructor replaced with static `PyIter.GetIter(PyObject)` method
### Fixed
diff --git a/src/runtime/pyansistring.cs b/src/runtime/pyansistring.cs
index 185cc6c94..8a27104b1 100644
--- a/src/runtime/pyansistring.cs
+++ b/src/runtime/pyansistring.cs
@@ -17,6 +17,16 @@ public PyAnsiString(IntPtr ptr) : base(ptr)
}
+ private static IntPtr FromObject(PyObject o)
+ {
+ if (o == null || !IsStringType(o))
+ {
+ throw new ArgumentException("object is not a string");
+ }
+ Runtime.XIncref(o.obj);
+ return o.obj;
+ }
+
///
/// PyString Constructor
///
@@ -25,14 +35,14 @@ public PyAnsiString(IntPtr ptr) : base(ptr)
/// An ArgumentException will be thrown if the given object is not
/// a Python string object.
///
- public PyAnsiString(PyObject o)
+ public PyAnsiString(PyObject o) : base(FromObject(o))
{
- if (!IsStringType(o))
- {
- throw new ArgumentException("object is not a string");
- }
- Runtime.XIncref(o.obj);
- obj = o.obj;
+ }
+ private static IntPtr FromString(string s)
+ {
+ IntPtr val = Runtime.PyString_FromString(s);
+ PythonException.ThrowIfIsNull(val);
+ return val;
}
@@ -42,10 +52,8 @@ public PyAnsiString(PyObject o)
///
/// Creates a Python string from a managed string.
///
- public PyAnsiString(string s)
+ public PyAnsiString(string s) : base(FromString(s))
{
- obj = Runtime.PyString_FromString(s);
- PythonException.ThrowIfIsNull(obj);
}
diff --git a/src/runtime/pydict.cs b/src/runtime/pydict.cs
index 7ff7a83c8..ade873f7a 100644
--- a/src/runtime/pydict.cs
+++ b/src/runtime/pydict.cs
@@ -29,9 +29,8 @@ public PyDict(IntPtr ptr) : base(ptr)
///
/// Creates a new Python dictionary object.
///
- public PyDict()
+ public PyDict() : base(Runtime.PyDict_New())
{
- obj = Runtime.PyDict_New();
if (obj == IntPtr.Zero)
{
throw new PythonException();
@@ -47,14 +46,13 @@ public PyDict()
/// ArgumentException will be thrown if the given object is not a
/// Python dictionary object.
///
- public PyDict(PyObject o)
+ public PyDict(PyObject o) : base(o.obj)
{
+ Runtime.XIncref(o.obj);
if (!IsDictType(o))
{
throw new ArgumentException("object is not a dict");
}
- Runtime.XIncref(o.obj);
- obj = o.obj;
}
diff --git a/src/runtime/pyfloat.cs b/src/runtime/pyfloat.cs
index d6fb55f26..b07b95de1 100644
--- a/src/runtime/pyfloat.cs
+++ b/src/runtime/pyfloat.cs
@@ -4,7 +4,6 @@ namespace Python.Runtime
{
///
/// Represents a Python float object. See the documentation at
- /// PY2: https://docs.python.org/2/c-api/float.html
/// PY3: https://docs.python.org/3/c-api/float.html
/// for details.
///
@@ -31,14 +30,8 @@ public PyFloat(IntPtr ptr) : base(ptr)
/// ArgumentException will be thrown if the given object is not a
/// Python float object.
///
- public PyFloat(PyObject o)
+ public PyFloat(PyObject o) : base(FromObject(o))
{
- if (!IsFloatType(o))
- {
- throw new ArgumentException("object is not a float");
- }
- Runtime.XIncref(o.obj);
- obj = o.obj;
}
@@ -48,12 +41,36 @@ public PyFloat(PyObject o)
///
/// Creates a new Python float from a double value.
///
- public PyFloat(double value)
+ public PyFloat(double value) : base(FromDouble(value))
+ {
+ }
+
+ private static IntPtr FromObject(PyObject o)
+ {
+ if (o == null || !IsFloatType(o))
+ {
+ throw new ArgumentException("object is not a float");
+ }
+ Runtime.XIncref(o.obj);
+ return o.obj;
+ }
+
+ private static IntPtr FromDouble(double value)
{
- obj = Runtime.PyFloat_FromDouble(value);
- PythonException.ThrowIfIsNull(obj);
+ IntPtr val = Runtime.PyFloat_FromDouble(value);
+ PythonException.ThrowIfIsNull(val);
+ return val;
}
+ private static IntPtr FromString(string value)
+ {
+ using (var s = new PyString(value))
+ {
+ IntPtr val = Runtime.PyFloat_FromString(s.obj, IntPtr.Zero);
+ PythonException.ThrowIfIsNull(val);
+ return val;
+ }
+ }
///
/// PyFloat Constructor
@@ -61,13 +78,8 @@ public PyFloat(double value)
///
/// Creates a new Python float from a string value.
///
- public PyFloat(string value)
+ public PyFloat(string value) : base(FromString(value))
{
- using (var s = new PyString(value))
- {
- obj = Runtime.PyFloat_FromString(s.obj, IntPtr.Zero);
- PythonException.ThrowIfIsNull(obj);
- }
}
diff --git a/src/runtime/pyint.cs b/src/runtime/pyint.cs
index 31295c899..e49e62a8a 100644
--- a/src/runtime/pyint.cs
+++ b/src/runtime/pyint.cs
@@ -31,16 +31,26 @@ public PyInt(IntPtr ptr) : base(ptr)
/// ArgumentException will be thrown if the given object is not a
/// Python int object.
///
- public PyInt(PyObject o)
+ public PyInt(PyObject o) : base(FromObject(o))
{
- if (!IsIntType(o))
+ }
+
+ private static IntPtr FromObject(PyObject o)
+ {
+ if (o == null || !IsIntType(o))
{
throw new ArgumentException("object is not an int");
}
Runtime.XIncref(o.obj);
- obj = o.obj;
+ return o.obj;
}
+ private static IntPtr FromInt(int value)
+ {
+ IntPtr val = Runtime.PyInt_FromInt32(value);
+ PythonException.ThrowIfIsNull(val);
+ return val;
+ }
///
/// PyInt Constructor
@@ -48,10 +58,8 @@ public PyInt(PyObject o)
///
/// Creates a new Python int from an int32 value.
///
- public PyInt(int value)
+ public PyInt(int value) : base(FromInt(value))
{
- obj = Runtime.PyInt_FromInt32(value);
- PythonException.ThrowIfIsNull(obj);
}
@@ -62,10 +70,8 @@ public PyInt(int value)
/// Creates a new Python int from a uint32 value.
///
[CLSCompliant(false)]
- public PyInt(uint value)
+ public PyInt(uint value) : base(FromLong(value))
{
- obj = Runtime.PyInt_FromInt64(value);
- PythonException.ThrowIfIsNull(obj);
}
@@ -75,10 +81,15 @@ public PyInt(uint value)
///
/// Creates a new Python int from an int64 value.
///
- public PyInt(long value)
+ public PyInt(long value) : base(FromLong(value))
{
- obj = Runtime.PyInt_FromInt64(value);
- PythonException.ThrowIfIsNull(obj);
+ }
+
+ private static IntPtr FromLong(long value)
+ {
+ IntPtr val = Runtime.PyInt_FromInt64(value);
+ PythonException.ThrowIfIsNull(val);
+ return val;
}
@@ -89,10 +100,8 @@ public PyInt(long value)
/// Creates a new Python int from a uint64 value.
///
[CLSCompliant(false)]
- public PyInt(ulong value)
+ public PyInt(ulong value) : base(FromLong((long)value))
{
- obj = Runtime.PyInt_FromInt64((long)value);
- PythonException.ThrowIfIsNull(obj);
}
@@ -142,16 +151,21 @@ public PyInt(sbyte value) : this((int)value)
}
+ private static IntPtr FromString(string value)
+ {
+ IntPtr val = Runtime.PyInt_FromString(value, IntPtr.Zero, 0);
+ PythonException.ThrowIfIsNull(val);
+ return val;
+ }
+
///
/// PyInt Constructor
///
///
/// Creates a new Python int from a string value.
///
- public PyInt(string value)
+ public PyInt(string value) : base(FromString(value))
{
- obj = Runtime.PyInt_FromString(value, IntPtr.Zero, 0);
- PythonException.ThrowIfIsNull(obj);
}
diff --git a/src/runtime/pyiter.cs b/src/runtime/pyiter.cs
index ee07bcecf..4ad761db7 100644
--- a/src/runtime/pyiter.cs
+++ b/src/runtime/pyiter.cs
@@ -26,18 +26,22 @@ public PyIter(IntPtr ptr) : base(ptr)
}
///
- /// PyIter Constructor
+ /// PyIter factory function.
///
///
- /// Creates a Python iterator from an iterable. Like doing "iter(iterable)" in python.
+ /// Create a new PyIter from a given iterable. Like doing "iter(iterable)" in python.
///
- public PyIter(PyObject iterable)
+ ///
+ ///
+ public static PyIter GetIter(PyObject iterable)
{
- obj = Runtime.PyObject_GetIter(iterable.obj);
- if (obj == IntPtr.Zero)
+ if (iterable == null)
{
- throw new PythonException();
+ throw new ArgumentNullException();
}
+ IntPtr val = Runtime.PyObject_GetIter(iterable.obj);
+ PythonException.ThrowIfIsNull(val);
+ return new PyIter(val);
}
protected override void Dispose(bool disposing)
diff --git a/src/runtime/pylist.cs b/src/runtime/pylist.cs
index 80267d81a..dcb0ea78f 100644
--- a/src/runtime/pylist.cs
+++ b/src/runtime/pylist.cs
@@ -28,6 +28,16 @@ public PyList(IntPtr ptr) : base(ptr)
internal PyList(BorrowedReference reference) : base(reference) { }
+ private static IntPtr FromObject(PyObject o)
+ {
+ if (o == null || !IsListType(o))
+ {
+ throw new ArgumentException("object is not a list");
+ }
+ Runtime.XIncref(o.obj);
+ return o.obj;
+ }
+
///
/// PyList Constructor
///
@@ -36,14 +46,8 @@ internal PyList(BorrowedReference reference) : base(reference) { }
/// ArgumentException will be thrown if the given object is not a
/// Python list object.
///
- public PyList(PyObject o)
+ public PyList(PyObject o) : base(FromObject(o))
{
- if (!IsListType(o))
- {
- throw new ArgumentException("object is not a list");
- }
- Runtime.XIncref(o.obj);
- obj = o.obj;
}
@@ -53,36 +57,40 @@ public PyList(PyObject o)
///
/// Creates a new empty Python list object.
///
- public PyList()
+ public PyList() : base(Runtime.PyList_New(0))
{
- obj = Runtime.PyList_New(0);
if (obj == IntPtr.Zero)
{
throw new PythonException();
}
}
-
- ///
- /// PyList Constructor
- ///
- ///
- /// Creates a new Python list object from an array of PyObjects.
- ///
- public PyList(PyObject[] items)
+ private static IntPtr FromArray(PyObject[] items)
{
int count = items.Length;
- obj = Runtime.PyList_New(count);
+ IntPtr val = Runtime.PyList_New(count);
for (var i = 0; i < count; i++)
{
IntPtr ptr = items[i].obj;
Runtime.XIncref(ptr);
- int r = Runtime.PyList_SetItem(obj, i, ptr);
+ int r = Runtime.PyList_SetItem(val, i, ptr);
if (r < 0)
{
+ Runtime.Py_DecRef(val);
throw new PythonException();
}
}
+ return val;
+ }
+
+ ///
+ /// PyList Constructor
+ ///
+ ///
+ /// Creates a new Python list object from an array of PyObjects.
+ ///
+ public PyList(PyObject[] items) : base(FromArray(items))
+ {
}
diff --git a/src/runtime/pylong.cs b/src/runtime/pylong.cs
index fc101105f..87cc7d2a5 100644
--- a/src/runtime/pylong.cs
+++ b/src/runtime/pylong.cs
@@ -31,16 +31,26 @@ public PyLong(IntPtr ptr) : base(ptr)
/// ArgumentException will be thrown if the given object is not a
/// Python long object.
///
- public PyLong(PyObject o)
+ public PyLong(PyObject o) : base(FromObject(o))
{
- if (!IsLongType(o))
+ }
+
+ private static IntPtr FromObject(PyObject o)
+ {
+ if (o == null || !IsLongType(o))
{
throw new ArgumentException("object is not a long");
}
Runtime.XIncref(o.obj);
- obj = o.obj;
+ return o.obj;
}
+ private static IntPtr FromInt(int value)
+ {
+ IntPtr val = Runtime.PyLong_FromLong(value);
+ PythonException.ThrowIfIsNull(val);
+ return val;
+ }
///
/// PyLong Constructor
@@ -48,10 +58,8 @@ public PyLong(PyObject o)
///
/// Creates a new PyLong from an int32 value.
///
- public PyLong(int value)
+ public PyLong(int value) : base(FromInt(value))
{
- obj = Runtime.PyLong_FromLong(value);
- PythonException.ThrowIfIsNull(obj);
}
@@ -62,25 +70,34 @@ public PyLong(int value)
/// Creates a new PyLong from a uint32 value.
///
[CLSCompliant(false)]
- public PyLong(uint value)
+ public PyLong(uint value) : base(FromInt((int)value))
{
- obj = Runtime.PyLong_FromLong(value);
- PythonException.ThrowIfIsNull(obj);
}
+ private static IntPtr FromLong(long value)
+ {
+ IntPtr val = Runtime.PyLong_FromLongLong(value);
+ PythonException.ThrowIfIsNull(val);
+ return val;
+ }
+
///
/// PyLong Constructor
///
///
/// Creates a new PyLong from an int64 value.
///
- public PyLong(long value)
+ public PyLong(long value) : base(FromLong(value))
{
- obj = Runtime.PyLong_FromLongLong(value);
- PythonException.ThrowIfIsNull(obj);
}
+ private static IntPtr FromULong(ulong value)
+ {
+ IntPtr val = Runtime.PyLong_FromUnsignedLongLong(value);
+ PythonException.ThrowIfIsNull(val);
+ return val;
+ }
///
/// PyLong Constructor
@@ -89,10 +106,8 @@ public PyLong(long value)
/// Creates a new PyLong from a uint64 value.
///
[CLSCompliant(false)]
- public PyLong(ulong value)
+ public PyLong(ulong value) : base(FromULong(value))
{
- obj = Runtime.PyLong_FromUnsignedLongLong(value);
- PythonException.ThrowIfIsNull(obj);
}
@@ -102,10 +117,8 @@ public PyLong(ulong value)
///
/// Creates a new PyLong from an int16 value.
///
- public PyLong(short value)
+ public PyLong(short value) : base(FromInt((int)value))
{
- obj = Runtime.PyLong_FromLong(value);
- PythonException.ThrowIfIsNull(obj);
}
@@ -116,10 +129,8 @@ public PyLong(short value)
/// Creates a new PyLong from an uint16 value.
///
[CLSCompliant(false)]
- public PyLong(ushort value)
+ public PyLong(ushort value) : base(FromInt((int)value))
{
- obj = Runtime.PyLong_FromLong(value);
- PythonException.ThrowIfIsNull(obj);
}
@@ -129,10 +140,8 @@ public PyLong(ushort value)
///
/// Creates a new PyLong from a byte value.
///
- public PyLong(byte value)
+ public PyLong(byte value) : base(FromInt((int)value))
{
- obj = Runtime.PyLong_FromLong(value);
- PythonException.ThrowIfIsNull(obj);
}
@@ -143,12 +152,16 @@ public PyLong(byte value)
/// Creates a new PyLong from an sbyte value.
///
[CLSCompliant(false)]
- public PyLong(sbyte value)
+ public PyLong(sbyte value) : base(FromInt((int)value))
{
- obj = Runtime.PyLong_FromLong(value);
- PythonException.ThrowIfIsNull(obj);
}
+ private static IntPtr FromDouble(double value)
+ {
+ IntPtr val = Runtime.PyLong_FromDouble(value);
+ PythonException.ThrowIfIsNull(val);
+ return val;
+ }
///
/// PyLong Constructor
@@ -156,12 +169,16 @@ public PyLong(sbyte value)
///
/// Creates a new PyLong from an double value.
///
- public PyLong(double value)
+ public PyLong(double value) : base(FromDouble(value))
{
- obj = Runtime.PyLong_FromDouble(value);
- PythonException.ThrowIfIsNull(obj);
}
+ private static IntPtr FromString(string value)
+ {
+ IntPtr val = Runtime.PyLong_FromString(value, IntPtr.Zero, 0);
+ PythonException.ThrowIfIsNull(val);
+ return val;
+ }
///
/// PyLong Constructor
@@ -169,10 +186,8 @@ public PyLong(double value)
///
/// Creates a new PyLong from a string value.
///
- public PyLong(string value)
+ public PyLong(string value) : base(FromString(value))
{
- obj = Runtime.PyLong_FromString(value, IntPtr.Zero, 0);
- PythonException.ThrowIfIsNull(obj);
}
diff --git a/src/runtime/pynumber.cs b/src/runtime/pynumber.cs
index 4f7373a8c..1af67b4e0 100644
--- a/src/runtime/pynumber.cs
+++ b/src/runtime/pynumber.cs
@@ -5,7 +5,6 @@ namespace Python.Runtime
///
/// Represents a generic Python number. The methods of this class are
/// equivalent to the Python "abstract number API". See
- /// PY2: https://docs.python.org/2/c-api/number.html
/// PY3: https://docs.python.org/3/c-api/number.html
/// for details.
///
@@ -18,11 +17,6 @@ protected PyNumber(IntPtr ptr) : base(ptr)
{
}
- protected PyNumber()
- {
- }
-
-
///
/// IsNumberType Method
///
diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs
index f456fd69d..a7f5e8305 100644
--- a/src/runtime/pyobject.cs
+++ b/src/runtime/pyobject.cs
@@ -69,17 +69,6 @@ internal PyObject(BorrowedReference reference)
#endif
}
- // Protected default constructor to allow subclasses to manage
- // initialization in different ways as appropriate.
- [Obsolete("Please, always use PyObject(*Reference)")]
- protected PyObject()
- {
- Finalizer.Instance.ThrottledCollect();
-#if TRACE_ALLOC
- Traceback = new StackTrace(1);
-#endif
- }
-
// Ensure that encapsulated Python object is decref'ed appropriately
// when the managed wrapper is garbage-collected.
~PyObject()
@@ -710,7 +699,7 @@ public PyObject GetIterator()
///
public IEnumerator GetEnumerator()
{
- return new PyIter(this);
+ return PyIter.GetIter(this);
}
diff --git a/src/runtime/pysequence.cs b/src/runtime/pysequence.cs
index 8df13f737..1850ef7de 100644
--- a/src/runtime/pysequence.cs
+++ b/src/runtime/pysequence.cs
@@ -18,10 +18,6 @@ protected PySequence(IntPtr ptr) : base(ptr)
internal PySequence(BorrowedReference reference) : base(reference) { }
- protected PySequence()
- {
- }
-
///
/// IsSequenceType Method
diff --git a/src/runtime/pystring.cs b/src/runtime/pystring.cs
index cb18024c5..b3d0dc86d 100644
--- a/src/runtime/pystring.cs
+++ b/src/runtime/pystring.cs
@@ -26,6 +26,16 @@ public PyString(IntPtr ptr) : base(ptr)
}
+ private static IntPtr FromObject(PyObject o)
+ {
+ if (o == null || !IsStringType(o))
+ {
+ throw new ArgumentException("object is not a string");
+ }
+ Runtime.XIncref(o.obj);
+ return o.obj;
+ }
+
///
/// PyString Constructor
///
@@ -34,27 +44,25 @@ public PyString(IntPtr ptr) : base(ptr)
/// An ArgumentException will be thrown if the given object is not
/// a Python string object.
///
- public PyString(PyObject o)
+ public PyString(PyObject o) : base(FromObject(o))
{
- if (!IsStringType(o))
- {
- throw new ArgumentException("object is not a string");
- }
- Runtime.XIncref(o.obj);
- obj = o.obj;
}
+ private static IntPtr FromString(string s)
+ {
+ IntPtr val = Runtime.PyUnicode_FromUnicode(s, s.Length);
+ PythonException.ThrowIfIsNull(val);
+ return val;
+ }
///
/// PyString Constructor
///
///
/// Creates a Python string from a managed string.
///
- public PyString(string s)
+ public PyString(string s) : base(FromString(s))
{
- obj = Runtime.PyUnicode_FromUnicode(s, s.Length);
- PythonException.ThrowIfIsNull(obj);
}
diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs
index 259d7ae0f..530ced3d2 100644
--- a/src/runtime/pytuple.cs
+++ b/src/runtime/pytuple.cs
@@ -31,6 +31,15 @@ public PyTuple(IntPtr ptr) : base(ptr)
///
internal PyTuple(BorrowedReference reference) : base(reference) { }
+ private static IntPtr FromObject(PyObject o)
+ {
+ if (o == null || !IsTupleType(o))
+ {
+ throw new ArgumentException("object is not a tuple");
+ }
+ Runtime.XIncref(o.obj);
+ return o.obj;
+ }
///
/// PyTuple Constructor
@@ -40,14 +49,8 @@ internal PyTuple(BorrowedReference reference) : base(reference) { }
/// ArgumentException will be thrown if the given object is not a
/// Python tuple object.
///
- public PyTuple(PyObject o)
+ public PyTuple(PyObject o) : base(FromObject(o))
{
- if (!IsTupleType(o))
- {
- throw new ArgumentException("object is not a tuple");
- }
- Runtime.XIncref(o.obj);
- obj = o.obj;
}
@@ -57,12 +60,28 @@ public PyTuple(PyObject o)
///
/// Creates a new empty PyTuple.
///
- public PyTuple()
+ public PyTuple() : base(Runtime.PyTuple_New(0))
{
- obj = Runtime.PyTuple_New(0);
PythonException.ThrowIfIsNull(obj);
}
+ private static IntPtr FromArray(PyObject[] items)
+ {
+ int count = items.Length;
+ IntPtr val = Runtime.PyTuple_New(count);
+ for (var i = 0; i < count; i++)
+ {
+ IntPtr ptr = items[i].obj;
+ Runtime.XIncref(ptr);
+ int res = Runtime.PyTuple_SetItem(val, i, ptr);
+ if (res != 0)
+ {
+ Runtime.Py_DecRef(val);
+ throw new PythonException();
+ }
+ }
+ return val;
+ }
///
/// PyTuple Constructor
@@ -73,17 +92,8 @@ public PyTuple()
/// See caveats about PyTuple_SetItem:
/// https://www.coursehero.com/file/p4j2ogg/important-exceptions-to-this-rule-PyTupleSetItem-and-PyListSetItem-These/
///
- public PyTuple(PyObject[] items)
+ public PyTuple(PyObject[] items) : base(FromArray(items))
{
- int count = items.Length;
- obj = Runtime.PyTuple_New(count);
- for (var i = 0; i < count; i++)
- {
- IntPtr ptr = items[i].obj;
- Runtime.XIncref(ptr);
- int res = Runtime.PyTuple_SetItem(obj, i, ptr);
- PythonException.ThrowIfIsNotZero(res);
- }
}