@@ -327,10 +327,14 @@ class PythonRuntimeTests: XCTestCase {
327327 XCTAssertEqual ( bytes, otherBytes)
328328 }
329329
330- func testPythonFunction ( ) {
330+ private var canUsePythonFunction : Bool {
331331 let versionMajor = Python . versionInfo. major
332332 let versionMinor = Python . versionInfo. minor
333- guard ( versionMajor == 3 && versionMinor >= 1 ) || versionMajor > 3 else {
333+ return ( versionMajor == 3 && versionMinor >= 1 ) || versionMajor > 3
334+ }
335+
336+ func testPythonFunction( ) {
337+ guard canUsePythonFunction else {
334338 return
335339 }
336340
@@ -344,4 +348,64 @@ class PythonRuntimeTests: XCTestCase {
344348 XCTAssertNotNil ( Double ( pythonSum) )
345349 XCTAssertEqual ( pythonSum, 5 )
346350 }
351+
352+ // From https://www.geeksforgeeks.org/create-classes-dynamically-in-python
353+ func testPythonClassConstruction( ) {
354+ guard canUsePythonFunction else {
355+ return
356+ }
357+
358+ let constructor = PythonInstanceMethod { ( params: [ PythonObject ] ) in
359+ let `self` = params [ 0 ]
360+ let arg = params [ 1 ]
361+ `self`. constructor_arg = arg
362+ return Python . None
363+ }
364+
365+ // Instead of calling `print`, use this to test what would be output.
366+ var printOutput : String ?
367+
368+ let displayMethod = PythonInstanceMethod { ( params: [ PythonObject ] ) in
369+ // let `self` = params[0]
370+ let arg = params [ 1 ]
371+ printOutput = String ( arg)
372+ return Python . None
373+ }
374+
375+ let classMethodOriginal = PythonInstanceMethod { ( params: [ PythonObject ] ) in
376+ // let cls = params[0]
377+ let arg = params [ 1 ]
378+ printOutput = String ( arg)
379+ return Python . None
380+ }
381+
382+ // Did not explicitly convert `constructor` or `displayMethod` to PythonObject.
383+ // This is intentional, as the `PythonClass` initializer should take any
384+ // `PythonConvertible` and not just `PythonObject`.
385+ let classMethod = Python . classmethod ( classMethodOriginal. pythonObject)
386+
387+ let Geeks = PythonClass ( " Geeks " , members: [
388+ // Constructor
389+ " __init__ " : constructor,
390+
391+ // Data members
392+ " string_attribute " : " Geeks 4 geeks! " ,
393+ " int_attribute " : 1706256 ,
394+
395+ // Member functions
396+ " func_arg " : displayMethod,
397+ " class_func " : classMethod,
398+ ] ) . pythonObject
399+
400+ let obj = Geeks ( " constructor argument " )
401+ XCTAssertEqual ( obj. constructor_arg, " constructor argument " )
402+ XCTAssertEqual ( obj. string_attribute, " Geeks 4 geeks! " )
403+ XCTAssertEqual ( obj. int_attribute, 1706256 )
404+
405+ obj. func_arg ( " Geeks for Geeks " )
406+ XCTAssertEqual ( printOutput, " Geeks for Geeks " )
407+
408+ Geeks . class_func ( " Class Dynamically Created! " )
409+ XCTAssertEqual ( printOutput, " Class Dynamically Created! " )
410+ }
347411}
0 commit comments