1
1
use crate :: conversion:: IntoPyObject ;
2
2
use crate :: ffi_ptr_ext:: FfiPtrExt ;
3
3
use crate :: instance:: Bound ;
4
+ use crate :: sync:: GILOnceCell ;
4
5
use crate :: types:: any:: PyAnyMethods ;
5
- use crate :: types:: PyString ;
6
- use crate :: { ffi, FromPyObject , PyAny , PyObject , PyResult , Python } ;
6
+ use crate :: { ffi, FromPyObject , IntoPyObjectExt , PyAny , PyErr , PyObject , PyResult , Python } ;
7
7
#[ allow( deprecated) ]
8
8
use crate :: { IntoPy , ToPyObject } ;
9
9
use std:: borrow:: Cow ;
10
- use std:: convert:: Infallible ;
11
10
use std:: ffi:: OsString ;
12
11
use std:: path:: { Path , PathBuf } ;
13
12
14
13
#[ allow( deprecated) ]
15
14
impl ToPyObject for Path {
16
15
#[ inline]
17
16
fn to_object ( & self , py : Python < ' _ > ) -> PyObject {
18
- self . into_pyobject ( py ) . unwrap ( ) . into_any ( ) . unbind ( )
17
+ self . as_os_str ( ) . into_py_any ( py ) . unwrap ( )
19
18
}
20
19
}
21
20
@@ -33,25 +32,28 @@ impl FromPyObject<'_> for PathBuf {
33
32
impl IntoPy < PyObject > for & Path {
34
33
#[ inline]
35
34
fn into_py ( self , py : Python < ' _ > ) -> PyObject {
36
- self . into_pyobject ( py) . unwrap ( ) . into_any ( ) . unbind ( )
35
+ self . to_object ( py)
37
36
}
38
37
}
39
38
40
39
impl < ' py > IntoPyObject < ' py > for & Path {
41
- type Target = PyString ;
40
+ type Target = PyAny ;
42
41
type Output = Bound < ' py , Self :: Target > ;
43
- type Error = Infallible ;
42
+ type Error = PyErr ;
44
43
45
44
#[ inline]
46
45
fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
47
- self . as_os_str ( ) . into_pyobject ( py)
46
+ static PY_PATH : GILOnceCell < PyObject > = GILOnceCell :: new ( ) ;
47
+ PY_PATH
48
+ . import ( py, "pathlib" , "Path" ) ?
49
+ . call ( ( self . as_os_str ( ) , ) , None )
48
50
}
49
51
}
50
52
51
53
impl < ' py > IntoPyObject < ' py > for & & Path {
52
- type Target = PyString ;
54
+ type Target = PyAny ;
53
55
type Output = Bound < ' py , Self :: Target > ;
54
- type Error = Infallible ;
56
+ type Error = PyErr ;
55
57
56
58
#[ inline]
57
59
fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
@@ -63,90 +65,90 @@ impl<'py> IntoPyObject<'py> for &&Path {
63
65
impl ToPyObject for Cow < ' _ , Path > {
64
66
#[ inline]
65
67
fn to_object ( & self , py : Python < ' _ > ) -> PyObject {
66
- self . into_pyobject ( py ) . unwrap ( ) . into_any ( ) . unbind ( )
68
+ ( * * self ) . to_object ( py )
67
69
}
68
70
}
69
71
70
72
#[ allow( deprecated) ]
71
73
impl IntoPy < PyObject > for Cow < ' _ , Path > {
72
74
#[ inline]
73
75
fn into_py ( self , py : Python < ' _ > ) -> PyObject {
74
- self . into_pyobject ( py ) . unwrap ( ) . into_any ( ) . unbind ( )
76
+ ( * self ) . to_object ( py )
75
77
}
76
78
}
77
79
78
80
impl < ' py > IntoPyObject < ' py > for Cow < ' _ , Path > {
79
- type Target = PyString ;
81
+ type Target = PyAny ;
80
82
type Output = Bound < ' py , Self :: Target > ;
81
- type Error = Infallible ;
83
+ type Error = PyErr ;
82
84
83
85
#[ inline]
84
86
fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
85
- self . as_os_str ( ) . into_pyobject ( py)
87
+ ( * self ) . into_pyobject ( py)
86
88
}
87
89
}
88
90
89
91
impl < ' py > IntoPyObject < ' py > for & Cow < ' _ , Path > {
90
- type Target = PyString ;
92
+ type Target = PyAny ;
91
93
type Output = Bound < ' py , Self :: Target > ;
92
- type Error = Infallible ;
94
+ type Error = PyErr ;
93
95
94
96
#[ inline]
95
97
fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
96
- self . as_os_str ( ) . into_pyobject ( py)
98
+ ( & * * self ) . into_pyobject ( py)
97
99
}
98
100
}
99
101
100
102
#[ allow( deprecated) ]
101
103
impl ToPyObject for PathBuf {
102
104
#[ inline]
103
105
fn to_object ( & self , py : Python < ' _ > ) -> PyObject {
104
- self . into_pyobject ( py ) . unwrap ( ) . into_any ( ) . unbind ( )
106
+ ( * * self ) . to_object ( py )
105
107
}
106
108
}
107
109
108
110
#[ allow( deprecated) ]
109
111
impl IntoPy < PyObject > for PathBuf {
110
112
#[ inline]
111
113
fn into_py ( self , py : Python < ' _ > ) -> PyObject {
112
- self . into_pyobject ( py ) . unwrap ( ) . into_any ( ) . unbind ( )
114
+ ( * self ) . to_object ( py )
113
115
}
114
116
}
115
117
116
118
impl < ' py > IntoPyObject < ' py > for PathBuf {
117
- type Target = PyString ;
119
+ type Target = PyAny ;
118
120
type Output = Bound < ' py , Self :: Target > ;
119
- type Error = Infallible ;
121
+ type Error = PyErr ;
120
122
121
123
#[ inline]
122
124
fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
123
- self . as_os_str ( ) . into_pyobject ( py)
125
+ ( & self ) . into_pyobject ( py)
124
126
}
125
127
}
126
128
127
129
#[ allow( deprecated) ]
128
130
impl IntoPy < PyObject > for & PathBuf {
129
131
#[ inline]
130
132
fn into_py ( self , py : Python < ' _ > ) -> PyObject {
131
- self . into_pyobject ( py ) . unwrap ( ) . into_any ( ) . unbind ( )
133
+ ( * * self ) . to_object ( py )
132
134
}
133
135
}
134
136
135
137
impl < ' py > IntoPyObject < ' py > for & PathBuf {
136
- type Target = PyString ;
138
+ type Target = PyAny ;
137
139
type Output = Bound < ' py , Self :: Target > ;
138
- type Error = Infallible ;
140
+ type Error = PyErr ;
139
141
140
142
#[ inline]
141
143
fn into_pyobject ( self , py : Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
142
- self . as_os_str ( ) . into_pyobject ( py)
144
+ ( & * * self ) . into_pyobject ( py)
143
145
}
144
146
}
145
147
146
148
#[ cfg( test) ]
147
149
mod tests {
148
150
use crate :: types:: { PyAnyMethods , PyString , PyStringMethods } ;
149
- use crate :: { BoundObject , IntoPyObject , Python } ;
151
+ use crate :: { IntoPyObject , IntoPyObjectExt , PyObject , Python } ;
150
152
use std:: borrow:: Cow ;
151
153
use std:: fmt:: Debug ;
152
154
use std:: path:: { Path , PathBuf } ;
@@ -180,10 +182,42 @@ mod tests {
180
182
T : IntoPyObject < ' py > + AsRef < Path > + Debug + Clone ,
181
183
T :: Error : Debug ,
182
184
{
183
- let pyobject = obj. clone ( ) . into_pyobject ( py) . unwrap ( ) . into_any ( ) ;
184
- let pystring = pyobject. as_borrowed ( ) . downcast :: < PyString > ( ) . unwrap ( ) ;
185
+ let pyobject = obj. clone ( ) . into_bound_py_any ( py) . unwrap ( ) ;
186
+ let roundtripped_obj: PathBuf = pyobject. extract ( ) . unwrap ( ) ;
187
+ assert_eq ! ( obj. as_ref( ) , roundtripped_obj. as_path( ) ) ;
188
+ }
189
+ let path = Path :: new ( "Hello\0 \n 🐍" ) ;
190
+ test_roundtrip :: < & Path > ( py, path) ;
191
+ test_roundtrip :: < Cow < ' _ , Path > > ( py, Cow :: Borrowed ( path) ) ;
192
+ test_roundtrip :: < Cow < ' _ , Path > > ( py, Cow :: Owned ( path. to_path_buf ( ) ) ) ;
193
+ test_roundtrip :: < PathBuf > ( py, path. to_path_buf ( ) ) ;
194
+ } ) ;
195
+ }
196
+
197
+ #[ test]
198
+ fn test_from_pystring ( ) {
199
+ Python :: with_gil ( |py| {
200
+ let path = "Hello\0 \n 🐍" ;
201
+ let pystring = PyString :: new ( py, path) ;
202
+ let roundtrip: PathBuf = pystring. extract ( ) . unwrap ( ) ;
203
+ assert_eq ! ( roundtrip, Path :: new( path) ) ;
204
+ } ) ;
205
+ }
206
+
207
+ #[ test]
208
+ #[ allow( deprecated) ]
209
+ fn test_intopy_string ( ) {
210
+ use crate :: IntoPy ;
211
+
212
+ Python :: with_gil ( |py| {
213
+ fn test_roundtrip < T > ( py : Python < ' _ > , obj : T )
214
+ where
215
+ T : IntoPy < PyObject > + AsRef < Path > + Debug + Clone ,
216
+ {
217
+ let pyobject = obj. clone ( ) . into_py ( py) . into_bound ( py) ;
218
+ let pystring = pyobject. downcast_exact :: < PyString > ( ) . unwrap ( ) ;
185
219
assert_eq ! ( pystring. to_string_lossy( ) , obj. as_ref( ) . to_string_lossy( ) ) ;
186
- let roundtripped_obj: PathBuf = pystring . extract ( ) . unwrap ( ) ;
220
+ let roundtripped_obj: PathBuf = pyobject . extract ( ) . unwrap ( ) ;
187
221
assert_eq ! ( obj. as_ref( ) , roundtripped_obj. as_path( ) ) ;
188
222
}
189
223
let path = Path :: new ( "Hello\0 \n 🐍" ) ;
0 commit comments