Skip to content

Commit 0b027c6

Browse files
lostmsuBadSingleton
authored andcommitted
refactoring in CreateSubType
1 parent b3e86da commit 0b027c6

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
@@ -1642,6 +1642,8 @@ internal static bool PyDict_Check(IntPtr ob)
16421642
/// </summary>
16431643
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
16441644
internal static extern IntPtr PyDict_GetItem(IntPtr pointer, IntPtr key);
1645+
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
1646+
internal static extern BorrowedReference PyDict_GetItemWithError(BorrowedReference pointer, BorrowedReference key);
16451647

16461648
/// <summary>
16471649
/// 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
{
@@ -313,6 +314,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
313314

314315
internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict)
315316
{
317+
var dictRef = new BorrowedReference(py_dict);
316318
// Utility to create a subtype of a managed type with the ability for the
317319
// a python subtype able to override the managed implementation
318320
string name = Runtime.GetManagedString(py_name);
@@ -322,40 +324,29 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
322324
object assembly = null;
323325
object namespaceStr = null;
324326

325-
var disposeList = new List<PyObject>();
326-
try
327+
using (var assemblyKey = new PyString("__assembly__"))
327328
{
328-
var assemblyKey = new PyObject(Converter.ToPython("__assembly__", typeof(string)));
329-
disposeList.Add(assemblyKey);
330-
if (0 != Runtime.PyMapping_HasKey(py_dict, assemblyKey.Handle))
329+
var assemblyPtr = Runtime.PyDict_GetItemWithError(dictRef, assemblyKey.Reference);
330+
if (assemblyPtr.IsNull)
331331
{
332-
var pyAssembly = new PyObject(Runtime.PyDict_GetItem(py_dict, assemblyKey.Handle));
333-
Runtime.XIncref(pyAssembly.Handle);
334-
disposeList.Add(pyAssembly);
335-
if (!Converter.ToManagedValue(pyAssembly.Handle, typeof(string), out assembly, false))
336-
{
337-
throw new InvalidCastException("Couldn't convert __assembly__ value to string");
338-
}
332+
if (Exceptions.ErrorOccurred()) return IntPtr.Zero;
333+
}
334+
else if (!Converter.ToManagedValue(assemblyPtr, typeof(string), out assembly, false))
335+
{
336+
return Exceptions.RaiseTypeError("Couldn't convert __assembly__ value to string");
339337
}
340338

341-
var namespaceKey = new PyObject(Converter.ToPythonImplicit("__namespace__"));
342-
disposeList.Add(namespaceKey);
343-
if (0 != Runtime.PyMapping_HasKey(py_dict, namespaceKey.Handle))
339+
using (var namespaceKey = new PyString("__namespace__"))
344340
{
345-
var pyNamespace = new PyObject(Runtime.PyDict_GetItem(py_dict, namespaceKey.Handle));
346-
Runtime.XIncref(pyNamespace.Handle);
347-
disposeList.Add(pyNamespace);
348-
if (!Converter.ToManagedValue(pyNamespace.Handle, typeof(string), out namespaceStr, false))
341+
var pyNamespace = Runtime.PyDict_GetItemWithError(dictRef, namespaceKey.Reference);
342+
if (pyNamespace.IsNull)
349343
{
350-
throw new InvalidCastException("Couldn't convert __namespace__ value to string");
344+
if (Exceptions.ErrorOccurred()) return IntPtr.Zero;
345+
}
346+
else if (!Converter.ToManagedValue(pyNamespace, typeof(string), out namespaceStr, false))
347+
{
348+
return Exceptions.RaiseTypeError("Couldn't convert __namespace__ value to string");
351349
}
352-
}
353-
}
354-
finally
355-
{
356-
foreach (PyObject o in disposeList)
357-
{
358-
o.Dispose();
359350
}
360351
}
361352

@@ -381,14 +372,14 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
381372
// by default the class dict will have all the C# methods in it, but as this is a
382373
// derived class we want the python overrides in there instead if they exist.
383374
IntPtr cls_dict = Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict);
384-
Runtime.PyDict_Update(cls_dict, py_dict);
375+
ThrowIfIsNotZero(Runtime.PyDict_Update(cls_dict, py_dict));
385376
Runtime.XIncref(py_type);
386377
// Update the __classcell__ if it exists
387378
var cell = new BorrowedReference(Runtime.PyDict_GetItemString(cls_dict, "__classcell__"));
388379
if (!cell.IsNull)
389380
{
390-
Runtime.PyCell_Set(cell, py_type);
391-
Runtime.PyDict_DelItemString(cls_dict, "__classcell__");
381+
ThrowIfIsNotZero(Runtime.PyCell_Set(cell, py_type));
382+
ThrowIfIsNotZero(Runtime.PyDict_DelItemString(cls_dict, "__classcell__"));
392383
}
393384

394385
return py_type;

0 commit comments

Comments
 (0)