@@ -233,7 +233,75 @@ public static IntPtr tp_str(IntPtr ob)
233
233
}
234
234
try
235
235
{
236
+ //As per python doc:
237
+ //The return value must be a string object. If a class defines __repr__() but not __str__(),
238
+ //then __repr__() is also used when an “informal” string representation of instances of that
239
+ //class is required.
240
+ //In C#, everything provides ToString(), so the check here will be whether the type explicitly
241
+ //provides ToString() or if it is language provided (i.e. the fully qualified type name as a string)
242
+
243
+ //First check which type in the object hierarchy provides ToString()
244
+ //ToString has two "official" overloads so loop over GetMethods to get the one without parameters
245
+ var instType = co . inst . GetType ( ) ;
246
+ foreach ( var method in instType . GetMethods ( ) )
247
+ {
248
+
249
+ //TODO this could probably be done more cleanly with Linq
250
+ if ( ! method . IsPublic ) continue ; //skip private/protected methods
251
+ if ( method . Name != "ToString" ) continue ; //only look for ToString
252
+ if ( method . DeclaringType == typeof ( object ) ) continue ; //ignore default from object
253
+ if ( method . GetParameters ( ) . Length != 0 ) continue ; //ignore Formatter overload of ToString
254
+
255
+ //match! something other than object provides a parameter-less overload of ToString
256
+ return Runtime . PyString_FromString ( co . inst . ToString ( ) ) ;
257
+ }
258
+
259
+ //If the object defines __repr__, call it.
260
+ System . Reflection . MethodInfo reprMethodInfo = instType . GetMethod ( "__repr__" ) ;
261
+ if ( reprMethodInfo != null && reprMethodInfo . IsPublic )
262
+ {
263
+ var reprString = reprMethodInfo . Invoke ( co . inst , null ) as string ;
264
+ return Runtime . PyString_FromString ( reprString ) ;
265
+ }
266
+
267
+ //otherwise fallback to object's ToString() implementation
236
268
return Runtime . PyString_FromString ( co . inst . ToString ( ) ) ;
269
+
270
+ }
271
+ catch ( Exception e )
272
+ {
273
+ if ( e . InnerException != null )
274
+ {
275
+ e = e . InnerException ;
276
+ }
277
+ Exceptions . SetError ( e ) ;
278
+ return IntPtr . Zero ;
279
+ }
280
+ }
281
+
282
+ public static IntPtr tp_repr ( IntPtr ob )
283
+ {
284
+ var co = GetManagedObject ( ob ) as CLRObject ;
285
+ if ( co == null )
286
+ {
287
+ return Exceptions . RaiseTypeError ( "invalid object" ) ;
288
+ }
289
+ try
290
+ {
291
+ //if __repr__ is defined, use it
292
+ var instType = co . inst . GetType ( ) ;
293
+ System . Reflection . MethodInfo methodInfo = instType . GetMethod ( "__repr__" ) ;
294
+ if ( methodInfo != null && methodInfo . IsPublic )
295
+ {
296
+ var reprString = methodInfo . Invoke ( co . inst , null ) as string ;
297
+ return Runtime . PyString_FromString ( reprString ) ;
298
+ }
299
+
300
+ //otherwise use the standard object.__repr__(inst)
301
+ IntPtr args = Runtime . PyTuple_New ( 1 ) ;
302
+ Runtime . PyTuple_SetItem ( args , 0 , ob ) ;
303
+ IntPtr reprFunc = Runtime . PyObject_GetAttrString ( Runtime . PyBaseObjectType , "__repr__" ) ;
304
+ return Runtime . PyObject_Call ( reprFunc , args , IntPtr . Zero ) ;
237
305
}
238
306
catch ( Exception e )
239
307
{
0 commit comments