6
6
using System . Runtime . InteropServices ;
7
7
using System . Diagnostics ;
8
8
using Python . Runtime . Slots ;
9
+ using static Python . Runtime . PythonException ;
9
10
10
11
namespace Python . Runtime
11
12
{
@@ -302,6 +303,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
302
303
303
304
internal static IntPtr CreateSubType ( IntPtr py_name , IntPtr py_base_type , IntPtr py_dict )
304
305
{
306
+ var dictRef = new BorrowedReference ( py_dict ) ;
305
307
// Utility to create a subtype of a managed type with the ability for the
306
308
// a python subtype able to override the managed implementation
307
309
string name = Runtime . GetManagedString ( py_name ) ;
@@ -311,40 +313,29 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
311
313
object assembly = null ;
312
314
object namespaceStr = null ;
313
315
314
- var disposeList = new List < PyObject > ( ) ;
315
- try
316
+ using ( var assemblyKey = new PyString ( "__assembly__" ) )
316
317
{
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 )
320
320
{
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" ) ;
328
326
}
329
327
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__" ) )
333
329
{
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 )
338
332
{
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" ) ;
340
338
}
341
- }
342
- }
343
- finally
344
- {
345
- foreach ( PyObject o in disposeList )
346
- {
347
- o . Dispose ( ) ;
348
339
}
349
340
}
350
341
@@ -370,14 +361,14 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
370
361
// by default the class dict will have all the C# methods in it, but as this is a
371
362
// derived class we want the python overrides in there instead if they exist.
372
363
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 ) ) ;
374
365
Runtime . XIncref ( py_type ) ;
375
366
// Update the __classcell__ if it exists
376
367
var cell = new BorrowedReference ( Runtime . PyDict_GetItemString ( cls_dict , "__classcell__" ) ) ;
377
368
if ( ! cell . IsNull )
378
369
{
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__" ) ) ;
381
372
}
382
373
383
374
return py_type ;
0 commit comments