@@ -60,9 +60,12 @@ pyobject_native_type_core!(PyTuple, pyobject_native_static_type_object!(ffi::PyT
60
60
impl PyTuple {
61
61
/// Deprecated form of `PyTuple::new_bound`.
62
62
#[ track_caller]
63
- #[ deprecated(
64
- since = "0.21.0" ,
65
- note = "`PyTuple::new` will be replaced by `PyTuple::new_bound` in a future PyO3 version"
63
+ #[ cfg_attr(
64
+ not( feature = "gil-refs" ) ,
65
+ deprecated(
66
+ since = "0.21.0" ,
67
+ note = "`PyTuple::new` will be replaced by `PyTuple::new_bound` in a future PyO3 version"
68
+ )
66
69
) ]
67
70
pub fn new < T , U > (
68
71
py : Python < ' _ > ,
@@ -115,9 +118,12 @@ impl PyTuple {
115
118
}
116
119
117
120
/// Deprecated form of `PyTuple::empty_bound`.
118
- #[ deprecated(
119
- since = "0.21.0" ,
120
- note = "`PyTuple::empty` will be replaced by `PyTuple::empty_bound` in a future PyO3 version"
121
+ #[ cfg_attr(
122
+ not( feature = "gil-refs" ) ,
123
+ deprecated(
124
+ since = "0.21.0" ,
125
+ note = "`PyTuple::empty` will be replaced by `PyTuple::empty_bound` in a future PyO3 version"
126
+ )
121
127
) ]
122
128
pub fn empty ( py : Python < ' _ > ) -> & PyTuple {
123
129
Self :: empty_bound ( py) . into_gil_ref ( )
@@ -361,7 +367,7 @@ impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> {
361
367
}
362
368
363
369
fn get_borrowed_item < ' a > ( & ' a self , index : usize ) -> PyResult < Borrowed < ' a , ' py , PyAny > > {
364
- Borrowed :: from ( self ) . get_borrowed_item ( index)
370
+ self . as_borrowed ( ) . get_borrowed_item ( index)
365
371
}
366
372
367
373
#[ cfg( not( any( Py_LIMITED_API , PyPy ) ) ) ]
@@ -371,7 +377,7 @@ impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> {
371
377
372
378
#[ cfg( not( any( Py_LIMITED_API , PyPy ) ) ) ]
373
379
unsafe fn get_borrowed_item_unchecked < ' a > ( & ' a self , index : usize ) -> Borrowed < ' a , ' py , PyAny > {
374
- Borrowed :: from ( self ) . get_borrowed_item_unchecked ( index)
380
+ self . as_borrowed ( ) . get_borrowed_item_unchecked ( index)
375
381
}
376
382
377
383
#[ cfg( not( Py_LIMITED_API ) ) ]
@@ -406,7 +412,7 @@ impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> {
406
412
}
407
413
408
414
fn iter_borrowed < ' a > ( & ' a self ) -> BorrowedTupleIterator < ' a , ' py > {
409
- BorrowedTupleIterator :: new ( Borrowed :: from ( self ) )
415
+ BorrowedTupleIterator :: new ( self . as_borrowed ( ) )
410
416
}
411
417
412
418
fn to_list ( & self ) -> Bound < ' py , PyList > {
@@ -498,7 +504,7 @@ impl<'py> Iterator for BoundTupleIterator<'py> {
498
504
fn next ( & mut self ) -> Option < Self :: Item > {
499
505
if self . index < self . length {
500
506
let item = unsafe {
501
- BorrowedTupleIterator :: get_item ( Borrowed :: from ( & self . tuple ) , self . index ) . to_owned ( )
507
+ BorrowedTupleIterator :: get_item ( self . tuple . as_borrowed ( ) , self . index ) . to_owned ( )
502
508
} ;
503
509
self . index += 1 ;
504
510
Some ( item)
@@ -519,7 +525,7 @@ impl<'py> DoubleEndedIterator for BoundTupleIterator<'py> {
519
525
fn next_back ( & mut self ) -> Option < Self :: Item > {
520
526
if self . index < self . length {
521
527
let item = unsafe {
522
- BorrowedTupleIterator :: get_item ( Borrowed :: from ( & self . tuple ) , self . length - 1 )
528
+ BorrowedTupleIterator :: get_item ( self . tuple . as_borrowed ( ) , self . length - 1 )
523
529
. to_owned ( )
524
530
} ;
525
531
self . length -= 1 ;
@@ -799,7 +805,7 @@ tuple_conversion!(
799
805
#[ cfg( test) ]
800
806
#[ allow( deprecated) ] // TODO: remove allow when GIL Pool is removed
801
807
mod tests {
802
- use crate :: types:: { PyAny , PyList , PyTuple } ;
808
+ use crate :: types:: { any :: PyAnyMethods , tuple :: PyTupleMethods , PyAny , PyList , PyTuple } ;
803
809
use crate :: { Python , ToPyObject } ;
804
810
use std:: collections:: HashSet ;
805
811
@@ -824,11 +830,21 @@ mod tests {
824
830
let ob = ( 1 , 2 , 3 ) . to_object ( py) ;
825
831
let tuple: & PyTuple = ob. downcast ( py) . unwrap ( ) ;
826
832
assert_eq ! ( 3 , tuple. len( ) ) ;
833
+ assert ! ( !tuple. is_empty( ) ) ;
827
834
let ob: & PyAny = tuple. into ( ) ;
828
835
assert_eq ! ( ( 1 , 2 , 3 ) , ob. extract( ) . unwrap( ) ) ;
829
836
} ) ;
830
837
}
831
838
839
+ #[ test]
840
+ fn test_empty ( ) {
841
+ Python :: with_gil ( |py| {
842
+ let tuple = PyTuple :: empty ( py) ;
843
+ assert ! ( tuple. is_empty( ) ) ;
844
+ assert_eq ! ( 0 , tuple. len( ) ) ;
845
+ } ) ;
846
+ }
847
+
832
848
#[ test]
833
849
fn test_slice ( ) {
834
850
Python :: with_gil ( |py| {
@@ -888,6 +904,52 @@ mod tests {
888
904
} ) ;
889
905
}
890
906
907
+ #[ test]
908
+ fn test_bound_iter ( ) {
909
+ Python :: with_gil ( |py| {
910
+ let tuple = PyTuple :: new_bound ( py, [ 1 , 2 , 3 ] ) ;
911
+ assert_eq ! ( 3 , tuple. len( ) ) ;
912
+ let mut iter = tuple. iter ( ) ;
913
+
914
+ assert_eq ! ( iter. size_hint( ) , ( 3 , Some ( 3 ) ) ) ;
915
+
916
+ assert_eq ! ( 1_i32 , iter. next( ) . unwrap( ) . extract:: <' _, i32 >( ) . unwrap( ) ) ;
917
+ assert_eq ! ( iter. size_hint( ) , ( 2 , Some ( 2 ) ) ) ;
918
+
919
+ assert_eq ! ( 2_i32 , iter. next( ) . unwrap( ) . extract:: <' _, i32 >( ) . unwrap( ) ) ;
920
+ assert_eq ! ( iter. size_hint( ) , ( 1 , Some ( 1 ) ) ) ;
921
+
922
+ assert_eq ! ( 3_i32 , iter. next( ) . unwrap( ) . extract:: <' _, i32 >( ) . unwrap( ) ) ;
923
+ assert_eq ! ( iter. size_hint( ) , ( 0 , Some ( 0 ) ) ) ;
924
+
925
+ assert ! ( iter. next( ) . is_none( ) ) ;
926
+ assert ! ( iter. next( ) . is_none( ) ) ;
927
+ } ) ;
928
+ }
929
+
930
+ #[ test]
931
+ fn test_bound_iter_rev ( ) {
932
+ Python :: with_gil ( |py| {
933
+ let tuple = PyTuple :: new_bound ( py, [ 1 , 2 , 3 ] ) ;
934
+ assert_eq ! ( 3 , tuple. len( ) ) ;
935
+ let mut iter = tuple. iter ( ) . rev ( ) ;
936
+
937
+ assert_eq ! ( iter. size_hint( ) , ( 3 , Some ( 3 ) ) ) ;
938
+
939
+ assert_eq ! ( 3_i32 , iter. next( ) . unwrap( ) . extract:: <' _, i32 >( ) . unwrap( ) ) ;
940
+ assert_eq ! ( iter. size_hint( ) , ( 2 , Some ( 2 ) ) ) ;
941
+
942
+ assert_eq ! ( 2_i32 , iter. next( ) . unwrap( ) . extract:: <' _, i32 >( ) . unwrap( ) ) ;
943
+ assert_eq ! ( iter. size_hint( ) , ( 1 , Some ( 1 ) ) ) ;
944
+
945
+ assert_eq ! ( 1_i32 , iter. next( ) . unwrap( ) . extract:: <' _, i32 >( ) . unwrap( ) ) ;
946
+ assert_eq ! ( iter. size_hint( ) , ( 0 , Some ( 0 ) ) ) ;
947
+
948
+ assert ! ( iter. next( ) . is_none( ) ) ;
949
+ assert ! ( iter. next( ) . is_none( ) ) ;
950
+ } ) ;
951
+ }
952
+
891
953
#[ test]
892
954
fn test_into_iter ( ) {
893
955
Python :: with_gil ( |py| {
@@ -1310,4 +1372,50 @@ mod tests {
1310
1372
assert ! ( list. eq( list_expected) . unwrap( ) ) ;
1311
1373
} )
1312
1374
}
1375
+
1376
+ #[ test]
1377
+ fn test_tuple_as_sequence ( ) {
1378
+ Python :: with_gil ( |py| {
1379
+ let tuple = PyTuple :: new ( py, vec ! [ 1 , 2 , 3 ] ) ;
1380
+ let sequence = tuple. as_sequence ( ) ;
1381
+ assert ! ( tuple. get_item( 0 ) . unwrap( ) . eq( 1 ) . unwrap( ) ) ;
1382
+ assert ! ( sequence. get_item( 0 ) . unwrap( ) . eq( 1 ) . unwrap( ) ) ;
1383
+
1384
+ assert_eq ! ( tuple. len( ) , 3 ) ;
1385
+ assert_eq ! ( sequence. len( ) . unwrap( ) , 3 ) ;
1386
+ } )
1387
+ }
1388
+
1389
+ #[ test]
1390
+ fn test_bound_tuple_get_item ( ) {
1391
+ Python :: with_gil ( |py| {
1392
+ let tuple = PyTuple :: new_bound ( py, vec ! [ 1 , 2 , 3 , 4 ] ) ;
1393
+
1394
+ assert_eq ! ( tuple. len( ) , 4 ) ;
1395
+ assert_eq ! ( tuple. get_item( 0 ) . unwrap( ) . extract:: <i32 >( ) . unwrap( ) , 1 ) ;
1396
+ assert_eq ! (
1397
+ tuple
1398
+ . get_borrowed_item( 1 )
1399
+ . unwrap( )
1400
+ . extract:: <i32 >( )
1401
+ . unwrap( ) ,
1402
+ 2
1403
+ ) ;
1404
+ #[ cfg( not( any( Py_LIMITED_API , PyPy ) ) ) ]
1405
+ {
1406
+ assert_eq ! (
1407
+ unsafe { tuple. get_item_unchecked( 2 ) }
1408
+ . extract:: <i32 >( )
1409
+ . unwrap( ) ,
1410
+ 3
1411
+ ) ;
1412
+ assert_eq ! (
1413
+ unsafe { tuple. get_borrowed_item_unchecked( 3 ) }
1414
+ . extract:: <i32 >( )
1415
+ . unwrap( ) ,
1416
+ 4
1417
+ ) ;
1418
+ }
1419
+ } )
1420
+ }
1313
1421
}
0 commit comments