From 3a25f9149ae354a0d9b657e8575d5b72c902e306 Mon Sep 17 00:00:00 2001 From: Patrick Pijnappel Date: Mon, 21 Mar 2022 16:17:02 +0100 Subject: [PATCH 1/6] Add pow --- PythonKit/Python.swift | 6 ++++++ PythonKit/PythonLibrary+Symbols.swift | 3 +++ 2 files changed, 9 insertions(+) diff --git a/PythonKit/Python.swift b/PythonKit/Python.swift index ad2a2c9..011e4cc 100644 --- a/PythonKit/Python.swift +++ b/PythonKit/Python.swift @@ -1231,6 +1231,12 @@ public extension PythonObject { } } +public func pow(_ lhs: PythonObject, _ rhs: PythonObject) -> PythonObject { + let result = PyNumber_Power(lhs.borrowedPyObject, rhs.borrowedPyObject, Python.None) + try! throwPythonErrorIfPresent() + return PythonObject(consuming: result!) +} + extension PythonObject : SignedNumeric { public init(exactly value: T) { self.init(Int(value)) diff --git a/PythonKit/PythonLibrary+Symbols.swift b/PythonKit/PythonLibrary+Symbols.swift index ae36cf4..1fae333 100644 --- a/PythonKit/PythonLibrary+Symbols.swift +++ b/PythonKit/PythonLibrary+Symbols.swift @@ -241,6 +241,9 @@ let PyNumber_Multiply: PyBinaryOperation = let PyNumber_TrueDivide: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_TrueDivide") +let PyNumber_Power: @convention(c) (PyObjectPointer?, PyObjectPointer?, PyObjectPointer?) -> PyObjectPointer? = + PythonLibrary.loadSymbol(name: "PyNumber_Power") + let PyNumber_InPlaceAdd: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_InPlaceAdd") From f7b21fd701067fe480f0d75bcd3c79521d6fdf5a Mon Sep 17 00:00:00 2001 From: Patrick Pijnappel Date: Tue, 22 Mar 2022 15:07:22 +0100 Subject: [PATCH 2/6] Fix compilation --- PythonKit/Python.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PythonKit/Python.swift b/PythonKit/Python.swift index 011e4cc..1040a1d 100644 --- a/PythonKit/Python.swift +++ b/PythonKit/Python.swift @@ -1232,7 +1232,7 @@ public extension PythonObject { } public func pow(_ lhs: PythonObject, _ rhs: PythonObject) -> PythonObject { - let result = PyNumber_Power(lhs.borrowedPyObject, rhs.borrowedPyObject, Python.None) + let result = PyNumber_Power(lhs.borrowedPyObject, rhs.borrowedPyObject, Python.None.borrowedPyObject) try! throwPythonErrorIfPresent() return PythonObject(consuming: result!) } From cc45773265ff5882bb7a77fdf14037c466ae53c9 Mon Sep 17 00:00:00 2001 From: Patrick Pijnappel Date: Fri, 25 Mar 2022 10:17:11 +0100 Subject: [PATCH 3/6] Expose all operators --- PythonKit/Python.swift | 60 +++++++++++++++++++++++++-- PythonKit/PythonLibrary+Symbols.swift | 58 +++++++++++++++++++++----- 2 files changed, 103 insertions(+), 15 deletions(-) diff --git a/PythonKit/Python.swift b/PythonKit/Python.swift index 1040a1d..e7b50bb 100644 --- a/PythonKit/Python.swift +++ b/PythonKit/Python.swift @@ -1231,10 +1231,62 @@ public extension PythonObject { } } -public func pow(_ lhs: PythonObject, _ rhs: PythonObject) -> PythonObject { - let result = PyNumber_Power(lhs.borrowedPyObject, rhs.borrowedPyObject, Python.None.borrowedPyObject) - try! throwPythonErrorIfPresent() - return PythonObject(consuming: result!) +public enum PythonNumber { + private static func performBinaryOp(_ op: PythonBinaryOp, lhs: PythonObject, rhs: PythonObject) throws -> PythonObject { + let result = op(lhs.borrowedPyObject, rhs.borrowedPyObject) + // If binary operation fails (e.g. due to `TypeError`), throw an exception. + try throwPythonErrorIfPresent() + return PythonObject(consuming: result!) + } + + private static func performUnaryOp(_ op: PythonUnaryOp, operand: PythonObject) throws -> PythonObject { + let result = op(operand.borrowedPyObject) + // If unary operation fails (e.g. due to `TypeError`), throw an exception. + try throwPythonErrorIfPresent() + return PythonObject(consuming: result!) + } + + public static func add(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Add, lhs: lhs, rhs: rhs) } + public static func subtract(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Subtract, lhs: lhs, rhs: rhs) } + public static func multiply(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Multiply, lhs: lhs, rhs: rhs) } + public static func matrixMultiply(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_MatrixMultiply, lhs: lhs, rhs: rhs) } + public static func floorDivide(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_FloorDivide, lhs: lhs, rhs: rhs) } + public static func trueDivide(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_TrueDivide, lhs: lhs, rhs: rhs) } + public static func remainder(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Remainder, lhs: lhs, rhs: rhs) } + public static func negative(_ operand: PythonObject) throws -> PythonObject { try performUnaryOp(PyNumber_Negative, operand: operand) } + public static func positive(_ operand: PythonObject) throws -> PythonObject { try performUnaryOp(PyNumber_Positive, operand: operand) } + public static func invert(_ operand: PythonObject) throws -> PythonObject { try performUnaryOp(PyNumber_Invert, operand: operand) } + public static func lshift(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Lshift, lhs: lhs, rhs: rhs) } + public static func rshift(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Rshift, lhs: lhs, rhs: rhs) } + public static func and(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_And, lhs: lhs, rhs: rhs) } + public static func xor(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Xor, lhs: lhs, rhs: rhs) } + public static func or(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Or, lhs: lhs, rhs: rhs) } + + public static func power(_ lhs: PythonObject, _ rhs: PythonObject, modulus: PythonObject = Python.None) throws -> PythonObject { + let result = PyNumber_Power(lhs.borrowedPyObject, rhs.borrowedPyObject, modulus.borrowedPyObject) + try throwPythonErrorIfPresent() + return PythonObject(consuming: result!) + } + + public static func inPlaceAdd(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceAdd, lhs: lhs, rhs: rhs) } + public static func inPlaceSubtract(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceSubtract, lhs: lhs, rhs: rhs) } + public static func inPlaceMultiply(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceMultiply, lhs: lhs, rhs: rhs) } + public static func inPlaceMatrixMultiply(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceMatrixMultiply, lhs: lhs, rhs: rhs) } + public static func inPlaceFloorDivide(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceFloorDivide, lhs: lhs, rhs: rhs) } + public static func inPlaceTrueDivide(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceTrueDivide, lhs: lhs, rhs: rhs) } + public static func inPlaceRemainder(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceRemainder, lhs: lhs, rhs: rhs) } + public static func inPlaceLshift(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceLshift, lhs: lhs, rhs: rhs) } + public static func inPlaceRshift(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceRshift, lhs: lhs, rhs: rhs) } + public static func inPlaceAnd(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceAnd, lhs: lhs, rhs: rhs) } + public static func inPlaceXor(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceOr, lhs: lhs, rhs: rhs) } + public static func inPlaceOr(_ lhs: inout PythonObject, _ rhs: PythonObject) throws { lhs = try performBinaryOp(PyNumber_InPlaceXor, lhs: lhs, rhs: rhs) } + + public static func inPlacePower(_ lhs: inout PythonObject, _ rhs: PythonObject, modulus: PythonObject = Python.None) throws { + let result = PyNumber_InPlacePower(lhs.borrowedPyObject, rhs.borrowedPyObject, modulus.borrowedPyObject) + try throwPythonErrorIfPresent() + lhs = PythonObject(consuming: result!) + } + } extension PythonObject : SignedNumeric { diff --git a/PythonKit/PythonLibrary+Symbols.swift b/PythonKit/PythonLibrary+Symbols.swift index 1fae333..9bbca8b 100644 --- a/PythonKit/PythonLibrary+Symbols.swift +++ b/PythonKit/PythonLibrary+Symbols.swift @@ -238,12 +238,45 @@ let PyNumber_Subtract: PyBinaryOperation = let PyNumber_Multiply: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_Multiply") +let PyNumber_MatrixMultiply: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_MatrixMultiply") + +let PyNumber_FloorDivide: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_FloorDivide") + let PyNumber_TrueDivide: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_TrueDivide") +let PyNumber_Remainder: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_Remainder") + let PyNumber_Power: @convention(c) (PyObjectPointer?, PyObjectPointer?, PyObjectPointer?) -> PyObjectPointer? = PythonLibrary.loadSymbol(name: "PyNumber_Power") +let PyNumber_Negative: PyUnaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_Negative") + +let PyNumber_Positive: PyUnaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_Positive") + +let PyNumber_Invert: PyUnaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_Invert") + +let PyNumber_Lshift: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_Lshift") + +let PyNumber_Rshift: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_Rshift") + +let PyNumber_And: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_And") + +let PyNumber_Xor: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_Xor") + +let PyNumber_Or: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_Or") + let PyNumber_InPlaceAdd: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_InPlaceAdd") @@ -253,20 +286,26 @@ let PyNumber_InPlaceSubtract: PyBinaryOperation = let PyNumber_InPlaceMultiply: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_InPlaceMultiply") +let PyNumber_InPlaceMatrixMultiply: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_InPlaceMatrixMultiply") + +let PyNumber_InPlaceFloorDivide: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_InPlaceFloorDivide") + let PyNumber_InPlaceTrueDivide: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_InPlaceTrueDivide") -let PyNumber_Negative: PyUnaryOperation = - PythonLibrary.loadSymbol(name: "PyNumber_Negative") +let PyNumber_InPlaceRemainder: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_InPlaceRemainder") -let PyNumber_And: PyBinaryOperation = - PythonLibrary.loadSymbol(name: "PyNumber_And") +let PyNumber_InPlacePower: @convention(c) (PyObjectPointer?, PyObjectPointer?, PyObjectPointer?) -> PyObjectPointer? = + PythonLibrary.loadSymbol(name: "PyNumber_InPlacePower") -let PyNumber_Or: PyBinaryOperation = - PythonLibrary.loadSymbol(name: "PyNumber_Or") +let PyNumber_InPlaceLshift: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_InPlaceLshift") -let PyNumber_Xor: PyBinaryOperation = - PythonLibrary.loadSymbol(name: "PyNumber_Xor") +let PyNumber_InPlaceRshift: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PyNumber_InPlaceRshift") let PyNumber_InPlaceAnd: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_InPlaceAnd") @@ -276,6 +315,3 @@ let PyNumber_InPlaceOr: PyBinaryOperation = let PyNumber_InPlaceXor: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_InPlaceXor") - -let PyNumber_Invert: PyUnaryOperation = - PythonLibrary.loadSymbol(name: "PyNumber_Invert") From 03846506f2304eabbab7f4a322143db26442f02e Mon Sep 17 00:00:00 2001 From: Patrick Pijnappel Date: Mon, 28 Mar 2022 09:52:21 +0200 Subject: [PATCH 4/6] Expose functions for is & in --- PythonKit/Python.swift | 12 +++++++++++- PythonKit/PythonLibrary+Symbols.swift | 6 ++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/PythonKit/Python.swift b/PythonKit/Python.swift index e7b50bb..5546292 100644 --- a/PythonKit/Python.swift +++ b/PythonKit/Python.swift @@ -1231,7 +1231,12 @@ public extension PythonObject { } } -public enum PythonNumber { +extension ThrowingPythonObject { + + public static func not(_ operand: PythonObject) throws -> PythonObject { + return try performUnaryOp(PyObject_Not, operand: operand) + } + private static func performBinaryOp(_ op: PythonBinaryOp, lhs: PythonObject, rhs: PythonObject) throws -> PythonObject { let result = op(lhs.borrowedPyObject, rhs.borrowedPyObject) // If binary operation fails (e.g. due to `TypeError`), throw an exception. @@ -1287,6 +1292,7 @@ public enum PythonNumber { lhs = PythonObject(consuming: result!) } + public static func contains(_ sequence: PythonObject, _ x: PythonObject) throws -> PythonObject { try performBinaryOp(PySequence_Contains, lhs: sequence, rhs: x) } } extension PythonObject : SignedNumeric { @@ -1363,6 +1369,10 @@ extension PythonObject : Equatable, Comparable { public static func >= (lhs: PythonObject, rhs: PythonObject) -> Bool { return lhs.compared(to: rhs, byOp: Py_GE) } + + public static func === (lhs: PythonObject, rhs: PythonObject) -> Bool { + return lhs.reference === rhs.reference + } } public extension PythonObject { diff --git a/PythonKit/PythonLibrary+Symbols.swift b/PythonKit/PythonLibrary+Symbols.swift index 9bbca8b..b03be8c 100644 --- a/PythonKit/PythonLibrary+Symbols.swift +++ b/PythonKit/PythonLibrary+Symbols.swift @@ -122,6 +122,9 @@ let PyObject_SetAttrString: @convention(c) ( PyObjectPointer, PyCCharPointer, PyObjectPointer) -> Int32 = PythonLibrary.loadSymbol(name: "PyObject_SetAttrString") +let PyObject_Not: PyUnaryOperation = + PythonLibrary.loadSymbol(name: "PyObject_Not") + let PySlice_New: @convention(c) ( PyObjectPointer?, PyObjectPointer?, PyObjectPointer?) -> PyObjectPointer? = @@ -315,3 +318,6 @@ let PyNumber_InPlaceOr: PyBinaryOperation = let PyNumber_InPlaceXor: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_InPlaceXor") + +let PySequence_Contains: PyBinaryOperation = + PythonLibrary.loadSymbol(name: "PySequence_Contains") From e7bb09213e145b02568fb1c2e50fdc0b68b9bac5 Mon Sep 17 00:00:00 2001 From: Patrick Pijnappel Date: Mon, 28 Mar 2022 10:00:16 +0200 Subject: [PATCH 5/6] Add !== --- PythonKit/Python.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PythonKit/Python.swift b/PythonKit/Python.swift index 5546292..e122855 100644 --- a/PythonKit/Python.swift +++ b/PythonKit/Python.swift @@ -1373,6 +1373,10 @@ extension PythonObject : Equatable, Comparable { public static func === (lhs: PythonObject, rhs: PythonObject) -> Bool { return lhs.reference === rhs.reference } + + public static func !== (lhs: PythonObject, rhs: PythonObject) -> Bool { + return lhs.reference !== rhs.reference + } } public extension PythonObject { From 365177de35420652842e4c0e5c8e84a95eca10c1 Mon Sep 17 00:00:00 2001 From: Patrick Pijnappel Date: Mon, 28 Mar 2022 10:33:13 +0200 Subject: [PATCH 6/6] Fix contains --- PythonKit/Python.swift | 10 ++++++---- PythonKit/PythonLibrary+Symbols.swift | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/PythonKit/Python.swift b/PythonKit/Python.swift index e122855..ddba350 100644 --- a/PythonKit/Python.swift +++ b/PythonKit/Python.swift @@ -1239,14 +1239,12 @@ extension ThrowingPythonObject { private static func performBinaryOp(_ op: PythonBinaryOp, lhs: PythonObject, rhs: PythonObject) throws -> PythonObject { let result = op(lhs.borrowedPyObject, rhs.borrowedPyObject) - // If binary operation fails (e.g. due to `TypeError`), throw an exception. try throwPythonErrorIfPresent() return PythonObject(consuming: result!) } private static func performUnaryOp(_ op: PythonUnaryOp, operand: PythonObject) throws -> PythonObject { let result = op(operand.borrowedPyObject) - // If unary operation fails (e.g. due to `TypeError`), throw an exception. try throwPythonErrorIfPresent() return PythonObject(consuming: result!) } @@ -1267,6 +1265,12 @@ extension ThrowingPythonObject { public static func xor(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Xor, lhs: lhs, rhs: rhs) } public static func or(_ lhs: PythonObject, _ rhs: PythonObject) throws -> PythonObject { try performBinaryOp(PyNumber_Or, lhs: lhs, rhs: rhs) } + public static func contains(_ sequence: PythonObject, _ x: PythonObject) throws -> Bool { + let result = PySequence_Contains(sequence.borrowedPyObject, x.borrowedPyObject) + try throwPythonErrorIfPresent() + return (result == 1) + } + public static func power(_ lhs: PythonObject, _ rhs: PythonObject, modulus: PythonObject = Python.None) throws -> PythonObject { let result = PyNumber_Power(lhs.borrowedPyObject, rhs.borrowedPyObject, modulus.borrowedPyObject) try throwPythonErrorIfPresent() @@ -1291,8 +1295,6 @@ extension ThrowingPythonObject { try throwPythonErrorIfPresent() lhs = PythonObject(consuming: result!) } - - public static func contains(_ sequence: PythonObject, _ x: PythonObject) throws -> PythonObject { try performBinaryOp(PySequence_Contains, lhs: sequence, rhs: x) } } extension PythonObject : SignedNumeric { diff --git a/PythonKit/PythonLibrary+Symbols.swift b/PythonKit/PythonLibrary+Symbols.swift index b03be8c..abbfe4a 100644 --- a/PythonKit/PythonLibrary+Symbols.swift +++ b/PythonKit/PythonLibrary+Symbols.swift @@ -319,5 +319,5 @@ let PyNumber_InPlaceOr: PyBinaryOperation = let PyNumber_InPlaceXor: PyBinaryOperation = PythonLibrary.loadSymbol(name: "PyNumber_InPlaceXor") -let PySequence_Contains: PyBinaryOperation = +let PySequence_Contains: @convention(c) (PyObjectPointer?, PyObjectPointer?) -> Int32 = PythonLibrary.loadSymbol(name: "PySequence_Contains")