@@ -1387,6 +1387,123 @@ def test_nested_sequence(self):
1387
1387
"argument 1 must be sequence of length 1, not 0" ):
1388
1388
parse (([],), {}, '(' + f + ')' , ['a' ])
1389
1389
1390
+ def test_specific_type_errors (self ):
1391
+ parse = _testcapi .parse_tuple_and_keywords
1392
+
1393
+ def check (format , arg , expected , got = 'list' ):
1394
+ errmsg = f'must be { expected } , not { got } '
1395
+ with self .assertRaisesRegex (TypeError , errmsg ):
1396
+ parse ((arg ,), {}, format , ['a' ])
1397
+
1398
+ check ('k' , [], 'int' )
1399
+ check ('k?' , [], 'int or None' )
1400
+ check ('K' , [], 'int' )
1401
+ check ('K?' , [], 'int or None' )
1402
+ check ('c' , [], 'a byte string of length 1' )
1403
+ check ('c?' , [], 'a byte string of length 1 or None' )
1404
+ check ('c' , b'abc' , 'a byte string of length 1' ,
1405
+ 'a bytes object of length 3' )
1406
+ check ('c?' , b'abc' , 'a byte string of length 1 or None' ,
1407
+ 'a bytes object of length 3' )
1408
+ check ('c' , bytearray (b'abc' ), 'a byte string of length 1' ,
1409
+ 'a bytearray object of length 3' )
1410
+ check ('c?' , bytearray (b'abc' ), 'a byte string of length 1 or None' ,
1411
+ 'a bytearray object of length 3' )
1412
+ check ('C' , [], 'a unicode character' )
1413
+ check ('C?' , [], 'a unicode character or None' )
1414
+ check ('C' , 'abc' , 'a unicode character' ,
1415
+ 'a string of length 3' )
1416
+ check ('C?' , 'abc' , 'a unicode character or None' ,
1417
+ 'a string of length 3' )
1418
+ check ('s' , [], 'str' )
1419
+ check ('s?' , [], 'str or None' )
1420
+ check ('z' , [], 'str or None' )
1421
+ check ('z?' , [], 'str or None' )
1422
+ check ('es' , [], 'str' )
1423
+ check ('es?' , [], 'str or None' )
1424
+ check ('es#' , [], 'str' )
1425
+ check ('es#?' , [], 'str or None' )
1426
+ check ('et' , [], 'str, bytes or bytearray' )
1427
+ check ('et?' , [], 'str, bytes, bytearray or None' )
1428
+ check ('et#' , [], 'str, bytes or bytearray' )
1429
+ check ('et#?' , [], 'str, bytes, bytearray or None' )
1430
+ check ('w*' , [], 'read-write bytes-like object' )
1431
+ check ('w*?' , [], 'read-write bytes-like object or None' )
1432
+ check ('S' , [], 'bytes' )
1433
+ check ('S?' , [], 'bytes or None' )
1434
+ check ('U' , [], 'str' )
1435
+ check ('U?' , [], 'str or None' )
1436
+ check ('Y' , [], 'bytearray' )
1437
+ check ('Y?' , [], 'bytearray or None' )
1438
+ check ('(OO)' , 42 , '2-item tuple' , 'int' )
1439
+ check ('(OO)?' , 42 , '2-item tuple or None' , 'int' )
1440
+ check ('(OO)' , (1 , 2 , 3 ), 'tuple of length 2' , '3' )
1441
+
1442
+ def test_nullable (self ):
1443
+ parse = _testcapi .parse_tuple_and_keywords
1444
+
1445
+ def check (format , arg , allows_none = False ):
1446
+ # Because some format units (such as y*) require cleanup,
1447
+ # we force the parsing code to perform the cleanup by adding
1448
+ # an argument that always fails.
1449
+ # By checking for an exception, we ensure that the parsing
1450
+ # of the first argument was successful.
1451
+ self .assertRaises (OverflowError , parse ,
1452
+ (arg , 256 ), {}, format + '?b' , ['a' , 'b' ])
1453
+ self .assertRaises (OverflowError , parse ,
1454
+ (None , 256 ), {}, format + '?b' , ['a' , 'b' ])
1455
+ self .assertRaises (OverflowError , parse ,
1456
+ (arg , 256 ), {}, format + 'b' , ['a' , 'b' ])
1457
+ self .assertRaises (OverflowError if allows_none else TypeError , parse ,
1458
+ (None , 256 ), {}, format + 'b' , ['a' , 'b' ])
1459
+
1460
+ check ('b' , 42 )
1461
+ check ('B' , 42 )
1462
+ check ('h' , 42 )
1463
+ check ('H' , 42 )
1464
+ check ('i' , 42 )
1465
+ check ('I' , 42 )
1466
+ check ('n' , 42 )
1467
+ check ('l' , 42 )
1468
+ check ('k' , 42 )
1469
+ check ('L' , 42 )
1470
+ check ('K' , 42 )
1471
+ check ('f' , 2.5 )
1472
+ check ('d' , 2.5 )
1473
+ check ('D' , 2.5j )
1474
+ check ('c' , b'a' )
1475
+ check ('C' , 'a' )
1476
+ check ('p' , True , allows_none = True )
1477
+ check ('y' , b'buffer' )
1478
+ check ('y*' , b'buffer' )
1479
+ check ('y#' , b'buffer' )
1480
+ check ('s' , 'string' )
1481
+ check ('s*' , 'string' )
1482
+ check ('s#' , 'string' )
1483
+ check ('z' , 'string' , allows_none = True )
1484
+ check ('z*' , 'string' , allows_none = True )
1485
+ check ('z#' , 'string' , allows_none = True )
1486
+ check ('w*' , bytearray (b'buffer' ))
1487
+ check ('U' , 'string' )
1488
+ check ('S' , b'bytes' )
1489
+ check ('Y' , bytearray (b'bytearray' ))
1490
+ check ('O' , object , allows_none = True )
1491
+
1492
+ check ('(OO)' , (1 , 2 ))
1493
+ self .assertEqual (parse ((((1 , 2 ), 3 ),), {}, '((OO)?O)' , ['a' ]), (1 , 2 , 3 ))
1494
+ self .assertEqual (parse (((None , 3 ),), {}, '((OO)?O)' , ['a' ]), (NULL , NULL , 3 ))
1495
+ self .assertEqual (parse ((((1 , 2 ), 3 ),), {}, '((OO)O)' , ['a' ]), (1 , 2 , 3 ))
1496
+ self .assertRaises (TypeError , parse , ((None , 3 ),), {}, '((OO)O)' , ['a' ])
1497
+
1498
+ parse ((None ,), {}, 'es?' , ['a' ])
1499
+ parse ((None ,), {}, 'es#?' , ['a' ])
1500
+ parse ((None ,), {}, 'et?' , ['a' ])
1501
+ parse ((None ,), {}, 'et#?' , ['a' ])
1502
+ parse ((None ,), {}, 'O!?' , ['a' ])
1503
+ parse ((None ,), {}, 'O&?' , ['a' ])
1504
+
1505
+ # TODO: More tests for es?, es#?, et?, et#?, O!, O&
1506
+
1390
1507
@unittest .skipIf (_testinternalcapi is None , 'needs _testinternalcapi' )
1391
1508
def test_gh_119213 (self ):
1392
1509
rc , out , err = script_helper .assert_python_ok ("-c" , """if True:
0 commit comments