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
{
@@ -313,6 +314,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
313
314
314
315
internal static IntPtr CreateSubType ( IntPtr py_name , IntPtr py_base_type , IntPtr py_dict )
315
316
{
317
+ var dictRef = new BorrowedReference ( py_dict ) ;
316
318
// Utility to create a subtype of a managed type with the ability for the
317
319
// a python subtype able to override the managed implementation
318
320
string name = Runtime . GetManagedString ( py_name ) ;
@@ -322,40 +324,29 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
322
324
object assembly = null ;
323
325
object namespaceStr = null ;
324
326
325
- var disposeList = new List < PyObject > ( ) ;
326
- try
327
+ using ( var assemblyKey = new PyString ( "__assembly__" ) )
327
328
{
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 )
331
331
{
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" ) ;
339
337
}
340
338
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__" ) )
344
340
{
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 )
349
343
{
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" ) ;
351
349
}
352
- }
353
- }
354
- finally
355
- {
356
- foreach ( PyObject o in disposeList )
357
- {
358
- o . Dispose ( ) ;
359
350
}
360
351
}
361
352
@@ -381,14 +372,14 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr
381
372
// by default the class dict will have all the C# methods in it, but as this is a
382
373
// derived class we want the python overrides in there instead if they exist.
383
374
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 ) ) ;
385
376
Runtime . XIncref ( py_type ) ;
386
377
// Update the __classcell__ if it exists
387
378
var cell = new BorrowedReference ( Runtime . PyDict_GetItemString ( cls_dict , "__classcell__" ) ) ;
388
379
if ( ! cell . IsNull )
389
380
{
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__" ) ) ;
392
383
}
393
384
394
385
return py_type ;
0 commit comments