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

Skip to content

Commit 08ea6f3

Browse files
committed
refactoring in CreateSubType
1 parent 44a36dc commit 08ea6f3

File tree

3 files changed

+26
-31
lines changed

3 files changed

+26
-31
lines changed

src/runtime/converter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,9 @@ internal static bool ToManaged(IntPtr value, Type type,
313313
return Converter.ToManagedValue(value, type, out result, setError);
314314
}
315315

316-
316+
internal static bool ToManagedValue(BorrowedReference value, Type obType,
317+
out object result, bool setError)
318+
=> ToManagedValue(value.DangerousGetAddress(), obType, out result, setError);
317319
internal static bool ToManagedValue(IntPtr value, Type obType,
318320
out object result, bool setError)
319321
{

src/runtime/runtime.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,8 @@ internal static bool PyDict_Check(IntPtr ob)
16411641
/// </summary>
16421642
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
16431643
internal static extern IntPtr PyDict_GetItem(IntPtr pointer, IntPtr key);
1644+
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
1645+
internal static extern BorrowedReference PyDict_GetItemWithError(BorrowedReference pointer, BorrowedReference key);
16441646

16451647
/// <summary>
16461648
/// Return value: Borrowed reference.

src/runtime/typemanager.cs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Runtime.InteropServices;
77
using System.Diagnostics;
88
using Python.Runtime.Slots;
9+
using static Python.Runtime.PythonException;
910

1011
namespace Python.Runtime
1112
{
@@ -302,6 +303,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
302303

303304
internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict)
304305
{
306+
var dictRef = new BorrowedReference(py_dict);
305307
// Utility to create a subtype of a managed type with the ability for the
306308
// a python subtype able to override the managed implementation
307309
string name = Runtime.GetManagedString(py_name);
@@ -311,40 +313,29 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
311313
object assembly = null;
312314
object namespaceStr = null;
313315

314-
var disposeList = new List<PyObject>();
315-
try
316+
using (var assemblyKey = new PyString("__assembly__"))
316317
{
317-
var assemblyKey = new PyObject(Converter.ToPython("__assembly__", typeof(string)));
318-
disposeList.Add(assemblyKey);
319-
if (0 != Runtime.PyMapping_HasKey(py_dict, assemblyKey.Handle))
318+
var assemblyPtr = Runtime.PyDict_GetItemWithError(dictRef, assemblyKey.Reference);
319+
if (assemblyPtr.IsNull)
320320
{
321-
var pyAssembly = new PyObject(Runtime.PyDict_GetItem(py_dict, assemblyKey.Handle));
322-
Runtime.XIncref(pyAssembly.Handle);
323-
disposeList.Add(pyAssembly);
324-
if (!Converter.ToManagedValue(pyAssembly.Handle, typeof(string), out assembly, false))
325-
{
326-
throw new InvalidCastException("Couldn't convert __assembly__ value to string");
327-
}
321+
if (Exceptions.ErrorOccurred()) return IntPtr.Zero;
322+
}
323+
else if (!Converter.ToManagedValue(assemblyPtr, typeof(string), out assembly, false))
324+
{
325+
return Exceptions.RaiseTypeError("Couldn't convert __assembly__ value to string");
328326
}
329327

330-
var namespaceKey = new PyObject(Converter.ToPythonImplicit("__namespace__"));
331-
disposeList.Add(namespaceKey);
332-
if (0 != Runtime.PyMapping_HasKey(py_dict, namespaceKey.Handle))
328+
using (var namespaceKey = new PyString("__namespace__"))
333329
{
334-
var pyNamespace = new PyObject(Runtime.PyDict_GetItem(py_dict, namespaceKey.Handle));
335-
Runtime.XIncref(pyNamespace.Handle);
336-
disposeList.Add(pyNamespace);
337-
if (!Converter.ToManagedValue(pyNamespace.Handle, typeof(string), out namespaceStr, false))
330+
var pyNamespace = Runtime.PyDict_GetItemWithError(dictRef, namespaceKey.Reference);
331+
if (pyNamespace.IsNull)
338332
{
339-
throw new InvalidCastException("Couldn't convert __namespace__ value to string");
333+
if (Exceptions.ErrorOccurred()) return IntPtr.Zero;
334+
}
335+
else if (!Converter.ToManagedValue(pyNamespace, typeof(string), out namespaceStr, false))
336+
{
337+
return Exceptions.RaiseTypeError("Couldn't convert __namespace__ value to string");
340338
}
341-
}
342-
}
343-
finally
344-
{
345-
foreach (PyObject o in disposeList)
346-
{
347-
o.Dispose();
348339
}
349340
}
350341

@@ -370,14 +361,14 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
370361
// by default the class dict will have all the C# methods in it, but as this is a
371362
// derived class we want the python overrides in there instead if they exist.
372363
IntPtr cls_dict = Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict);
373-
Runtime.PyDict_Update(cls_dict, py_dict);
364+
ThrowIfIsNotZero(Runtime.PyDict_Update(cls_dict, py_dict));
374365
Runtime.XIncref(py_type);
375366
// Update the __classcell__ if it exists
376367
var cell = new BorrowedReference(Runtime.PyDict_GetItemString(cls_dict, "__classcell__"));
377368
if (!cell.IsNull)
378369
{
379-
Runtime.PyCell_Set(cell, py_type);
380-
Runtime.PyDict_DelItemString(cls_dict, "__classcell__");
370+
ThrowIfIsNotZero(Runtime.PyCell_Set(cell, py_type));
371+
ThrowIfIsNotZero(Runtime.PyDict_DelItemString(cls_dict, "__classcell__"));
381372
}
382373

383374
return py_type;

0 commit comments

Comments
 (0)