From 5137b0b11f7363894fed07ef4807a0d4558125a0 Mon Sep 17 00:00:00 2001 From: Doug Friedman Date: Tue, 9 Apr 2019 12:22:34 -0400 Subject: [PATCH 01/10] numpy => python --- ...onversion.swift => PythonConversion.swift} | 21 +++++++++++++++++-- stdlib/public/TensorFlow/TensorShape.swift | 19 ----------------- ...nversion.swift => python_conversion.swift} | 4 ++-- 3 files changed, 21 insertions(+), 23 deletions(-) rename stdlib/public/TensorFlow/{NumpyConversion.swift => PythonConversion.swift} (92%) rename test/TensorFlowRuntime/{numpy_conversion.swift => python_conversion.swift} (98%) diff --git a/stdlib/public/TensorFlow/NumpyConversion.swift b/stdlib/public/TensorFlow/PythonConversion.swift similarity index 92% rename from stdlib/public/TensorFlow/NumpyConversion.swift rename to stdlib/public/TensorFlow/PythonConversion.swift index f9dd0fd8fde2c..74523765a4985 100644 --- a/stdlib/public/TensorFlow/NumpyConversion.swift +++ b/stdlib/public/TensorFlow/PythonConversion.swift @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// // -// This file defines conversion initializers from `numpy.ndarray` to -// `ShapedArray` and `Tensor`. +// This file defines conversion logic between Python types & +// custom TensorFlow types // //===----------------------------------------------------------------------===// @@ -164,4 +164,21 @@ extension Tensor where Scalar : NumpyScalarCompatible { public func makeNumpyArray() -> PythonObject { return array.makeNumpyArray() } } +extension TensorShape : PythonConvertible { + public var pythonObject: PythonObject { + return dimensions.pythonObject + } + + public init?(_ pythonObject: PythonObject) { + let hasLen = Bool(Python.hasattr(pythonObject, "__len__")) + if(hasLen == true) { + guard let array = [Int32](pythonObject) else { return nil } + self.init(array) + } else { + guard let num = Int32(pythonObject) else { return nil } + self.init(num) + } + } +} + #endif // canImport(Python) diff --git a/stdlib/public/TensorFlow/TensorShape.swift b/stdlib/public/TensorFlow/TensorShape.swift index 68a16136f30bd..7209e4d01a275 100644 --- a/stdlib/public/TensorFlow/TensorShape.swift +++ b/stdlib/public/TensorFlow/TensorShape.swift @@ -10,8 +10,6 @@ // //===----------------------------------------------------------------------===// -import Python - // NOTE: it may be possible to edit `TensorShape` to support "labeled tensors". // Dimensions may be either an Int32 or an enum representing a label. @@ -160,20 +158,3 @@ extension TensorShape : Codable { self.init(dimensions) } } - -extension TensorShape : PythonConvertible { - public var pythonObject: PythonObject { - return dimensions.pythonObject - } - - public init?(_ pythonObject: PythonObject) { - let hasLen = Bool(Python.hasattr(pythonObject, "__len__")) - if(hasLen == true) { - guard let array = [Int32](pythonObject) else { return nil } - self.init(array) - } else { - guard let num = Int32(pythonObject) else { return nil } - self.init(num) - } - } -} diff --git a/test/TensorFlowRuntime/numpy_conversion.swift b/test/TensorFlowRuntime/python_conversion.swift similarity index 98% rename from test/TensorFlowRuntime/numpy_conversion.swift rename to test/TensorFlowRuntime/python_conversion.swift index b27b7002d3009..41ee30605d203 100644 --- a/test/TensorFlowRuntime/numpy_conversion.swift +++ b/test/TensorFlowRuntime/python_conversion.swift @@ -4,12 +4,12 @@ // REQUIRES: swift_test_mode_optimize // REQUIRES: tensorflow // -// `numpy.ndarray` conversion tests. +// `numpy.ndarray` and Python conversion tests. import TensorFlow import StdlibUnittest -var NumpyConversionTests = TestSuite("NumpyConversion") +var PythonConversionTests = TestSuite("PythonConversion") // TODO: Add `python` as a lit feature so this test can use "REQUIRE: python" // instead of `#if canImport(Python)`. From cde6b273ce687df991f92cf9fe4fd7cb341d42ac Mon Sep 17 00:00:00 2001 From: Doug Friedman Date: Tue, 9 Apr 2019 12:43:23 -0400 Subject: [PATCH 02/10] s/Numpy/Python/ --- stdlib/public/TensorFlow/PythonConversion.swift | 2 +- test/TensorFlowRuntime/python_conversion.swift | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/public/TensorFlow/PythonConversion.swift b/stdlib/public/TensorFlow/PythonConversion.swift index 74523765a4985..f686cc5c41545 100644 --- a/stdlib/public/TensorFlow/PythonConversion.swift +++ b/stdlib/public/TensorFlow/PythonConversion.swift @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines conversion logic between Python types & +// This file defines conversions between Python types & // custom TensorFlow types // //===----------------------------------------------------------------------===// diff --git a/test/TensorFlowRuntime/python_conversion.swift b/test/TensorFlowRuntime/python_conversion.swift index 41ee30605d203..d02bd1be0d474 100644 --- a/test/TensorFlowRuntime/python_conversion.swift +++ b/test/TensorFlowRuntime/python_conversion.swift @@ -4,7 +4,7 @@ // REQUIRES: swift_test_mode_optimize // REQUIRES: tensorflow // -// `numpy.ndarray` and Python conversion tests. +// Python conversion and `numpy.ndarray` tests. import TensorFlow import StdlibUnittest @@ -20,7 +20,7 @@ import Python let numpyModule = try? Python.attemptImport("numpy") let ctypesModule = try? Python.attemptImport("ctypes") -NumpyConversionTests.test("shaped-array-conversion") { +PythonConversionTests.test("shaped-array-conversion") { guard let np = numpyModule else { return } let numpyArrayEmpty = np.array([[]] as [[Float]], dtype: np.float32) @@ -75,7 +75,7 @@ NumpyConversionTests.test("shaped-array-conversion") { } } -NumpyConversionTests.test("tensor-conversion") { +PythonConversionTests.test("tensor-conversion") { guard let np = numpyModule else { return } let numpyArrayEmpty = np.array([[]] as [[Float]], dtype: np.float32) @@ -123,7 +123,7 @@ NumpyConversionTests.test("tensor-conversion") { } } -NumpyConversionTests.test("tensor-round-trip") { +PythonConversionTests.test("tensor-round-trip") { guard numpyModule != nil else { return } guard ctypesModule != nil else { return } @@ -137,7 +137,7 @@ NumpyConversionTests.test("tensor-round-trip") { expectEqual(t3, Tensor(numpy: t3.makeNumpyArray())!) } -NumpyConversionTests.test("tensor-shape") { +PythonConversionTests.test("tensor-shape") { let pyArray = [2, 3].pythonObject expectEqual(pyArray, TensorShape(2, 3).pythonObject) expectEqual(TensorShape(2, 3), TensorShape(pyArray)) From 2e27373d977d9f1dcb0b6a442e6579a55fc0811c Mon Sep 17 00:00:00 2001 From: Doug Friedman Date: Tue, 9 Apr 2019 14:34:29 -0400 Subject: [PATCH 03/10] other renames that were missed --- stdlib/public/TensorFlow/CMakeLists.txt | 4 ++-- stdlib/public/TensorFlow/PythonConversion.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/public/TensorFlow/CMakeLists.txt b/stdlib/public/TensorFlow/CMakeLists.txt index f099d82a44859..0c363c4bcfc1d 100644 --- a/stdlib/public/TensorFlow/CMakeLists.txt +++ b/stdlib/public/TensorFlow/CMakeLists.txt @@ -50,7 +50,7 @@ set(SOURCES Utilities.swift Threading.swift # NumPy bridging for `ShapedArray` and `Tensor`. - NumpyConversion.swift) + PythonConversion.swift) # Copy TensorFlow bindings file, if it exists. if (TENSORFLOW_SWIFT_BINDINGS) @@ -65,7 +65,7 @@ if (TENSORFLOW_SWIFT_APIS) list(APPEND SOURCES "${TENSORFLOW_SWIFT_API_SOURCES}") endif() -# When Python exists, NumpyConversion.swift imports it, so it must be +# When Python exists, PythonConversion.swift imports it, so it must be # available at link time. set(TENSORFLOW_DEPENDS_PYTHON) if (SWIFT_PYTHON_EXISTS) diff --git a/stdlib/public/TensorFlow/PythonConversion.swift b/stdlib/public/TensorFlow/PythonConversion.swift index f686cc5c41545..aa4856b5a266d 100644 --- a/stdlib/public/TensorFlow/PythonConversion.swift +++ b/stdlib/public/TensorFlow/PythonConversion.swift @@ -1,4 +1,4 @@ -//===-- NumpyConversion.swift ---------------------------------*- swift -*-===// +//===-- PythonConversion.swift ---------------------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // From 1d49f38cb700224ce8ee655d1eca3d88ee554a51 Mon Sep 17 00:00:00 2001 From: Doug Friedman Date: Fri, 12 Apr 2019 21:31:15 +0000 Subject: [PATCH 04/10] syntax updates --- stdlib/public/TensorFlow/PythonConversion.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/stdlib/public/TensorFlow/PythonConversion.swift b/stdlib/public/TensorFlow/PythonConversion.swift index aa4856b5a266d..f2165e7a64dc2 100644 --- a/stdlib/public/TensorFlow/PythonConversion.swift +++ b/stdlib/public/TensorFlow/PythonConversion.swift @@ -1,4 +1,4 @@ -//===-- PythonConversion.swift ---------------------------------*- swift -*-===// +//===-- PythonConversion.swift --------------------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // @@ -10,8 +10,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines conversions between Python types & -// custom TensorFlow types +// This file defines conversions between Python types & custom TensorFlow types. // //===----------------------------------------------------------------------===// @@ -170,8 +169,7 @@ extension TensorShape : PythonConvertible { } public init?(_ pythonObject: PythonObject) { - let hasLen = Bool(Python.hasattr(pythonObject, "__len__")) - if(hasLen == true) { + if Python.hasattr(pythonObject, "__len__") == true { guard let array = [Int32](pythonObject) else { return nil } self.init(array) } else { From 7c4f0f8d2fcc3f683128bc657847b7193981c23c Mon Sep 17 00:00:00 2001 From: Doug Friedman Date: Sun, 14 Apr 2019 22:16:13 +0000 Subject: [PATCH 05/10] split PythonConvertible protocol in two --- stdlib/public/Python/Python.swift | 133 +++++++++++------- .../public/TensorFlow/PythonConversion.swift | 10 -- test/TensorFlow/integration.swift | 2 +- .../TensorFlowRuntime/python_conversion.swift | 6 +- 4 files changed, 82 insertions(+), 69 deletions(-) diff --git a/stdlib/public/Python/Python.swift b/stdlib/public/Python/Python.swift index 62253e68752db..3bef3d239ee2d 100644 --- a/stdlib/public/Python/Python.swift +++ b/stdlib/public/Python/Python.swift @@ -147,14 +147,20 @@ extension PythonObject : CustomReflectable { //===----------------------------------------------------------------------===// public protocol PythonConvertible { + /// A `PythonObject` instance representing this value. + var pythonObject: PythonObject { get } +} + +//===----------------------------------------------------------------------===// +// `PythonConvertible` protocol +//===----------------------------------------------------------------------===// + +public protocol ConvertibleFromPython { /// Creates a new instance from the given `PythonObject`, if possible. /// - Note: Conversion may fail if the given `PythonObject` instance is /// incompatible (e.g. a Python `string` object cannot be converted into an /// `Int`). init?(_ object: PythonObject) - - /// A `PythonObject` instance representing this value. - var pythonObject: PythonObject { get } } public extension PythonObject { @@ -177,7 +183,7 @@ fileprivate extension PythonConvertible { } // `PythonObject` is trivially `PythonConvertible`. -extension PythonObject : PythonConvertible { +extension PythonObject : PythonConvertible, ConvertibleFromPython { public init(_ object: PythonObject) { self.init(consuming: object.ownedPyObject) } @@ -747,7 +753,7 @@ private func isType(_ object: PythonObject, return pyObject != _Py_ZeroStruct } -extension Bool : PythonConvertible { +extension Bool : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard isType(pythonObject, type: PyBool_Type) else { return nil } @@ -763,7 +769,7 @@ extension Bool : PythonConvertible { } } -extension String : PythonConvertible { +extension String : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { let pyObject = pythonObject.ownedPyObject defer { Py_DecRef(pyObject) } @@ -808,7 +814,7 @@ fileprivate extension PythonObject { } } -extension Int : PythonConvertible { +extension Int : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { // `PyInt_AsLong` return -1 and sets an error if the Python object is not // integer compatible. @@ -825,7 +831,7 @@ extension Int : PythonConvertible { } } -extension UInt : PythonConvertible { +extension UInt : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { // `PyInt_AsUnsignedLongMask` isn't documented as such, but in fact it does // return -1 and set an error if the Python object is not integer @@ -843,7 +849,7 @@ extension UInt : PythonConvertible { } } -extension Double : PythonConvertible { +extension Double : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { // `PyFloat_AsDouble` return -1 and sets an error if the Python object is // not float compatible. @@ -867,7 +873,7 @@ extension Double : PythonConvertible { // Any `FixedWidthInteger` type is `PythonConvertible` via the `Int`/`UInt` // implementation. -extension Int8 : PythonConvertible { +extension Int8 : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard let i = Int(pythonObject) else { return nil } self.init(i) @@ -878,7 +884,7 @@ extension Int8 : PythonConvertible { } } -extension Int16 : PythonConvertible { +extension Int16 : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard let i = Int(pythonObject) else { return nil } self.init(i) @@ -889,7 +895,7 @@ extension Int16 : PythonConvertible { } } -extension Int32 : PythonConvertible { +extension Int32 : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard let i = Int(pythonObject) else { return nil } self.init(i) @@ -900,7 +906,7 @@ extension Int32 : PythonConvertible { } } -extension Int64 : PythonConvertible { +extension Int64 : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard let i = Int(pythonObject) else { return nil } self.init(i) @@ -911,7 +917,7 @@ extension Int64 : PythonConvertible { } } -extension UInt8 : PythonConvertible { +extension UInt8 : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard let i = UInt(pythonObject) else { return nil } self.init(i) @@ -922,7 +928,7 @@ extension UInt8 : PythonConvertible { } } -extension UInt16 : PythonConvertible { +extension UInt16 : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard let i = UInt(pythonObject) else { return nil } self.init(i) @@ -933,7 +939,7 @@ extension UInt16 : PythonConvertible { } } -extension UInt32 : PythonConvertible { +extension UInt32 : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard let i = UInt(pythonObject) else { return nil } self.init(i) @@ -944,7 +950,7 @@ extension UInt32 : PythonConvertible { } } -extension UInt64 : PythonConvertible { +extension UInt64 : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard let i = UInt(pythonObject) else { return nil } self.init(i) @@ -957,7 +963,7 @@ extension UInt64 : PythonConvertible { // `Float` is `PythonConvertible` via the `Double` implementation. -extension Float : PythonConvertible { +extension Float : PythonConvertible, ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard let v = Double(pythonObject) else { return nil } self.init(v) @@ -973,6 +979,16 @@ extension Float : PythonConvertible { //===----------------------------------------------------------------------===// extension Optional : PythonConvertible where Wrapped : PythonConvertible { + public var pythonObject: PythonObject { + return self?.pythonObject ?? Python.None + } +} + +//===----------------------------------------------------------------------===// +// `ConvertibleFromPython` conformance for `Optional` +//===----------------------------------------------------------------------===// + +extension Optional : ConvertibleFromPython where Wrapped : ConvertibleFromPython { public init?(_ object: PythonObject) { if object == Python.None { self = .none @@ -983,27 +999,16 @@ extension Optional : PythonConvertible where Wrapped : PythonConvertible { self = .some(converted) } } - - public var pythonObject: PythonObject { - return self?.pythonObject ?? Python.None - } } //===----------------------------------------------------------------------===// -// `PythonConvertible` conformance for `Array` and `Dictionary` +// `PythonConvertible` and `ConvertibleFromPython conformance for +// `Array` and `Dictionary` //===----------------------------------------------------------------------===// // `Array` conditionally conforms to `PythonConvertible` if the `Element` // associated type does. extension Array : PythonConvertible where Element : PythonConvertible { - public init?(_ pythonObject: PythonObject) { - self = [] - for elementObject in pythonObject { - guard let element = Element(elementObject) else { return nil } - append(element) - } - } - public var pythonObject: PythonObject { _ = Python // Ensure Python is initialized. let list = PyList_New(count)! @@ -1015,10 +1020,36 @@ extension Array : PythonConvertible where Element : PythonConvertible { } } +extension Array : ConvertibleFromPython where Element : ConvertibleFromPython { + public init?(_ pythonObject: PythonObject) { + self = [] + for elementObject in pythonObject { + guard let element = Element(elementObject) else { return nil } + append(element) + } + } +} + // `Dictionary` conditionally conforms to `PythonConvertible` if the `Key` and // `Value` associated types do. extension Dictionary : PythonConvertible where Key : PythonConvertible, Value : PythonConvertible { + public var pythonObject: PythonObject { + _ = Python // Ensure Python is initialized. + let dict = PyDict_New()! + for (key, value) in self { + let k = key.ownedPyObject + let v = value.ownedPyObject + PyDict_SetItem(dict, k, v) + Py_DecRef(k) + Py_DecRef(v) + } + return PythonObject(consuming: dict) + } +} + +extension Dictionary : ConvertibleFromPython + where Key : ConvertibleFromPython, Value : ConvertibleFromPython { public init?(_ pythonDict: PythonObject) { self = [:] @@ -1042,26 +1073,21 @@ extension Dictionary : PythonConvertible } } } - - public var pythonObject: PythonObject { - _ = Python // Ensure Python is initialized. - let dict = PyDict_New()! - for (key, value) in self { - let k = key.ownedPyObject - let v = value.ownedPyObject - PyDict_SetItem(dict, k, v) - Py_DecRef(k) - Py_DecRef(v) - } - return PythonObject(consuming: dict) - } } //===----------------------------------------------------------------------===// -// `PythonConvertible` conformance for `Range` types +// `PythonConvertible` and `ConvertibleFromPython` conformance +// for `Range` types //===----------------------------------------------------------------------===// extension Range : PythonConvertible where Bound : PythonConvertible { + public var pythonObject: PythonObject { + _ = Python // Ensure Python is initialized. + return Python.slice(lowerBound, upperBound, Python.None) + } +} + +extension Range : ConvertibleFromPython where Bound : ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard isType(pythonObject, type: PySlice_Type) else { return nil } guard let lowerBound = Bound(pythonObject.start), @@ -1071,14 +1097,16 @@ extension Range : PythonConvertible where Bound : PythonConvertible { guard pythonObject.step == Python.None else { return nil } self.init(uncheckedBounds: (lowerBound, upperBound)) } +} +extension PartialRangeFrom : PythonConvertible where Bound : PythonConvertible { public var pythonObject: PythonObject { _ = Python // Ensure Python is initialized. - return Python.slice(lowerBound, upperBound, Python.None) + return Python.slice(lowerBound, Python.None, Python.None) } } -extension PartialRangeFrom : PythonConvertible where Bound : PythonConvertible { +extension PartialRangeFrom : ConvertibleFromPython where Bound : ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard isType(pythonObject, type: PySlice_Type) else { return nil } guard let lowerBound = Bound(pythonObject.start) else { return nil } @@ -1088,14 +1116,16 @@ extension PartialRangeFrom : PythonConvertible where Bound : PythonConvertible { } self.init(lowerBound) } +} +extension PartialRangeUpTo : PythonConvertible where Bound : PythonConvertible { public var pythonObject: PythonObject { _ = Python // Ensure Python is initialized. - return Python.slice(lowerBound, Python.None, Python.None) + return Python.slice(Python.None, upperBound, Python.None) } } -extension PartialRangeUpTo : PythonConvertible where Bound : PythonConvertible { +extension PartialRangeUpTo : ConvertibleFromPython where Bound : ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard isType(pythonObject, type: PySlice_Type) else { return nil } guard let upperBound = Bound(pythonObject.stop) else { return nil } @@ -1105,11 +1135,6 @@ extension PartialRangeUpTo : PythonConvertible where Bound : PythonConvertible { } self.init(upperBound) } - - public var pythonObject: PythonObject { - _ = Python // Ensure Python is initialized. - return Python.slice(Python.None, upperBound, Python.None) - } } //===----------------------------------------------------------------------===// diff --git a/stdlib/public/TensorFlow/PythonConversion.swift b/stdlib/public/TensorFlow/PythonConversion.swift index f2165e7a64dc2..3a32b6e86cc2c 100644 --- a/stdlib/public/TensorFlow/PythonConversion.swift +++ b/stdlib/public/TensorFlow/PythonConversion.swift @@ -167,16 +167,6 @@ extension TensorShape : PythonConvertible { public var pythonObject: PythonObject { return dimensions.pythonObject } - - public init?(_ pythonObject: PythonObject) { - if Python.hasattr(pythonObject, "__len__") == true { - guard let array = [Int32](pythonObject) else { return nil } - self.init(array) - } else { - guard let num = Int32(pythonObject) else { return nil } - self.init(num) - } - } } #endif // canImport(Python) diff --git a/test/TensorFlow/integration.swift b/test/TensorFlow/integration.swift index ed1fd83063c1a..b8714b8825547 100644 --- a/test/TensorFlow/integration.swift +++ b/test/TensorFlow/integration.swift @@ -377,7 +377,7 @@ public func testResourceAndVariants() { // expected-error @+1 {{op named 'TensorDataSet' is not registered in TensorFlow}} #tfop("TensorDataSet", values, Toutput_types$dtype: [Float.tensorFlowDataType], - output_shapes: [TensorShape([1])]) + output_shapes: [TensorShape(1)]) // REGISTER_OP("Iterator") // .Output("handle: resource") diff --git a/test/TensorFlowRuntime/python_conversion.swift b/test/TensorFlowRuntime/python_conversion.swift index d02bd1be0d474..57e4a2f263f4b 100644 --- a/test/TensorFlowRuntime/python_conversion.swift +++ b/test/TensorFlowRuntime/python_conversion.swift @@ -1,7 +1,6 @@ // RUN: %target-run-eager-swift %swift-tensorflow-test-run-extra-options // RUN: %target-run-gpe-swift %swift-tensorflow-test-run-extra-options // REQUIRES: executable_test -// REQUIRES: swift_test_mode_optimize // REQUIRES: tensorflow // // Python conversion and `numpy.ndarray` tests. @@ -60,9 +59,9 @@ PythonConversionTests.test("shaped-array-conversion") { let numpyArray1D = np.ones(28) let reshaped3D = np.reshape(numpyArray1D, [2, 7, 2] as TensorShape) - expectEqual(TensorShape(reshaped3D.shape), [2, 7, 2]) + expectEqual(reshaped3D.shape, [2, 7, 2]) let reshaped2D = np.reshape(reshaped3D, [14, 2] as TensorShape) - expectEqual(TensorShape(reshaped2D.shape), [14, 2]) + expectEqual(reshaped2D.shape, [14, 2]) let numpyArrayStrided = np.array([[1, 2], [1, 2]], dtype: np.int32)[ Python.slice(Python.None), 1] @@ -140,7 +139,6 @@ PythonConversionTests.test("tensor-round-trip") { PythonConversionTests.test("tensor-shape") { let pyArray = [2, 3].pythonObject expectEqual(pyArray, TensorShape(2, 3).pythonObject) - expectEqual(TensorShape(2, 3), TensorShape(pyArray)) } #endif From 99c2cdb1969e8ace42fcabb86d396d04f5eba0d2 Mon Sep 17 00:00:00 2001 From: Richard Wei Date: Mon, 15 Apr 2019 17:43:09 -0400 Subject: [PATCH 06/10] Update stdlib/public/Python/Python.swift Co-Authored-By: realdoug --- stdlib/public/Python/Python.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/public/Python/Python.swift b/stdlib/public/Python/Python.swift index 3bef3d239ee2d..b9b2ea9d2f566 100644 --- a/stdlib/public/Python/Python.swift +++ b/stdlib/public/Python/Python.swift @@ -1106,7 +1106,8 @@ extension PartialRangeFrom : PythonConvertible where Bound : PythonConvertible { } } -extension PartialRangeFrom : ConvertibleFromPython where Bound : ConvertibleFromPython { +extension PartialRangeFrom : ConvertibleFromPython + where Bound : ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard isType(pythonObject, type: PySlice_Type) else { return nil } guard let lowerBound = Bound(pythonObject.start) else { return nil } From aacc10eeda504ca056eaac58a9a2aeea696579ef Mon Sep 17 00:00:00 2001 From: Richard Wei Date: Mon, 15 Apr 2019 17:43:23 -0400 Subject: [PATCH 07/10] Update stdlib/public/Python/Python.swift Co-Authored-By: realdoug --- stdlib/public/Python/Python.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/Python/Python.swift b/stdlib/public/Python/Python.swift index b9b2ea9d2f566..bd0dfc3ae88bc 100644 --- a/stdlib/public/Python/Python.swift +++ b/stdlib/public/Python/Python.swift @@ -1076,7 +1076,7 @@ extension Dictionary : ConvertibleFromPython } //===----------------------------------------------------------------------===// -// `PythonConvertible` and `ConvertibleFromPython` conformance +// `PythonConvertible` and `ConvertibleFromPython` conformances // for `Range` types //===----------------------------------------------------------------------===// From 71dc58700c3f745af68e59bd25fd971ee5c02403 Mon Sep 17 00:00:00 2001 From: Richard Wei Date: Mon, 15 Apr 2019 17:43:31 -0400 Subject: [PATCH 08/10] Update stdlib/public/Python/Python.swift Co-Authored-By: realdoug --- stdlib/public/Python/Python.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/public/Python/Python.swift b/stdlib/public/Python/Python.swift index bd0dfc3ae88bc..3009aad1785e7 100644 --- a/stdlib/public/Python/Python.swift +++ b/stdlib/public/Python/Python.swift @@ -1126,7 +1126,8 @@ extension PartialRangeUpTo : PythonConvertible where Bound : PythonConvertible { } } -extension PartialRangeUpTo : ConvertibleFromPython where Bound : ConvertibleFromPython { +extension PartialRangeUpTo : ConvertibleFromPython + where Bound : ConvertibleFromPython { public init?(_ pythonObject: PythonObject) { guard isType(pythonObject, type: PySlice_Type) else { return nil } guard let upperBound = Bound(pythonObject.stop) else { return nil } From 3783c951522a95bee2440353040d690e38b8ee8d Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Mon, 15 Apr 2019 17:50:41 -0400 Subject: [PATCH 09/10] Update stdlib/public/Python/Python.swift Co-Authored-By: realdoug --- stdlib/public/Python/Python.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/public/Python/Python.swift b/stdlib/public/Python/Python.swift index 3009aad1785e7..4ac12a86d8a0c 100644 --- a/stdlib/public/Python/Python.swift +++ b/stdlib/public/Python/Python.swift @@ -988,7 +988,8 @@ extension Optional : PythonConvertible where Wrapped : PythonConvertible { // `ConvertibleFromPython` conformance for `Optional` //===----------------------------------------------------------------------===// -extension Optional : ConvertibleFromPython where Wrapped : ConvertibleFromPython { +extension Optional : ConvertibleFromPython + where Wrapped : ConvertibleFromPython { public init?(_ object: PythonObject) { if object == Python.None { self = .none From 27f55218797c8d6461744bf4d0b3a4b79bfd2797 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Tue, 16 Apr 2019 00:03:16 -0700 Subject: [PATCH 10/10] Fix "shaped-array-conversion" test. NumPy arrays have tuple shapes, not list shapes. --- test/TensorFlowRuntime/python_conversion.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/TensorFlowRuntime/python_conversion.swift b/test/TensorFlowRuntime/python_conversion.swift index 57e4a2f263f4b..fbba5e496e2b2 100644 --- a/test/TensorFlowRuntime/python_conversion.swift +++ b/test/TensorFlowRuntime/python_conversion.swift @@ -59,9 +59,9 @@ PythonConversionTests.test("shaped-array-conversion") { let numpyArray1D = np.ones(28) let reshaped3D = np.reshape(numpyArray1D, [2, 7, 2] as TensorShape) - expectEqual(reshaped3D.shape, [2, 7, 2]) + expectEqual(reshaped3D.shape, Python.tuple([2, 7, 2])) let reshaped2D = np.reshape(reshaped3D, [14, 2] as TensorShape) - expectEqual(reshaped2D.shape, [14, 2]) + expectEqual(reshaped2D.shape, Python.tuple([14, 2])) let numpyArrayStrided = np.array([[1, 2], [1, 2]], dtype: np.int32)[ Python.slice(Python.None), 1]