Skip to content

Commit d59167a

Browse files
authored
Test #1 out of 2
1 parent 7cdbc2a commit d59167a

File tree

1 file changed

+66
-2
lines changed

1 file changed

+66
-2
lines changed

Tests/PythonKitTests/PythonRuntimeTests.swift

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)