@@ -147,14 +147,20 @@ extension PythonObject : CustomReflectable {
147
147
//===----------------------------------------------------------------------===//
148
148
149
149
public protocol PythonConvertible {
150
+ /// A `PythonObject` instance representing this value.
151
+ var pythonObject : PythonObject { get }
152
+ }
153
+
154
+ //===----------------------------------------------------------------------===//
155
+ // `PythonConvertible` protocol
156
+ //===----------------------------------------------------------------------===//
157
+
158
+ public protocol ConvertibleFromPython {
150
159
/// Creates a new instance from the given `PythonObject`, if possible.
151
160
/// - Note: Conversion may fail if the given `PythonObject` instance is
152
161
/// incompatible (e.g. a Python `string` object cannot be converted into an
153
162
/// `Int`).
154
163
init ? ( _ object: PythonObject )
155
-
156
- /// A `PythonObject` instance representing this value.
157
- var pythonObject : PythonObject { get }
158
164
}
159
165
160
166
public extension PythonObject {
@@ -177,7 +183,7 @@ fileprivate extension PythonConvertible {
177
183
}
178
184
179
185
// `PythonObject` is trivially `PythonConvertible`.
180
- extension PythonObject : PythonConvertible {
186
+ extension PythonObject : PythonConvertible , ConvertibleFromPython {
181
187
public init ( _ object: PythonObject ) {
182
188
self . init ( consuming: object. ownedPyObject)
183
189
}
@@ -747,7 +753,7 @@ private func isType(_ object: PythonObject,
747
753
return pyObject != _Py_ZeroStruct
748
754
}
749
755
750
- extension Bool : PythonConvertible {
756
+ extension Bool : PythonConvertible , ConvertibleFromPython {
751
757
public init ? ( _ pythonObject: PythonObject ) {
752
758
guard isType ( pythonObject, type: PyBool_Type) else { return nil }
753
759
@@ -763,7 +769,7 @@ extension Bool : PythonConvertible {
763
769
}
764
770
}
765
771
766
- extension String : PythonConvertible {
772
+ extension String : PythonConvertible , ConvertibleFromPython {
767
773
public init ? ( _ pythonObject: PythonObject ) {
768
774
let pyObject = pythonObject. ownedPyObject
769
775
defer { Py_DecRef ( pyObject) }
@@ -808,7 +814,7 @@ fileprivate extension PythonObject {
808
814
}
809
815
}
810
816
811
- extension Int : PythonConvertible {
817
+ extension Int : PythonConvertible , ConvertibleFromPython {
812
818
public init ? ( _ pythonObject: PythonObject ) {
813
819
// `PyInt_AsLong` return -1 and sets an error if the Python object is not
814
820
// integer compatible.
@@ -825,7 +831,7 @@ extension Int : PythonConvertible {
825
831
}
826
832
}
827
833
828
- extension UInt : PythonConvertible {
834
+ extension UInt : PythonConvertible , ConvertibleFromPython {
829
835
public init ? ( _ pythonObject: PythonObject ) {
830
836
// `PyInt_AsUnsignedLongMask` isn't documented as such, but in fact it does
831
837
// return -1 and set an error if the Python object is not integer
@@ -843,7 +849,7 @@ extension UInt : PythonConvertible {
843
849
}
844
850
}
845
851
846
- extension Double : PythonConvertible {
852
+ extension Double : PythonConvertible , ConvertibleFromPython {
847
853
public init ? ( _ pythonObject: PythonObject ) {
848
854
// `PyFloat_AsDouble` return -1 and sets an error if the Python object is
849
855
// not float compatible.
@@ -867,7 +873,7 @@ extension Double : PythonConvertible {
867
873
// Any `FixedWidthInteger` type is `PythonConvertible` via the `Int`/`UInt`
868
874
// implementation.
869
875
870
- extension Int8 : PythonConvertible {
876
+ extension Int8 : PythonConvertible , ConvertibleFromPython {
871
877
public init ? ( _ pythonObject: PythonObject ) {
872
878
guard let i = Int ( pythonObject) else { return nil }
873
879
self . init ( i)
@@ -878,7 +884,7 @@ extension Int8 : PythonConvertible {
878
884
}
879
885
}
880
886
881
- extension Int16 : PythonConvertible {
887
+ extension Int16 : PythonConvertible , ConvertibleFromPython {
882
888
public init ? ( _ pythonObject: PythonObject ) {
883
889
guard let i = Int ( pythonObject) else { return nil }
884
890
self . init ( i)
@@ -889,7 +895,7 @@ extension Int16 : PythonConvertible {
889
895
}
890
896
}
891
897
892
- extension Int32 : PythonConvertible {
898
+ extension Int32 : PythonConvertible , ConvertibleFromPython {
893
899
public init ? ( _ pythonObject: PythonObject ) {
894
900
guard let i = Int ( pythonObject) else { return nil }
895
901
self . init ( i)
@@ -900,7 +906,7 @@ extension Int32 : PythonConvertible {
900
906
}
901
907
}
902
908
903
- extension Int64 : PythonConvertible {
909
+ extension Int64 : PythonConvertible , ConvertibleFromPython {
904
910
public init ? ( _ pythonObject: PythonObject ) {
905
911
guard let i = Int ( pythonObject) else { return nil }
906
912
self . init ( i)
@@ -911,7 +917,7 @@ extension Int64 : PythonConvertible {
911
917
}
912
918
}
913
919
914
- extension UInt8 : PythonConvertible {
920
+ extension UInt8 : PythonConvertible , ConvertibleFromPython {
915
921
public init ? ( _ pythonObject: PythonObject ) {
916
922
guard let i = UInt ( pythonObject) else { return nil }
917
923
self . init ( i)
@@ -922,7 +928,7 @@ extension UInt8 : PythonConvertible {
922
928
}
923
929
}
924
930
925
- extension UInt16 : PythonConvertible {
931
+ extension UInt16 : PythonConvertible , ConvertibleFromPython {
926
932
public init ? ( _ pythonObject: PythonObject ) {
927
933
guard let i = UInt ( pythonObject) else { return nil }
928
934
self . init ( i)
@@ -933,7 +939,7 @@ extension UInt16 : PythonConvertible {
933
939
}
934
940
}
935
941
936
- extension UInt32 : PythonConvertible {
942
+ extension UInt32 : PythonConvertible , ConvertibleFromPython {
937
943
public init ? ( _ pythonObject: PythonObject ) {
938
944
guard let i = UInt ( pythonObject) else { return nil }
939
945
self . init ( i)
@@ -944,7 +950,7 @@ extension UInt32 : PythonConvertible {
944
950
}
945
951
}
946
952
947
- extension UInt64 : PythonConvertible {
953
+ extension UInt64 : PythonConvertible , ConvertibleFromPython {
948
954
public init ? ( _ pythonObject: PythonObject ) {
949
955
guard let i = UInt ( pythonObject) else { return nil }
950
956
self . init ( i)
@@ -957,7 +963,7 @@ extension UInt64 : PythonConvertible {
957
963
958
964
// `Float` is `PythonConvertible` via the `Double` implementation.
959
965
960
- extension Float : PythonConvertible {
966
+ extension Float : PythonConvertible , ConvertibleFromPython {
961
967
public init ? ( _ pythonObject: PythonObject ) {
962
968
guard let v = Double ( pythonObject) else { return nil }
963
969
self . init ( v)
@@ -973,6 +979,17 @@ extension Float : PythonConvertible {
973
979
//===----------------------------------------------------------------------===//
974
980
975
981
extension Optional : PythonConvertible where Wrapped : PythonConvertible {
982
+ public var pythonObject : PythonObject {
983
+ return self ? . pythonObject ?? Python . None
984
+ }
985
+ }
986
+
987
+ //===----------------------------------------------------------------------===//
988
+ // `ConvertibleFromPython` conformance for `Optional`
989
+ //===----------------------------------------------------------------------===//
990
+
991
+ extension Optional : ConvertibleFromPython
992
+ where Wrapped : ConvertibleFromPython {
976
993
public init ? ( _ object: PythonObject ) {
977
994
if object == Python . None {
978
995
self = . none
@@ -983,27 +1000,16 @@ extension Optional : PythonConvertible where Wrapped : PythonConvertible {
983
1000
self = . some( converted)
984
1001
}
985
1002
}
986
-
987
- public var pythonObject : PythonObject {
988
- return self ? . pythonObject ?? Python . None
989
- }
990
1003
}
991
1004
992
1005
//===----------------------------------------------------------------------===//
993
- // `PythonConvertible` conformance for `Array` and `Dictionary`
1006
+ // `PythonConvertible` and `ConvertibleFromPython conformance for
1007
+ // `Array` and `Dictionary`
994
1008
//===----------------------------------------------------------------------===//
995
1009
996
1010
// `Array` conditionally conforms to `PythonConvertible` if the `Element`
997
1011
// associated type does.
998
1012
extension Array : PythonConvertible where Element : PythonConvertible {
999
- public init ? ( _ pythonObject: PythonObject ) {
1000
- self = [ ]
1001
- for elementObject in pythonObject {
1002
- guard let element = Element ( elementObject) else { return nil }
1003
- append ( element)
1004
- }
1005
- }
1006
-
1007
1013
public var pythonObject : PythonObject {
1008
1014
_ = Python // Ensure Python is initialized.
1009
1015
let list = PyList_New ( count) !
@@ -1015,10 +1021,36 @@ extension Array : PythonConvertible where Element : PythonConvertible {
1015
1021
}
1016
1022
}
1017
1023
1024
+ extension Array : ConvertibleFromPython where Element : ConvertibleFromPython {
1025
+ public init ? ( _ pythonObject: PythonObject ) {
1026
+ self = [ ]
1027
+ for elementObject in pythonObject {
1028
+ guard let element = Element ( elementObject) else { return nil }
1029
+ append ( element)
1030
+ }
1031
+ }
1032
+ }
1033
+
1018
1034
// `Dictionary` conditionally conforms to `PythonConvertible` if the `Key` and
1019
1035
// `Value` associated types do.
1020
1036
extension Dictionary : PythonConvertible
1021
1037
where Key : PythonConvertible , Value : PythonConvertible {
1038
+ public var pythonObject : PythonObject {
1039
+ _ = Python // Ensure Python is initialized.
1040
+ let dict = PyDict_New ( ) !
1041
+ for (key, value) in self {
1042
+ let k = key. ownedPyObject
1043
+ let v = value. ownedPyObject
1044
+ PyDict_SetItem ( dict, k, v)
1045
+ Py_DecRef ( k)
1046
+ Py_DecRef ( v)
1047
+ }
1048
+ return PythonObject ( consuming: dict)
1049
+ }
1050
+ }
1051
+
1052
+ extension Dictionary : ConvertibleFromPython
1053
+ where Key : ConvertibleFromPython , Value : ConvertibleFromPython {
1022
1054
public init ? ( _ pythonDict: PythonObject ) {
1023
1055
self = [ : ]
1024
1056
@@ -1042,26 +1074,21 @@ extension Dictionary : PythonConvertible
1042
1074
}
1043
1075
}
1044
1076
}
1045
-
1046
- public var pythonObject : PythonObject {
1047
- _ = Python // Ensure Python is initialized.
1048
- let dict = PyDict_New ( ) !
1049
- for (key, value) in self {
1050
- let k = key. ownedPyObject
1051
- let v = value. ownedPyObject
1052
- PyDict_SetItem ( dict, k, v)
1053
- Py_DecRef ( k)
1054
- Py_DecRef ( v)
1055
- }
1056
- return PythonObject ( consuming: dict)
1057
- }
1058
1077
}
1059
1078
1060
1079
//===----------------------------------------------------------------------===//
1061
- // `PythonConvertible` conformance for `Range` types
1080
+ // `PythonConvertible` and `ConvertibleFromPython` conformances
1081
+ // for `Range` types
1062
1082
//===----------------------------------------------------------------------===//
1063
1083
1064
1084
extension Range : PythonConvertible where Bound : PythonConvertible {
1085
+ public var pythonObject : PythonObject {
1086
+ _ = Python // Ensure Python is initialized.
1087
+ return Python . slice ( lowerBound, upperBound, Python . None)
1088
+ }
1089
+ }
1090
+
1091
+ extension Range : ConvertibleFromPython where Bound : ConvertibleFromPython {
1065
1092
public init ? ( _ pythonObject: PythonObject ) {
1066
1093
guard isType ( pythonObject, type: PySlice_Type) else { return nil }
1067
1094
guard let lowerBound = Bound ( pythonObject. start) ,
@@ -1071,14 +1098,17 @@ extension Range : PythonConvertible where Bound : PythonConvertible {
1071
1098
guard pythonObject. step == Python . None else { return nil }
1072
1099
self . init ( uncheckedBounds: ( lowerBound, upperBound) )
1073
1100
}
1101
+ }
1074
1102
1103
+ extension PartialRangeFrom : PythonConvertible where Bound : PythonConvertible {
1075
1104
public var pythonObject : PythonObject {
1076
1105
_ = Python // Ensure Python is initialized.
1077
- return Python . slice ( lowerBound, upperBound , Python . None)
1106
+ return Python . slice ( lowerBound, Python . None , Python . None)
1078
1107
}
1079
1108
}
1080
1109
1081
- extension PartialRangeFrom : PythonConvertible where Bound : PythonConvertible {
1110
+ extension PartialRangeFrom : ConvertibleFromPython
1111
+ where Bound : ConvertibleFromPython {
1082
1112
public init ? ( _ pythonObject: PythonObject ) {
1083
1113
guard isType ( pythonObject, type: PySlice_Type) else { return nil }
1084
1114
guard let lowerBound = Bound ( pythonObject. start) else { return nil }
@@ -1088,14 +1118,17 @@ extension PartialRangeFrom : PythonConvertible where Bound : PythonConvertible {
1088
1118
}
1089
1119
self . init ( lowerBound)
1090
1120
}
1121
+ }
1091
1122
1123
+ extension PartialRangeUpTo : PythonConvertible where Bound : PythonConvertible {
1092
1124
public var pythonObject : PythonObject {
1093
1125
_ = Python // Ensure Python is initialized.
1094
- return Python . slice ( lowerBound , Python . None, Python . None)
1126
+ return Python . slice ( Python . None, upperBound , Python . None)
1095
1127
}
1096
1128
}
1097
1129
1098
- extension PartialRangeUpTo : PythonConvertible where Bound : PythonConvertible {
1130
+ extension PartialRangeUpTo : ConvertibleFromPython
1131
+ where Bound : ConvertibleFromPython {
1099
1132
public init ? ( _ pythonObject: PythonObject ) {
1100
1133
guard isType ( pythonObject, type: PySlice_Type) else { return nil }
1101
1134
guard let upperBound = Bound ( pythonObject. stop) else { return nil }
@@ -1105,11 +1138,6 @@ extension PartialRangeUpTo : PythonConvertible where Bound : PythonConvertible {
1105
1138
}
1106
1139
self . init ( upperBound)
1107
1140
}
1108
-
1109
- public var pythonObject : PythonObject {
1110
- _ = Python // Ensure Python is initialized.
1111
- return Python . slice ( Python . None, upperBound, Python . None)
1112
- }
1113
1141
}
1114
1142
1115
1143
//===----------------------------------------------------------------------===//
0 commit comments