11#![ cfg( feature = "macros" ) ]
22
33use pyo3:: exceptions:: { PyIndexError , PyValueError } ;
4- use pyo3:: types:: { IntoPyDict , PyList , PyMapping , PySequence } ;
4+ use pyo3:: types:: { IntoPyDict , PyInt , PyList , PyMapping , PySequence } ;
55use pyo3:: { ffi, prelude:: * } ;
66
77use pyo3:: py_run;
@@ -255,15 +255,15 @@ fn test_inplace_repeat() {
255255// Check that #[pyo3(get, set)] works correctly for Vec<PyObject>
256256
257257#[ pyclass]
258- struct GenericList {
258+ struct AnyObjectList {
259259 #[ pyo3( get, set) ]
260260 items : Vec < PyObject > ,
261261}
262262
263263#[ test]
264- fn test_generic_list_get ( ) {
264+ fn test_any_object_list_get ( ) {
265265 Python :: with_gil ( |py| {
266- let list = GenericList {
266+ let list = AnyObjectList {
267267 items : [ 1i32 , 2 , 3 ]
268268 . iter ( )
269269 . map ( |i| i. into_pyobject ( py) . unwrap ( ) . into_any ( ) . unbind ( ) )
@@ -277,9 +277,9 @@ fn test_generic_list_get() {
277277}
278278
279279#[ test]
280- fn test_generic_list_set ( ) {
280+ fn test_any_object_list_set ( ) {
281281 Python :: with_gil ( |py| {
282- let list = Bound :: new ( py, GenericList { items : vec ! [ ] } ) . unwrap ( ) ;
282+ let list = Bound :: new ( py, AnyObjectList { items : vec ! [ ] } ) . unwrap ( ) ;
283283
284284 py_run ! ( py, list, "list.items = [1, 2, 3]" ) ;
285285 assert ! ( list
@@ -367,3 +367,58 @@ fn sequence_length() {
367367 unsafe { ffi:: PyErr_Clear ( ) } ;
368368 } )
369369}
370+
371+ #[ cfg( Py_3_9 ) ]
372+ #[ pyclass( generic, sequence) ]
373+ struct GenericList {
374+ #[ pyo3( get, set) ]
375+ items : Vec < PyObject > ,
376+ }
377+
378+ #[ cfg( Py_3_9 ) ]
379+ #[ pymethods]
380+ impl GenericList {
381+ fn __len__ ( & self ) -> usize {
382+ self . items . len ( )
383+ }
384+
385+ fn __getitem__ ( & self , idx : isize ) -> PyResult < PyObject > {
386+ match self . items . get ( idx as usize ) {
387+ Some ( x) => pyo3:: Python :: with_gil ( |py| Ok ( x. clone_ref ( py) ) ) ,
388+ None => Err ( PyIndexError :: new_err ( "Index out of bounds" ) ) ,
389+ }
390+ }
391+ }
392+
393+ #[ cfg( Py_3_9 ) ]
394+ #[ test]
395+ fn test_generic_both_subscriptions_types ( ) {
396+ use std:: convert:: Infallible ;
397+
398+ Python :: with_gil ( |py| {
399+ let l = Bound :: new (
400+ py,
401+ GenericList {
402+ items : vec ! [ 1 , 2 , 3 ]
403+ . iter ( )
404+ . map ( |x| -> PyObject {
405+ let x: Result < Bound < ' _ , PyInt > , Infallible > = x. into_pyobject ( py) ;
406+ return x. unwrap ( ) . into_any ( ) . unbind ( ) ;
407+ } )
408+ . collect ( ) ,
409+ } ,
410+ )
411+ . unwrap ( ) ;
412+ let ty = py. get_type :: < GenericList > ( ) ;
413+ py_assert ! ( py, l, "l[0] == 1" ) ;
414+ py_run ! (
415+ py,
416+ ty,
417+ "import types;
418+ import typing;
419+ IntOrNone: typing.Alias = typing.Union[int, None];
420+ assert ty[IntOrNone] == types.GenericAlias(ty, (IntOrNone,))"
421+ ) ;
422+ py_assert ! ( py, l, "list(reversed(l)) == [3, 2, 1]" ) ;
423+ } ) ;
424+ }
0 commit comments