15
15
// specific language governing permissions and limitations
16
16
// under the License.
17
17
18
- use pyo3:: exceptions:: { PyException , PyNotImplementedError } ;
18
+ use pyo3:: exceptions:: PyException ;
19
19
use pyo3:: prelude:: * ;
20
20
use pyo3:: types:: PyList ;
21
- use pyo3:: PyNativeType ;
22
21
23
22
use crate :: arrow:: array:: ArrayData ;
24
23
use crate :: arrow:: pyarrow:: PyArrowConvert ;
@@ -49,8 +48,13 @@ impl PyArrowConvert for ScalarValue {
49
48
Ok ( scalar)
50
49
}
51
50
52
- fn to_pyarrow ( & self , _py : Python ) -> PyResult < PyObject > {
53
- Err ( PyNotImplementedError :: new_err ( "Not implemented" ) )
51
+ fn to_pyarrow ( & self , py : Python ) -> PyResult < PyObject > {
52
+ let array = self . to_array ( ) ;
53
+ // convert to pyarrow array using C data interface
54
+ let pyarray = array. data_ref ( ) . clone ( ) . into_py ( py) ;
55
+ let pyscalar = pyarray. call_method1 ( py, "__getitem__" , ( 0 , ) ) ?;
56
+
57
+ Ok ( pyscalar)
54
58
}
55
59
}
56
60
@@ -65,3 +69,82 @@ impl<'a> IntoPy<PyObject> for ScalarValue {
65
69
self . to_pyarrow ( py) . unwrap ( )
66
70
}
67
71
}
72
+
73
+ #[ cfg( test) ]
74
+ mod tests {
75
+ use super :: * ;
76
+ use pyo3:: prepare_freethreaded_python;
77
+ use pyo3:: py_run;
78
+ use pyo3:: types:: PyDict ;
79
+ use pyo3:: Python ;
80
+
81
+ fn init_python ( ) {
82
+ prepare_freethreaded_python ( ) ;
83
+ Python :: with_gil ( |py| {
84
+ if let Err ( err) = py. run ( "import pyarrow" , None , None ) {
85
+ let locals = PyDict :: new ( py) ;
86
+ py. run (
87
+ "import sys; executable = sys.executable; python_path = sys.path" ,
88
+ None ,
89
+ Some ( locals) ,
90
+ )
91
+ . expect ( "Couldn't get python info" ) ;
92
+ let executable: String =
93
+ locals. get_item ( "executable" ) . unwrap ( ) . extract ( ) . unwrap ( ) ;
94
+ let python_path: Vec < & str > =
95
+ locals. get_item ( "python_path" ) . unwrap ( ) . extract ( ) . unwrap ( ) ;
96
+
97
+ Err ( err) . expect (
98
+ format ! (
99
+ "pyarrow not found\n Executable: {}\n Python path: {:?}\n \
100
+ HINT: try `pip install pyarrow`\n \
101
+ NOTE: On Mac OS, you must compile against a Framework Python \
102
+ (default in python.org installers and brew, but not pyenv)\n \
103
+ NOTE: On Mac OS, PYO3 might point to incorrect Python library \
104
+ path when using virtual environments. Try \
105
+ `export PYTHONPATH=$(python -c \" import sys; print(sys.path[-1])\" )`\n ",
106
+ executable, python_path
107
+ )
108
+ . as_ref ( ) ,
109
+ )
110
+ }
111
+ } )
112
+ }
113
+
114
+ #[ test]
115
+ fn test_roundtrip ( ) {
116
+ init_python ( ) ;
117
+
118
+ let example_scalars = vec ! [
119
+ ScalarValue :: Boolean ( Some ( true ) ) ,
120
+ ScalarValue :: Int32 ( Some ( 23 ) ) ,
121
+ ScalarValue :: Float64 ( Some ( 12.34 ) ) ,
122
+ ScalarValue :: Utf8 ( Some ( "Hello!" . to_string( ) ) ) ,
123
+ ScalarValue :: Date32 ( Some ( 1234 ) ) ,
124
+ ] ;
125
+
126
+ Python :: with_gil ( |py| {
127
+ for scalar in example_scalars. iter ( ) {
128
+ let result =
129
+ ScalarValue :: from_pyarrow ( scalar. to_pyarrow ( py) . unwrap ( ) . as_ref ( py) )
130
+ . unwrap ( ) ;
131
+ assert_eq ! ( scalar, & result) ;
132
+ }
133
+ } ) ;
134
+ }
135
+
136
+ #[ test]
137
+ fn test_py_scalar ( ) {
138
+ init_python ( ) ;
139
+
140
+ Python :: with_gil ( |py| {
141
+ let scalar_float = ScalarValue :: Float64 ( Some ( 12.34 ) ) ;
142
+ let py_float = scalar_float. into_py ( py) . call_method0 ( py, "as_py" ) . unwrap ( ) ;
143
+ py_run ! ( py, py_float, "assert py_float == 12.34" ) ;
144
+
145
+ let scalar_string = ScalarValue :: Utf8 ( Some ( "Hello!" . to_string ( ) ) ) ;
146
+ let py_string = scalar_string. into_py ( py) . call_method0 ( py, "as_py" ) . unwrap ( ) ;
147
+ py_run ! ( py, py_string, "assert py_string == 'Hello!'" ) ;
148
+ } ) ;
149
+ }
150
+ }
0 commit comments