@@ -69,6 +69,7 @@ impl PyList {
69
69
/// Gets the item at the specified index.
70
70
///
71
71
/// Panics if the index is out of range.
72
+ #[ deprecated = "use PyList::get, which does not panic" ]
72
73
pub fn get_item ( & self , index : isize ) -> & PyAny {
73
74
assert ! ( index >= 0 && index < self . len( ) as isize ) ;
74
75
unsafe {
@@ -83,6 +84,24 @@ impl PyList {
83
84
}
84
85
}
85
86
87
+ /// Gets the list item at the specified index.
88
+ pub fn get ( & self , index : usize ) -> PyResult < & PyAny > {
89
+ unsafe {
90
+ let item = ffi:: PyList_GetItem ( self . as_ptr ( ) , index as Py_ssize_t ) ;
91
+ self . py ( ) . from_borrowed_ptr_or_err ( item)
92
+ }
93
+ }
94
+
95
+ /// Gets the list item at the specified index. Undefined behavior on bad index. Use with caution.
96
+ /// # Safety
97
+ ///
98
+ /// Caller must verify that the index is within the bounds of the list.
99
+ #[ cfg( not( any( Py_LIMITED_API , PyPy ) ) ) ]
100
+ pub unsafe fn get_unchecked ( & self , index : usize ) -> & PyAny {
101
+ let item = ffi:: PyList_GET_ITEM ( self . as_ptr ( ) , index as Py_ssize_t ) ;
102
+ self . py ( ) . from_borrowed_ptr ( item)
103
+ }
104
+
86
105
/// Sets the item at the specified index.
87
106
///
88
107
/// Panics if the index is out of range.
@@ -142,16 +161,19 @@ impl PyList {
142
161
/// Used by `PyList::iter()`.
143
162
pub struct PyListIterator < ' a > {
144
163
list : & ' a PyList ,
145
- index : isize ,
164
+ index : usize ,
146
165
}
147
166
148
167
impl < ' a > Iterator for PyListIterator < ' a > {
149
168
type Item = & ' a PyAny ;
150
169
151
170
#[ inline]
152
171
fn next ( & mut self ) -> Option < & ' a PyAny > {
153
- if self . index < self . list . len ( ) as isize {
154
- let item = self . list . get_item ( self . index ) ;
172
+ if self . index < self . list . len ( ) {
173
+ #[ cfg( any( Py_LIMITED_API , PyPy ) ) ]
174
+ let item = self . list . get ( self . index ) . expect ( "tuple.get failed" ) ;
175
+ #[ cfg( not( any( Py_LIMITED_API , PyPy ) ) ) ]
176
+ let item = unsafe { self . list . get_unchecked ( self . index ) } ;
155
177
self . index += 1 ;
156
178
Some ( item)
157
179
} else {
@@ -217,10 +239,10 @@ mod test {
217
239
let gil = Python :: acquire_gil ( ) ;
218
240
let py = gil. python ( ) ;
219
241
let list = PyList :: new ( py, & [ 2 , 3 , 5 , 7 ] ) ;
220
- assert_eq ! ( 2 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
221
- assert_eq ! ( 3 , list. get_item ( 1 ) . extract:: <i32 >( ) . unwrap( ) ) ;
222
- assert_eq ! ( 5 , list. get_item ( 2 ) . extract:: <i32 >( ) . unwrap( ) ) ;
223
- assert_eq ! ( 7 , list. get_item ( 3 ) . extract:: <i32 >( ) . unwrap( ) ) ;
242
+ assert_eq ! ( 2 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
243
+ assert_eq ! ( 3 , list. get ( 1 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
244
+ assert_eq ! ( 5 , list. get ( 2 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
245
+ assert_eq ! ( 7 , list. get ( 3 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
224
246
}
225
247
226
248
#[ test]
@@ -236,19 +258,10 @@ mod test {
236
258
let gil = Python :: acquire_gil ( ) ;
237
259
let py = gil. python ( ) ;
238
260
let list = PyList :: new ( py, & [ 2 , 3 , 5 , 7 ] ) ;
239
- assert_eq ! ( 2 , list. get_item( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
240
- assert_eq ! ( 3 , list. get_item( 1 ) . extract:: <i32 >( ) . unwrap( ) ) ;
241
- assert_eq ! ( 5 , list. get_item( 2 ) . extract:: <i32 >( ) . unwrap( ) ) ;
242
- assert_eq ! ( 7 , list. get_item( 3 ) . extract:: <i32 >( ) . unwrap( ) ) ;
243
- }
244
-
245
- #[ test]
246
- #[ should_panic]
247
- fn test_get_item_invalid ( ) {
248
- let gil = Python :: acquire_gil ( ) ;
249
- let py = gil. python ( ) ;
250
- let list = PyList :: new ( py, & [ 2 , 3 , 5 , 7 ] ) ;
251
- list. get_item ( -1 ) ;
261
+ assert_eq ! ( 2 , list. get( 0 ) . unwrap( ) . extract:: <i32 >( ) . unwrap( ) ) ;
262
+ assert_eq ! ( 3 , list. get( 1 ) . unwrap( ) . extract:: <i32 >( ) . unwrap( ) ) ;
263
+ assert_eq ! ( 5 , list. get( 2 ) . unwrap( ) . extract:: <i32 >( ) . unwrap( ) ) ;
264
+ assert_eq ! ( 7 , list. get( 3 ) . unwrap( ) . extract:: <i32 >( ) . unwrap( ) ) ;
252
265
}
253
266
254
267
#[ test]
@@ -257,9 +270,9 @@ mod test {
257
270
let py = gil. python ( ) ;
258
271
let list = PyList :: new ( py, & [ 2 , 3 , 5 , 7 ] ) ;
259
272
let val = 42i32 . to_object ( py) ;
260
- assert_eq ! ( 2 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
273
+ assert_eq ! ( 2 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
261
274
list. set_item ( 0 , val) . unwrap ( ) ;
262
- assert_eq ! ( 42 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
275
+ assert_eq ! ( 42 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
263
276
}
264
277
265
278
#[ test]
@@ -288,11 +301,11 @@ mod test {
288
301
let list = PyList :: new ( py, & [ 2 , 3 , 5 , 7 ] ) ;
289
302
let val = 42i32 . to_object ( py) ;
290
303
assert_eq ! ( 4 , list. len( ) ) ;
291
- assert_eq ! ( 2 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
304
+ assert_eq ! ( 2 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
292
305
list. insert ( 0 , val) . unwrap ( ) ;
293
306
assert_eq ! ( 5 , list. len( ) ) ;
294
- assert_eq ! ( 42 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
295
- assert_eq ! ( 2 , list. get_item ( 1 ) . extract:: <i32 >( ) . unwrap( ) ) ;
307
+ assert_eq ! ( 42 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
308
+ assert_eq ! ( 2 , list. get ( 1 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
296
309
}
297
310
298
311
#[ test]
@@ -318,8 +331,8 @@ mod test {
318
331
let py = gil. python ( ) ;
319
332
let list = PyList :: new ( py, & [ 2 ] ) ;
320
333
list. append ( 3 ) . unwrap ( ) ;
321
- assert_eq ! ( 2 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
322
- assert_eq ! ( 3 , list. get_item ( 1 ) . extract:: <i32 >( ) . unwrap( ) ) ;
334
+ assert_eq ! ( 2 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
335
+ assert_eq ! ( 3 , list. get ( 1 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
323
336
}
324
337
325
338
#[ test]
@@ -397,15 +410,15 @@ mod test {
397
410
let py = gil. python ( ) ;
398
411
let v = vec ! [ 7 , 3 , 2 , 5 ] ;
399
412
let list = PyList :: new ( py, & v) ;
400
- assert_eq ! ( 7 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
401
- assert_eq ! ( 3 , list. get_item ( 1 ) . extract:: <i32 >( ) . unwrap( ) ) ;
402
- assert_eq ! ( 2 , list. get_item ( 2 ) . extract:: <i32 >( ) . unwrap( ) ) ;
403
- assert_eq ! ( 5 , list. get_item ( 3 ) . extract:: <i32 >( ) . unwrap( ) ) ;
413
+ assert_eq ! ( 7 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
414
+ assert_eq ! ( 3 , list. get ( 1 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
415
+ assert_eq ! ( 2 , list. get ( 2 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
416
+ assert_eq ! ( 5 , list. get ( 3 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
404
417
list. sort ( ) . unwrap ( ) ;
405
- assert_eq ! ( 2 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
406
- assert_eq ! ( 3 , list. get_item ( 1 ) . extract:: <i32 >( ) . unwrap( ) ) ;
407
- assert_eq ! ( 5 , list. get_item ( 2 ) . extract:: <i32 >( ) . unwrap( ) ) ;
408
- assert_eq ! ( 7 , list. get_item ( 3 ) . extract:: <i32 >( ) . unwrap( ) ) ;
418
+ assert_eq ! ( 2 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
419
+ assert_eq ! ( 3 , list. get ( 1 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
420
+ assert_eq ! ( 5 , list. get ( 2 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
421
+ assert_eq ! ( 7 , list. get ( 3 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
409
422
}
410
423
411
424
#[ test]
@@ -414,15 +427,15 @@ mod test {
414
427
let py = gil. python ( ) ;
415
428
let v = vec ! [ 2 , 3 , 5 , 7 ] ;
416
429
let list = PyList :: new ( py, & v) ;
417
- assert_eq ! ( 2 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
418
- assert_eq ! ( 3 , list. get_item ( 1 ) . extract:: <i32 >( ) . unwrap( ) ) ;
419
- assert_eq ! ( 5 , list. get_item ( 2 ) . extract:: <i32 >( ) . unwrap( ) ) ;
420
- assert_eq ! ( 7 , list. get_item ( 3 ) . extract:: <i32 >( ) . unwrap( ) ) ;
430
+ assert_eq ! ( 2 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
431
+ assert_eq ! ( 3 , list. get ( 1 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
432
+ assert_eq ! ( 5 , list. get ( 2 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
433
+ assert_eq ! ( 7 , list. get ( 3 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
421
434
list. reverse ( ) . unwrap ( ) ;
422
- assert_eq ! ( 7 , list. get_item ( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
423
- assert_eq ! ( 5 , list. get_item ( 1 ) . extract:: <i32 >( ) . unwrap( ) ) ;
424
- assert_eq ! ( 3 , list. get_item ( 2 ) . extract:: <i32 >( ) . unwrap( ) ) ;
425
- assert_eq ! ( 2 , list. get_item ( 3 ) . extract:: <i32 >( ) . unwrap( ) ) ;
435
+ assert_eq ! ( 7 , list. get ( 0 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
436
+ assert_eq ! ( 5 , list. get ( 1 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
437
+ assert_eq ! ( 3 , list. get ( 2 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
438
+ assert_eq ! ( 2 , list. get ( 3 ) . unwrap ( ) . extract:: <i32 >( ) . unwrap( ) ) ;
426
439
}
427
440
428
441
#[ test]
@@ -431,7 +444,48 @@ mod test {
431
444
let py = gil. python ( ) ;
432
445
let array: PyObject = [ 1 , 2 ] . into_py ( py) ;
433
446
let list = <PyList as PyTryFrom >:: try_from ( array. as_ref ( py) ) . unwrap ( ) ;
434
- assert_eq ! ( 1 , list. get_item( 0 ) . extract:: <i32 >( ) . unwrap( ) ) ;
435
- assert_eq ! ( 2 , list. get_item( 1 ) . extract:: <i32 >( ) . unwrap( ) ) ;
447
+ assert_eq ! ( 1 , list. get( 0 ) . unwrap( ) . extract:: <i32 >( ) . unwrap( ) ) ;
448
+ assert_eq ! ( 2 , list. get( 1 ) . unwrap( ) . extract:: <i32 >( ) . unwrap( ) ) ;
449
+ }
450
+
451
+ #[ test]
452
+ fn test_list_get_invalid_index ( ) {
453
+ pyo3:: Python :: with_gil ( |py| {
454
+ let list = PyList :: new ( py, & [ 2 , 3 , 5 , 7 ] ) ;
455
+ let obj = list. get ( 5 ) ;
456
+ assert ! ( obj. is_err( ) ) ;
457
+ assert_eq ! (
458
+ obj. unwrap_err( ) . to_string( ) ,
459
+ "IndexError: list index out of range"
460
+ ) ;
461
+ } ) ;
462
+ }
463
+
464
+ #[ test]
465
+ fn test_list_get_sanity ( ) {
466
+ pyo3:: Python :: with_gil ( |py| {
467
+ let list = PyList :: new ( py, & [ 2 , 3 , 5 , 7 ] ) ;
468
+ let obj = list. get ( 0 ) ;
469
+ assert_eq ! ( obj. unwrap( ) . extract:: <i32 >( ) . unwrap( ) , 2 ) ;
470
+ } ) ;
471
+ }
472
+
473
+ #[ cfg( not( any( Py_LIMITED_API , PyPy ) ) ) ]
474
+ #[ test]
475
+ fn test_list_get_unchecked_sanity ( ) {
476
+ pyo3:: Python :: with_gil ( |py| {
477
+ let list = PyList :: new ( py, & [ 2 , 3 , 5 , 7 ] ) ;
478
+ let obj = unsafe { list. get_unchecked ( 0 ) } ;
479
+ assert_eq ! ( obj. extract:: <i32 >( ) . unwrap( ) , 2 ) ;
480
+ } ) ;
481
+ }
482
+
483
+ #[ cfg( not( any( Py_LIMITED_API , PyPy ) ) ) ]
484
+ #[ test]
485
+ fn test_list_get_unchecked_invalid_index ( ) {
486
+ pyo3:: Python :: with_gil ( |py| {
487
+ let list = PyList :: new ( py, & [ 2 , 3 , 5 , 7 ] ) ;
488
+ unsafe { list. get_unchecked ( 5 ) } ;
489
+ } ) ;
436
490
}
437
491
}
0 commit comments