@@ -1627,7 +1627,7 @@ def test_depr_star_invalid_format_1(self):
1627
1627
Docstring.
1628
1628
"""
1629
1629
err = (
1630
- "Function 'foo.bar': expected format '* [from major.minor]' "
1630
+ "Function 'foo.bar': expected format '[from major.minor]' "
1631
1631
"where 'major' and 'minor' are integers; got '3'"
1632
1632
)
1633
1633
self .expect_failure (block , err , lineno = 3 )
@@ -1641,7 +1641,7 @@ def test_depr_star_invalid_format_2(self):
1641
1641
Docstring.
1642
1642
"""
1643
1643
err = (
1644
- "Function 'foo.bar': expected format '* [from major.minor]' "
1644
+ "Function 'foo.bar': expected format '[from major.minor]' "
1645
1645
"where 'major' and 'minor' are integers; got 'a.b'"
1646
1646
)
1647
1647
self .expect_failure (block , err , lineno = 3 )
@@ -1655,7 +1655,7 @@ def test_depr_star_invalid_format_3(self):
1655
1655
Docstring.
1656
1656
"""
1657
1657
err = (
1658
- "Function 'foo.bar': expected format '* [from major.minor]' "
1658
+ "Function 'foo.bar': expected format '[from major.minor]' "
1659
1659
"where 'major' and 'minor' are integers; got '1.2.3'"
1660
1660
)
1661
1661
self .expect_failure (block , err , lineno = 3 )
@@ -1674,6 +1674,22 @@ def test_parameters_required_after_depr_star(self):
1674
1674
)
1675
1675
self .expect_failure (block , err , lineno = 4 )
1676
1676
1677
+ def test_parameters_required_after_depr_star2 (self ):
1678
+ block = """
1679
+ module foo
1680
+ foo.bar
1681
+ a: int
1682
+ * [from 3.14]
1683
+ *
1684
+ b: int
1685
+ Docstring.
1686
+ """
1687
+ err = (
1688
+ "Function 'foo.bar' specifies '* [from ...]' without "
1689
+ "any parameters afterwards"
1690
+ )
1691
+ self .expect_failure (block , err , lineno = 4 )
1692
+
1677
1693
def test_depr_star_must_come_before_star (self ):
1678
1694
block = """
1679
1695
module foo
@@ -1697,7 +1713,21 @@ def test_depr_star_duplicate(self):
1697
1713
c: int
1698
1714
Docstring.
1699
1715
"""
1700
- err = "Function 'foo.bar' uses '[from ...]' more than once"
1716
+ err = "Function 'foo.bar' uses '* [from ...]' more than once."
1717
+ self .expect_failure (block , err , lineno = 5 )
1718
+
1719
+ def test_depr_slash_duplicate (self ):
1720
+ block = """
1721
+ module foo
1722
+ foo.bar
1723
+ a: int
1724
+ / [from 3.14]
1725
+ b: int
1726
+ / [from 3.14]
1727
+ c: int
1728
+ Docstring.
1729
+ """
1730
+ err = "Function 'bar' uses '/ [from ...]' more than once."
1701
1731
self .expect_failure (block , err , lineno = 5 )
1702
1732
1703
1733
def test_single_slash (self ):
@@ -1713,6 +1743,48 @@ def test_single_slash(self):
1713
1743
)
1714
1744
self .expect_failure (block , err )
1715
1745
1746
+ def test_parameters_required_before_depr_slash (self ):
1747
+ block = """
1748
+ module foo
1749
+ foo.bar
1750
+ / [from 3.14]
1751
+ Docstring.
1752
+ """
1753
+ err = (
1754
+ "Function 'bar' specifies '/ [from ...]' without "
1755
+ "any parameters beforehead."
1756
+ )
1757
+ self .expect_failure (block , err , lineno = 2 )
1758
+
1759
+ def test_parameters_required_before_depr_slash2 (self ):
1760
+ block = """
1761
+ module foo
1762
+ foo.bar
1763
+ /
1764
+ / [from 3.14]
1765
+ Docstring.
1766
+ """
1767
+ err = (
1768
+ "Function 'bar' has an unsupported group configuration. "
1769
+ "(Unexpected state 0.d)"
1770
+ )
1771
+ self .expect_failure (block , err , lineno = 2 )
1772
+
1773
+ def test_parameters_required_before_depr_slash3 (self ):
1774
+ block = """
1775
+ module foo
1776
+ foo.bar
1777
+ a: int
1778
+ /
1779
+ / [from 3.14]
1780
+ Docstring.
1781
+ """
1782
+ err = (
1783
+ "Function 'bar' specifies '/ [from ...]' without "
1784
+ "any parameters beforehead."
1785
+ )
1786
+ self .expect_failure (block , err , lineno = 4 )
1787
+
1716
1788
def test_double_slash (self ):
1717
1789
block = """
1718
1790
module foo
@@ -1741,6 +1813,67 @@ def test_mix_star_and_slash(self):
1741
1813
)
1742
1814
self .expect_failure (block , err )
1743
1815
1816
+ def test_depr_star_must_come_after_slash (self ):
1817
+ block = """
1818
+ module foo
1819
+ foo.bar
1820
+ a: int
1821
+ * [from 3.14]
1822
+ /
1823
+ b: int
1824
+ Docstring.
1825
+ """
1826
+ err = (
1827
+ "Function 'bar' mixes keyword-only and positional-only parameters, "
1828
+ "which is unsupported."
1829
+ )
1830
+ self .expect_failure (block , err , lineno = 4 )
1831
+
1832
+ def test_depr_star_must_come_after_depr_slash (self ):
1833
+ block = """
1834
+ module foo
1835
+ foo.bar
1836
+ a: int
1837
+ * [from 3.14]
1838
+ / [from 3.14]
1839
+ b: int
1840
+ Docstring.
1841
+ """
1842
+ err = (
1843
+ "Function 'bar' mixes keyword-only and positional-only parameters, "
1844
+ "which is unsupported."
1845
+ )
1846
+ self .expect_failure (block , err , lineno = 4 )
1847
+
1848
+ def test_star_must_come_after_depr_slash (self ):
1849
+ block = """
1850
+ module foo
1851
+ foo.bar
1852
+ a: int
1853
+ *
1854
+ / [from 3.14]
1855
+ b: int
1856
+ Docstring.
1857
+ """
1858
+ err = (
1859
+ "Function 'bar' mixes keyword-only and positional-only parameters, "
1860
+ "which is unsupported."
1861
+ )
1862
+ self .expect_failure (block , err , lineno = 4 )
1863
+
1864
+ def test_depr_slash_must_come_after_slash (self ):
1865
+ block = """
1866
+ module foo
1867
+ foo.bar
1868
+ a: int
1869
+ / [from 3.14]
1870
+ /
1871
+ b: int
1872
+ Docstring.
1873
+ """
1874
+ err = "Function 'foo.bar': '/ [from ...]' must come after '/'"
1875
+ self .expect_failure (block , err , lineno = 4 )
1876
+
1744
1877
def test_parameters_not_permitted_after_slash_for_now (self ):
1745
1878
block = """
1746
1879
module foo
@@ -2537,11 +2670,33 @@ class ClinicFunctionalTest(unittest.TestCase):
2537
2670
locals ().update ((name , getattr (ac_tester , name ))
2538
2671
for name in dir (ac_tester ) if name .startswith ('test_' ))
2539
2672
2540
- def check_depr_star (self , pnames , fn , * args , ** kwds ):
2673
+ def check_depr_star (self , pnames , fn , * args , name = None , ** kwds ):
2674
+ if name is None :
2675
+ name = fn .__qualname__
2676
+ if isinstance (fn , type ):
2677
+ name = f'{ fn .__module__ } .{ name } '
2541
2678
regex = (
2542
2679
fr"Passing( more than)?( [0-9]+)? positional argument(s)? to "
2543
- fr"{ fn .__name__ } \(\) is deprecated. Parameter(s)? { pnames } will "
2544
- fr"become( a)? keyword-only parameter(s)? in Python 3\.14"
2680
+ fr"{ re .escape (name )} \(\) is deprecated. Parameters? { pnames } will "
2681
+ fr"become( a)? keyword-only parameters? in Python 3\.14"
2682
+ )
2683
+ with self .assertWarnsRegex (DeprecationWarning , regex ) as cm :
2684
+ # Record the line number, so we're sure we've got the correct stack
2685
+ # level on the deprecation warning.
2686
+ _ , lineno = fn (* args , ** kwds ), sys ._getframe ().f_lineno
2687
+ self .assertEqual (cm .filename , __file__ )
2688
+ self .assertEqual (cm .lineno , lineno )
2689
+
2690
+ def check_depr_kwd (self , pnames , fn , * args , name = None , ** kwds ):
2691
+ if name is None :
2692
+ name = fn .__qualname__
2693
+ if isinstance (fn , type ):
2694
+ name = f'{ fn .__module__ } .{ name } '
2695
+ pl = 's' if ' ' in pnames else ''
2696
+ regex = (
2697
+ fr"Passing keyword argument{ pl } { pnames } to "
2698
+ fr"{ re .escape (name )} \(\) is deprecated. Corresponding parameter{ pl } "
2699
+ fr"will become positional-only in Python 3\.14."
2545
2700
)
2546
2701
with self .assertWarnsRegex (DeprecationWarning , regex ) as cm :
2547
2702
# Record the line number, so we're sure we've got the correct stack
@@ -3015,46 +3170,40 @@ def test_cloned_func_with_converter_exception_message(self):
3015
3170
self .assertEqual (func (), name )
3016
3171
3017
3172
def test_depr_star_new (self ):
3018
- regex = re .escape (
3019
- "Passing positional arguments to _testclinic.DeprStarNew() is "
3020
- "deprecated. Parameter 'a' will become a keyword-only parameter "
3021
- "in Python 3.14."
3022
- )
3023
- with self .assertWarnsRegex (DeprecationWarning , regex ) as cm :
3024
- ac_tester .DeprStarNew (None )
3025
- self .assertEqual (cm .filename , __file__ )
3173
+ cls = ac_tester .DeprStarNew
3174
+ cls (a = None )
3175
+ self .check_depr_star ("'a'" , cls , None )
3176
+ self .assertRaises (TypeError , cls )
3026
3177
3027
3178
def test_depr_star_new_cloned (self ):
3028
- regex = re .escape (
3029
- "Passing positional arguments to _testclinic.DeprStarNew.cloned() "
3030
- "is deprecated. Parameter 'a' will become a keyword-only parameter "
3031
- "in Python 3.14."
3032
- )
3033
- obj = ac_tester .DeprStarNew (a = None )
3034
- with self .assertWarnsRegex (DeprecationWarning , regex ) as cm :
3035
- obj .cloned (None )
3036
- self .assertEqual (cm .filename , __file__ )
3179
+ fn = ac_tester .DeprStarNew (a = None ).cloned
3180
+ fn (a = None )
3181
+ self .check_depr_star ("'a'" , fn , None , name = '_testclinic.DeprStarNew.cloned' )
3182
+ self .assertRaises (TypeError , fn )
3037
3183
3038
3184
def test_depr_star_init (self ):
3039
- regex = re .escape (
3040
- "Passing positional arguments to _testclinic.DeprStarInit() is "
3041
- "deprecated. Parameter 'a' will become a keyword-only parameter "
3042
- "in Python 3.14."
3043
- )
3044
- with self .assertWarnsRegex (DeprecationWarning , regex ) as cm :
3045
- ac_tester .DeprStarInit (None )
3046
- self .assertEqual (cm .filename , __file__ )
3185
+ cls = ac_tester .DeprStarInit
3186
+ cls (a = None )
3187
+ self .check_depr_star ("'a'" , cls , None )
3188
+ self .assertRaises (TypeError , cls )
3047
3189
3048
3190
def test_depr_star_init_cloned (self ):
3049
- regex = re .escape (
3050
- "Passing positional arguments to _testclinic.DeprStarInit.cloned() "
3051
- "is deprecated. Parameter 'a' will become a keyword-only parameter "
3052
- "in Python 3.14."
3053
- )
3054
- obj = ac_tester .DeprStarInit (a = None )
3055
- with self .assertWarnsRegex (DeprecationWarning , regex ) as cm :
3056
- obj .cloned (None )
3057
- self .assertEqual (cm .filename , __file__ )
3191
+ fn = ac_tester .DeprStarInit (a = None ).cloned
3192
+ fn (a = None )
3193
+ self .check_depr_star ("'a'" , fn , None , name = '_testclinic.DeprStarInit.cloned' )
3194
+ self .assertRaises (TypeError , fn )
3195
+
3196
+ def test_depr_kwd_new (self ):
3197
+ cls = ac_tester .DeprKwdNew
3198
+ cls (None )
3199
+ self .check_depr_kwd ("'a'" , cls , a = None )
3200
+ self .assertRaises (TypeError , cls )
3201
+
3202
+ def test_depr_kwd_init (self ):
3203
+ cls = ac_tester .DeprKwdInit
3204
+ cls (None )
3205
+ self .check_depr_kwd ("'a'" , cls , a = None )
3206
+ self .assertRaises (TypeError , cls )
3058
3207
3059
3208
def test_depr_star_pos0_len1 (self ):
3060
3209
fn = ac_tester .depr_star_pos0_len1
@@ -3125,6 +3274,90 @@ def test_depr_star_pos2_len2_with_kwd(self):
3125
3274
check ("a" , "b" , "c" , d = 0 , e = 0 )
3126
3275
check ("a" , "b" , "c" , "d" , e = 0 )
3127
3276
3277
+ def test_depr_kwd_required_1 (self ):
3278
+ fn = ac_tester .depr_kwd_required_1
3279
+ fn ("a" , "b" )
3280
+ self .assertRaises (TypeError , fn , "a" )
3281
+ self .assertRaises (TypeError , fn , "a" , "b" , "c" )
3282
+ check = partial (self .check_depr_kwd , "'b'" , fn )
3283
+ check ("a" , b = "b" )
3284
+ self .assertRaises (TypeError , fn , a = "a" , b = "b" )
3285
+
3286
+ def test_depr_kwd_required_2 (self ):
3287
+ fn = ac_tester .depr_kwd_required_2
3288
+ fn ("a" , "b" , "c" )
3289
+ self .assertRaises (TypeError , fn , "a" , "b" )
3290
+ self .assertRaises (TypeError , fn , "a" , "b" , "c" , "d" )
3291
+ check = partial (self .check_depr_kwd , "'b' and 'c'" , fn )
3292
+ check ("a" , "b" , c = "c" )
3293
+ check ("a" , b = "b" , c = "c" )
3294
+ self .assertRaises (TypeError , fn , a = "a" , b = "b" , c = "c" )
3295
+
3296
+ def test_depr_kwd_optional_1 (self ):
3297
+ fn = ac_tester .depr_kwd_optional_1
3298
+ fn ("a" )
3299
+ fn ("a" , "b" )
3300
+ self .assertRaises (TypeError , fn )
3301
+ self .assertRaises (TypeError , fn , "a" , "b" , "c" )
3302
+ check = partial (self .check_depr_kwd , "'b'" , fn )
3303
+ check ("a" , b = "b" )
3304
+ self .assertRaises (TypeError , fn , a = "a" , b = "b" )
3305
+
3306
+ def test_depr_kwd_optional_2 (self ):
3307
+ fn = ac_tester .depr_kwd_optional_2
3308
+ fn ("a" )
3309
+ fn ("a" , "b" )
3310
+ fn ("a" , "b" , "c" )
3311
+ self .assertRaises (TypeError , fn )
3312
+ self .assertRaises (TypeError , fn , "a" , "b" , "c" , "d" )
3313
+ check = partial (self .check_depr_kwd , "'b' and 'c'" , fn )
3314
+ check ("a" , b = "b" )
3315
+ check ("a" , c = "c" )
3316
+ check ("a" , b = "b" , c = "c" )
3317
+ check ("a" , c = "c" , b = "b" )
3318
+ check ("a" , "b" , c = "c" )
3319
+ self .assertRaises (TypeError , fn , a = "a" , b = "b" , c = "c" )
3320
+
3321
+ def test_depr_kwd_optional_3 (self ):
3322
+ fn = ac_tester .depr_kwd_optional_3
3323
+ fn ()
3324
+ fn ("a" )
3325
+ fn ("a" , "b" )
3326
+ fn ("a" , "b" , "c" )
3327
+ self .assertRaises (TypeError , fn , "a" , "b" , "c" , "d" )
3328
+ check = partial (self .check_depr_kwd , "'a', 'b' and 'c'" , fn )
3329
+ check ("a" , "b" , c = "c" )
3330
+ check ("a" , b = "b" )
3331
+ check (a = "a" )
3332
+
3333
+ def test_depr_kwd_required_optional (self ):
3334
+ fn = ac_tester .depr_kwd_required_optional
3335
+ fn ("a" , "b" )
3336
+ fn ("a" , "b" , "c" )
3337
+ self .assertRaises (TypeError , fn )
3338
+ self .assertRaises (TypeError , fn , "a" )
3339
+ self .assertRaises (TypeError , fn , "a" , "b" , "c" , "d" )
3340
+ check = partial (self .check_depr_kwd , "'b' and 'c'" , fn )
3341
+ check ("a" , b = "b" )
3342
+ check ("a" , b = "b" , c = "c" )
3343
+ check ("a" , c = "c" , b = "b" )
3344
+ check ("a" , "b" , c = "c" )
3345
+ self .assertRaises (TypeError , fn , "a" , c = "c" )
3346
+ self .assertRaises (TypeError , fn , a = "a" , b = "b" , c = "c" )
3347
+
3348
+ def test_depr_kwd_noinline (self ):
3349
+ fn = ac_tester .depr_kwd_noinline
3350
+ fn ("a" , "b" )
3351
+ fn ("a" , "b" , "c" )
3352
+ self .assertRaises (TypeError , fn , "a" )
3353
+ check = partial (self .check_depr_kwd , "'b' and 'c'" , fn )
3354
+ check ("a" , b = "b" )
3355
+ check ("a" , b = "b" , c = "c" )
3356
+ check ("a" , c = "c" , b = "b" )
3357
+ check ("a" , "b" , c = "c" )
3358
+ self .assertRaises (TypeError , fn , "a" , c = "c" )
3359
+ self .assertRaises (TypeError , fn , a = "a" , b = "b" , c = "c" )
3360
+
3128
3361
3129
3362
class PermutationTests (unittest .TestCase ):
3130
3363
"""Test permutation support functions."""
0 commit comments