66using System . Runtime . InteropServices ;
77using System . Diagnostics ;
88using Python . Runtime . Slots ;
9+ using static Python . Runtime . PythonException ;
910
1011namespace 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