@@ -67,54 +67,42 @@ impl<'py> Py2<'py, PyAny> {
67
67
}
68
68
69
69
impl < ' py , T > Py2 < ' py , T > {
70
- /// Helper to cast to Py2<'py, T >
70
+ /// Helper to cast to Py2<'py, PyAny >
71
71
pub ( crate ) fn as_any ( & self ) -> & Py2 < ' py , PyAny > {
72
+ // Safety: all Py2<T> have the same memory layout, and all Py2<T> are valid Py2<PyAny>
72
73
unsafe { std:: mem:: transmute ( self ) }
73
74
}
74
75
}
75
76
76
- impl < ' py , T > std:: fmt:: Debug for Py2 < ' py , T >
77
- where
78
- Self : Deref < Target = Py2 < ' py , PyAny > > ,
79
- {
77
+ impl < ' py , T > std:: fmt:: Debug for Py2 < ' py , T > {
80
78
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
81
- let s = self . repr ( ) . or ( Err ( std :: fmt :: Error ) ) ? ;
82
- f . write_str ( & s . as_gil_ref ( ) . to_string_lossy ( ) )
79
+ let any = self . as_any ( ) ;
80
+ python_format ( any , any . repr ( ) , f )
83
81
}
84
82
}
85
83
86
- impl < ' py , T > std:: fmt:: Display for Py2 < ' py , T >
87
- where
88
- Self : Deref < Target = Py2 < ' py , PyAny > > ,
89
- {
84
+ impl < ' py , T > std:: fmt:: Display for Py2 < ' py , T > {
90
85
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
91
- match self . str ( ) {
92
- Result :: Ok ( s) => return f. write_str ( & s. as_gil_ref ( ) . to_string_lossy ( ) ) ,
93
- Result :: Err ( err) => {
94
- err. write_unraisable ( self . py ( ) , std:: option:: Option :: Some ( self . as_gil_ref ( ) ) )
95
- }
96
- }
97
-
98
- match self . get_type ( ) . name ( ) {
99
- Result :: Ok ( name) => std:: write!( f, "<unprintable {} object>" , name) ,
100
- Result :: Err ( _err) => f. write_str ( "<unprintable object>" ) ,
101
- }
86
+ let any = self . as_any ( ) ;
87
+ python_format ( any, any. str ( ) , f)
102
88
}
103
89
}
104
90
105
- impl < ' py > std:: fmt:: Display for Py2 < ' py , PyAny > {
106
- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
107
- match self . str ( ) {
108
- Result :: Ok ( s) => return f. write_str ( & s. as_gil_ref ( ) . to_string_lossy ( ) ) ,
109
- Result :: Err ( err) => {
110
- err. write_unraisable ( self . py ( ) , std:: option:: Option :: Some ( self . as_gil_ref ( ) ) )
111
- }
91
+ fn python_format (
92
+ any : & Py2 < ' _ , PyAny > ,
93
+ format_result : PyResult < Py2 < ' _ , PyString > > ,
94
+ f : & mut std:: fmt:: Formatter < ' _ > ,
95
+ ) -> Result < ( ) , std:: fmt:: Error > {
96
+ match format_result {
97
+ Result :: Ok ( s) => return f. write_str ( & s. as_gil_ref ( ) . to_string_lossy ( ) ) ,
98
+ Result :: Err ( err) => {
99
+ err. write_unraisable ( any. py ( ) , std:: option:: Option :: Some ( any. as_gil_ref ( ) ) )
112
100
}
101
+ }
113
102
114
- match self . get_type ( ) . name ( ) {
115
- Result :: Ok ( name) => std:: write!( f, "<unprintable {} object>" , name) ,
116
- Result :: Err ( _err) => f. write_str ( "<unprintable object>" ) ,
117
- }
103
+ match any. get_type ( ) . name ( ) {
104
+ Result :: Ok ( name) => std:: write!( f, "<unprintable {} object>" , name) ,
105
+ Result :: Err ( _err) => f. write_str ( "<unprintable object>" ) ,
118
106
}
119
107
}
120
108
@@ -126,14 +114,16 @@ where
126
114
127
115
#[ inline]
128
116
fn deref ( & self ) -> & Py2 < ' py , PyAny > {
129
- :: std :: convert :: AsRef :: as_ref ( self )
117
+ self . as_any ( )
130
118
}
131
119
}
132
120
133
- impl < ' py , T > AsRef < Py2 < ' py , PyAny > > for Py2 < ' py , T > {
121
+ impl < ' py , T > AsRef < Py2 < ' py , PyAny > > for Py2 < ' py , T >
122
+ where
123
+ T : AsRef < PyAny > ,
124
+ {
134
125
fn as_ref ( & self ) -> & Py2 < ' py , PyAny > {
135
- // Safety: &Py2<T> has the same layout as &Py2<PyAny>
136
- unsafe { std:: mem:: transmute ( self ) }
126
+ self . as_any ( )
137
127
}
138
128
}
139
129
@@ -176,9 +166,7 @@ impl<'py, T> Py2<'py, T> {
176
166
/// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)).
177
167
#[ inline]
178
168
pub fn into_ptr ( self ) -> * mut ffi:: PyObject {
179
- let ptr = ( self . 1 ) . 0 . as_ptr ( ) ;
180
- std:: mem:: forget ( self ) ;
181
- ptr
169
+ self . into_non_null ( ) . as_ptr ( )
182
170
}
183
171
184
172
/// Internal helper to convert e.g. &'a &'py PyDict to &'a Py2<'py, PyDict> for
@@ -211,10 +199,12 @@ impl<'py, T> Py2<'py, T> {
211
199
unsafe { self . py ( ) . from_owned_ptr ( self . into_ptr ( ) ) }
212
200
}
213
201
202
+ // Internal helper to convert `self` into a `NonNull` which owns the
203
+ // Python reference.
214
204
pub ( crate ) fn into_non_null ( self ) -> NonNull < ffi:: PyObject > {
215
- let ptr = ( self . 1 ) . 0 ;
216
- std :: mem :: forget ( self ) ;
217
- ptr
205
+ // wrap in ManuallyDrop to avoid running Drop for self and decreasing
206
+ // the reference count
207
+ ManuallyDrop :: new ( self ) . 1 . 0
218
208
}
219
209
}
220
210
@@ -1477,6 +1467,22 @@ a = A()
1477
1467
} ) ;
1478
1468
}
1479
1469
1470
+ #[ test]
1471
+ fn test_debug_fmt ( ) {
1472
+ Python :: with_gil ( |py| {
1473
+ let obj = "hello world" . to_object ( py) . attach_into ( py) ;
1474
+ assert_eq ! ( format!( "{:?}" , obj) , "'hello world'" ) ;
1475
+ } ) ;
1476
+ }
1477
+
1478
+ #[ test]
1479
+ fn test_display_fmt ( ) {
1480
+ Python :: with_gil ( |py| {
1481
+ let obj = "hello world" . to_object ( py) . attach_into ( py) ;
1482
+ assert_eq ! ( format!( "{}" , obj) , "hello world" ) ;
1483
+ } ) ;
1484
+ }
1485
+
1480
1486
#[ cfg( feature = "macros" ) ]
1481
1487
mod using_macros {
1482
1488
use super :: * ;
0 commit comments