(root)/
Python-3.11.7/
Lib/
test/
test_clinic.py
       1  # Argument Clinic
       2  # Copyright 2012-2013 by Larry Hastings.
       3  # Licensed to the PSF under a contributor agreement.
       4  
       5  from test import support, test_tools
       6  from test.support import os_helper
       7  from test.support import SHORT_TIMEOUT, requires_subprocess
       8  from test.support.os_helper import TESTFN, unlink
       9  from textwrap import dedent
      10  from unittest import TestCase
      11  import collections
      12  import inspect
      13  import os.path
      14  import subprocess
      15  import sys
      16  import unittest
      17  
      18  test_tools.skip_if_missing('clinic')
      19  with test_tools.imports_under_tool('clinic'):
      20      import clinic
      21      from clinic import DSLParser
      22  
      23  
      24  class ESC[4;38;5;81m_ParserBase(ESC[4;38;5;149mTestCase):
      25      maxDiff = None
      26  
      27      def expect_parser_failure(self, parser, _input):
      28          with support.captured_stdout() as stdout:
      29              with self.assertRaises(SystemExit):
      30                  parser(_input)
      31          return stdout.getvalue()
      32  
      33      def parse_function_should_fail(self, _input):
      34          return self.expect_parser_failure(self.parse_function, _input)
      35  
      36  
      37  class ESC[4;38;5;81mFakeConverter:
      38      def __init__(self, name, args):
      39          self.name = name
      40          self.args = args
      41  
      42  
      43  class ESC[4;38;5;81mFakeConverterFactory:
      44      def __init__(self, name):
      45          self.name = name
      46  
      47      def __call__(self, name, default, **kwargs):
      48          return FakeConverter(self.name, kwargs)
      49  
      50  
      51  class ESC[4;38;5;81mFakeConvertersDict:
      52      def __init__(self):
      53          self.used_converters = {}
      54  
      55      def get(self, name, default):
      56          return self.used_converters.setdefault(name, FakeConverterFactory(name))
      57  
      58  c = clinic.Clinic(language='C', filename = "file")
      59  
      60  class ESC[4;38;5;81mFakeClinic:
      61      def __init__(self):
      62          self.converters = FakeConvertersDict()
      63          self.legacy_converters = FakeConvertersDict()
      64          self.language = clinic.CLanguage(None)
      65          self.filename = None
      66          self.destination_buffers = {}
      67          self.block_parser = clinic.BlockParser('', self.language)
      68          self.modules = collections.OrderedDict()
      69          self.classes = collections.OrderedDict()
      70          clinic.clinic = self
      71          self.name = "FakeClinic"
      72          self.line_prefix = self.line_suffix = ''
      73          self.destinations = {}
      74          self.add_destination("block", "buffer")
      75          self.add_destination("file", "buffer")
      76          self.add_destination("suppress", "suppress")
      77          d = self.destinations.get
      78          self.field_destinations = collections.OrderedDict((
      79              ('docstring_prototype', d('suppress')),
      80              ('docstring_definition', d('block')),
      81              ('methoddef_define', d('block')),
      82              ('impl_prototype', d('block')),
      83              ('parser_prototype', d('suppress')),
      84              ('parser_definition', d('block')),
      85              ('impl_definition', d('block')),
      86          ))
      87  
      88      def get_destination(self, name):
      89          d = self.destinations.get(name)
      90          if not d:
      91              sys.exit("Destination does not exist: " + repr(name))
      92          return d
      93  
      94      def add_destination(self, name, type, *args):
      95          if name in self.destinations:
      96              sys.exit("Destination already exists: " + repr(name))
      97          self.destinations[name] = clinic.Destination(name, type, self, *args)
      98  
      99      def is_directive(self, name):
     100          return name == "module"
     101  
     102      def directive(self, name, args):
     103          self.called_directives[name] = args
     104  
     105      _module_and_class = clinic.Clinic._module_and_class
     106  
     107  
     108  class ESC[4;38;5;81mClinicWholeFileTest(ESC[4;38;5;149m_ParserBase):
     109      def setUp(self):
     110          self.clinic = clinic.Clinic(clinic.CLanguage(None), filename="test.c")
     111  
     112      def expect_failure(self, raw):
     113          _input = dedent(raw).strip()
     114          return self.expect_parser_failure(self.clinic.parse, _input)
     115  
     116      def test_eol(self):
     117          # regression test:
     118          # clinic's block parser didn't recognize
     119          # the "end line" for the block if it
     120          # didn't end in "\n" (as in, the last)
     121          # byte of the file was '/'.
     122          # so it would spit out an end line for you.
     123          # and since you really already had one,
     124          # the last line of the block got corrupted.
     125          raw = "/*[clinic]\nfoo\n[clinic]*/"
     126          cooked = self.clinic.parse(raw).splitlines()
     127          end_line = cooked[2].rstrip()
     128          # this test is redundant, it's just here explicitly to catch
     129          # the regression test so we don't forget what it looked like
     130          self.assertNotEqual(end_line, "[clinic]*/[clinic]*/")
     131          self.assertEqual(end_line, "[clinic]*/")
     132  
     133      def test_mangled_marker_line(self):
     134          raw = """
     135              /*[clinic input]
     136              [clinic start generated code]*/
     137              /*[clinic end generated code: foo]*/
     138          """
     139          msg = (
     140              'Error in file "test.c" on line 3:\n'
     141              "Mangled Argument Clinic marker line: '/*[clinic end generated code: foo]*/'\n"
     142          )
     143          out = self.expect_failure(raw)
     144          self.assertEqual(out, msg)
     145  
     146      def test_checksum_mismatch(self):
     147          raw = """
     148              /*[clinic input]
     149              [clinic start generated code]*/
     150              /*[clinic end generated code: output=0123456789abcdef input=fedcba9876543210]*/
     151          """
     152          msg = (
     153              'Error in file "test.c" on line 3:\n'
     154              'Checksum mismatch!\n'
     155              'Expected: 0123456789abcdef\n'
     156              'Computed: da39a3ee5e6b4b0d\n'
     157          )
     158          out = self.expect_failure(raw)
     159          self.assertIn(msg, out)
     160  
     161      def test_garbage_after_stop_line(self):
     162          raw = """
     163              /*[clinic input]
     164              [clinic start generated code]*/foobarfoobar!
     165          """
     166          msg = (
     167              'Error in file "test.c" on line 2:\n'
     168              "Garbage after stop line: 'foobarfoobar!'\n"
     169          )
     170          out = self.expect_failure(raw)
     171          self.assertEqual(out, msg)
     172  
     173      def test_whitespace_before_stop_line(self):
     174          raw = """
     175              /*[clinic input]
     176               [clinic start generated code]*/
     177          """
     178          msg = (
     179              'Error in file "test.c" on line 2:\n'
     180              "Whitespace is not allowed before the stop line: ' [clinic start generated code]*/'\n"
     181          )
     182          out = self.expect_failure(raw)
     183          self.assertEqual(out, msg)
     184  
     185      def test_parse_with_body_prefix(self):
     186          clang = clinic.CLanguage(None)
     187          clang.body_prefix = "//"
     188          clang.start_line = "//[{dsl_name} start]"
     189          clang.stop_line = "//[{dsl_name} stop]"
     190          cl = clinic.Clinic(clang, filename="test.c")
     191          raw = dedent("""
     192              //[clinic start]
     193              //module test
     194              //[clinic stop]
     195          """).strip()
     196          out = cl.parse(raw)
     197          expected = dedent("""
     198              //[clinic start]
     199              //module test
     200              //
     201              //[clinic stop]
     202              /*[clinic end generated code: output=da39a3ee5e6b4b0d input=65fab8adff58cf08]*/
     203          """).lstrip()  # Note, lstrip() because of the newline
     204          self.assertEqual(out, expected)
     205  
     206      def test_cpp_monitor_fail_nested_block_comment(self):
     207          raw = """
     208              /* start
     209              /* nested
     210              */
     211              */
     212          """
     213          msg = (
     214              'Error in file "test.c" on line 2:\n'
     215              'Nested block comment!\n'
     216          )
     217          out = self.expect_failure(raw)
     218          self.assertEqual(out, msg)
     219  
     220      def test_cpp_monitor_fail_invalid_format_noarg(self):
     221          raw = """
     222              #if
     223              a()
     224              #endif
     225          """
     226          msg = (
     227              'Error in file "test.c" on line 1:\n'
     228              'Invalid format for #if line: no argument!\n'
     229          )
     230          out = self.expect_failure(raw)
     231          self.assertEqual(out, msg)
     232  
     233      def test_cpp_monitor_fail_invalid_format_toomanyargs(self):
     234          raw = """
     235              #ifdef A B
     236              a()
     237              #endif
     238          """
     239          msg = (
     240              'Error in file "test.c" on line 1:\n'
     241              'Invalid format for #ifdef line: should be exactly one argument!\n'
     242          )
     243          out = self.expect_failure(raw)
     244          self.assertEqual(out, msg)
     245  
     246      def test_cpp_monitor_fail_no_matching_if(self):
     247          raw = '#else'
     248          msg = (
     249              'Error in file "test.c" on line 1:\n'
     250              '#else without matching #if / #ifdef / #ifndef!\n'
     251          )
     252          out = self.expect_failure(raw)
     253          self.assertEqual(out, msg)
     254  
     255      def test_directive_output_unknown_preset(self):
     256          out = self.expect_failure("""
     257              /*[clinic input]
     258              output preset nosuchpreset
     259              [clinic start generated code]*/
     260          """)
     261          msg = "Unknown preset 'nosuchpreset'"
     262          self.assertIn(msg, out)
     263  
     264      def test_directive_output_cant_pop(self):
     265          out = self.expect_failure("""
     266              /*[clinic input]
     267              output pop
     268              [clinic start generated code]*/
     269          """)
     270          msg = "Can't 'output pop', stack is empty"
     271          self.assertIn(msg, out)
     272  
     273      def test_directive_output_print(self):
     274          raw = dedent("""
     275              /*[clinic input]
     276              output print 'I told you once.'
     277              [clinic start generated code]*/
     278          """)
     279          out = self.clinic.parse(raw)
     280          # The generated output will differ for every run, but we can check that
     281          # it starts with the clinic block, we check that it contains all the
     282          # expected fields, and we check that it contains the checksum line.
     283          self.assertTrue(out.startswith(dedent("""
     284              /*[clinic input]
     285              output print 'I told you once.'
     286              [clinic start generated code]*/
     287          """)))
     288          fields = {
     289              "cpp_endif",
     290              "cpp_if",
     291              "docstring_definition",
     292              "docstring_prototype",
     293              "impl_definition",
     294              "impl_prototype",
     295              "methoddef_define",
     296              "methoddef_ifndef",
     297              "parser_definition",
     298              "parser_prototype",
     299          }
     300          for field in fields:
     301              with self.subTest(field=field):
     302                  self.assertIn(field, out)
     303          last_line = out.rstrip().split("\n")[-1]
     304          self.assertTrue(
     305              last_line.startswith("/*[clinic end generated code: output=")
     306          )
     307  
     308      def test_unknown_destination_command(self):
     309          out = self.expect_failure("""
     310              /*[clinic input]
     311              destination buffer nosuchcommand
     312              [clinic start generated code]*/
     313          """)
     314          msg = "unknown destination command 'nosuchcommand'"
     315          self.assertIn(msg, out)
     316  
     317      def test_no_access_to_members_in_converter_init(self):
     318          out = self.expect_failure("""
     319              /*[python input]
     320              class Custom_converter(CConverter):
     321                  converter = "some_c_function"
     322                  def converter_init(self):
     323                      self.function.noaccess
     324              [python start generated code]*/
     325              /*[clinic input]
     326              module test
     327              test.fn
     328                  a: Custom
     329              [clinic start generated code]*/
     330          """)
     331          msg = (
     332              "Stepped on a land mine, trying to access attribute 'noaccess':\n"
     333              "Don't access members of self.function inside converter_init!"
     334          )
     335          self.assertIn(msg, out)
     336  
     337  
     338  class ESC[4;38;5;81mClinicGroupPermuterTest(ESC[4;38;5;149mTestCase):
     339      def _test(self, l, m, r, output):
     340          computed = clinic.permute_optional_groups(l, m, r)
     341          self.assertEqual(output, computed)
     342  
     343      def test_range(self):
     344          self._test([['start']], ['stop'], [['step']],
     345            (
     346              ('stop',),
     347              ('start', 'stop',),
     348              ('start', 'stop', 'step',),
     349            ))
     350  
     351      def test_add_window(self):
     352          self._test([['x', 'y']], ['ch'], [['attr']],
     353            (
     354              ('ch',),
     355              ('ch', 'attr'),
     356              ('x', 'y', 'ch',),
     357              ('x', 'y', 'ch', 'attr'),
     358            ))
     359  
     360      def test_ludicrous(self):
     361          self._test([['a1', 'a2', 'a3'], ['b1', 'b2']], ['c1'], [['d1', 'd2'], ['e1', 'e2', 'e3']],
     362            (
     363            ('c1',),
     364            ('b1', 'b2', 'c1'),
     365            ('b1', 'b2', 'c1', 'd1', 'd2'),
     366            ('a1', 'a2', 'a3', 'b1', 'b2', 'c1'),
     367            ('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2'),
     368            ('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2', 'e1', 'e2', 'e3'),
     369            ))
     370  
     371      def test_right_only(self):
     372          self._test([], [], [['a'],['b'],['c']],
     373            (
     374            (),
     375            ('a',),
     376            ('a', 'b'),
     377            ('a', 'b', 'c')
     378            ))
     379  
     380      def test_have_left_options_but_required_is_empty(self):
     381          def fn():
     382              clinic.permute_optional_groups(['a'], [], [])
     383          self.assertRaises(AssertionError, fn)
     384  
     385  
     386  class ESC[4;38;5;81mClinicLinearFormatTest(ESC[4;38;5;149mTestCase):
     387      def _test(self, input, output, **kwargs):
     388          computed = clinic.linear_format(input, **kwargs)
     389          self.assertEqual(output, computed)
     390  
     391      def test_empty_strings(self):
     392          self._test('', '')
     393  
     394      def test_solo_newline(self):
     395          self._test('\n', '\n')
     396  
     397      def test_no_substitution(self):
     398          self._test("""
     399            abc
     400          """, """
     401            abc
     402          """)
     403  
     404      def test_empty_substitution(self):
     405          self._test("""
     406            abc
     407            {name}
     408            def
     409          """, """
     410            abc
     411            def
     412          """, name='')
     413  
     414      def test_single_line_substitution(self):
     415          self._test("""
     416            abc
     417            {name}
     418            def
     419          """, """
     420            abc
     421            GARGLE
     422            def
     423          """, name='GARGLE')
     424  
     425      def test_multiline_substitution(self):
     426          self._test("""
     427            abc
     428            {name}
     429            def
     430          """, """
     431            abc
     432            bingle
     433            bungle
     434  
     435            def
     436          """, name='bingle\nbungle\n')
     437  
     438  class ESC[4;38;5;81mInertParser:
     439      def __init__(self, clinic):
     440          pass
     441  
     442      def parse(self, block):
     443          pass
     444  
     445  class ESC[4;38;5;81mCopyParser:
     446      def __init__(self, clinic):
     447          pass
     448  
     449      def parse(self, block):
     450          block.output = block.input
     451  
     452  
     453  class ESC[4;38;5;81mClinicBlockParserTest(ESC[4;38;5;149mTestCase):
     454      def _test(self, input, output):
     455          language = clinic.CLanguage(None)
     456  
     457          blocks = list(clinic.BlockParser(input, language))
     458          writer = clinic.BlockPrinter(language)
     459          for block in blocks:
     460              writer.print_block(block)
     461          output = writer.f.getvalue()
     462          assert output == input, "output != input!\n\noutput " + repr(output) + "\n\n input " + repr(input)
     463  
     464      def round_trip(self, input):
     465          return self._test(input, input)
     466  
     467      def test_round_trip_1(self):
     468          self.round_trip("""
     469              verbatim text here
     470              lah dee dah
     471          """)
     472      def test_round_trip_2(self):
     473          self.round_trip("""
     474      verbatim text here
     475      lah dee dah
     476  /*[inert]
     477  abc
     478  [inert]*/
     479  def
     480  /*[inert checksum: 7b18d017f89f61cf17d47f92749ea6930a3f1deb]*/
     481  xyz
     482  """)
     483  
     484      def _test_clinic(self, input, output):
     485          language = clinic.CLanguage(None)
     486          c = clinic.Clinic(language, filename="file")
     487          c.parsers['inert'] = InertParser(c)
     488          c.parsers['copy'] = CopyParser(c)
     489          computed = c.parse(input)
     490          self.assertEqual(output, computed)
     491  
     492      def test_clinic_1(self):
     493          self._test_clinic("""
     494      verbatim text here
     495      lah dee dah
     496  /*[copy input]
     497  def
     498  [copy start generated code]*/
     499  abc
     500  /*[copy end generated code: output=03cfd743661f0797 input=7b18d017f89f61cf]*/
     501  xyz
     502  """, """
     503      verbatim text here
     504      lah dee dah
     505  /*[copy input]
     506  def
     507  [copy start generated code]*/
     508  def
     509  /*[copy end generated code: output=7b18d017f89f61cf input=7b18d017f89f61cf]*/
     510  xyz
     511  """)
     512  
     513  
     514  class ESC[4;38;5;81mClinicParserTest(ESC[4;38;5;149m_ParserBase):
     515      def checkDocstring(self, fn, expected):
     516          self.assertTrue(hasattr(fn, "docstring"))
     517          self.assertEqual(fn.docstring.strip(),
     518                           dedent(expected).strip())
     519  
     520      def test_trivial(self):
     521          parser = DSLParser(FakeClinic())
     522          block = clinic.Block("""
     523              module os
     524              os.access
     525          """)
     526          parser.parse(block)
     527          module, function = block.signatures
     528          self.assertEqual("access", function.name)
     529          self.assertEqual("os", module.name)
     530  
     531      def test_ignore_line(self):
     532          block = self.parse(dedent("""
     533              #
     534              module os
     535              os.access
     536          """))
     537          module, function = block.signatures
     538          self.assertEqual("access", function.name)
     539          self.assertEqual("os", module.name)
     540  
     541      def test_param(self):
     542          function = self.parse_function("""
     543              module os
     544              os.access
     545                  path: int
     546          """)
     547          self.assertEqual("access", function.name)
     548          self.assertEqual(2, len(function.parameters))
     549          p = function.parameters['path']
     550          self.assertEqual('path', p.name)
     551          self.assertIsInstance(p.converter, clinic.int_converter)
     552  
     553      def test_param_default(self):
     554          function = self.parse_function("""
     555              module os
     556              os.access
     557                  follow_symlinks: bool = True
     558          """)
     559          p = function.parameters['follow_symlinks']
     560          self.assertEqual(True, p.default)
     561  
     562      def test_param_with_continuations(self):
     563          function = self.parse_function(r"""
     564              module os
     565              os.access
     566                  follow_symlinks: \
     567                  bool \
     568                  = \
     569                  True
     570          """)
     571          p = function.parameters['follow_symlinks']
     572          self.assertEqual(True, p.default)
     573  
     574      def test_param_default_expression(self):
     575          function = self.parse_function("""
     576              module os
     577              os.access
     578                  follow_symlinks: int(c_default='MAXSIZE') = sys.maxsize
     579              """)
     580          p = function.parameters['follow_symlinks']
     581          self.assertEqual(sys.maxsize, p.default)
     582          self.assertEqual("MAXSIZE", p.converter.c_default)
     583  
     584          expected_msg = (
     585              "Error on line 0:\n"
     586              "When you specify a named constant ('sys.maxsize') as your default value,\n"
     587              "you MUST specify a valid c_default.\n"
     588          )
     589          out = self.parse_function_should_fail("""
     590              module os
     591              os.access
     592                  follow_symlinks: int = sys.maxsize
     593          """)
     594          self.assertEqual(out, expected_msg)
     595  
     596      def test_param_no_docstring(self):
     597          function = self.parse_function("""
     598              module os
     599              os.access
     600                  follow_symlinks: bool = True
     601                  something_else: str = ''
     602          """)
     603          p = function.parameters['follow_symlinks']
     604          self.assertEqual(3, len(function.parameters))
     605          conv = function.parameters['something_else'].converter
     606          self.assertIsInstance(conv, clinic.str_converter)
     607  
     608      def test_param_default_parameters_out_of_order(self):
     609          expected_msg = (
     610              "Error on line 0:\n"
     611              "Can't have a parameter without a default ('something_else')\n"
     612              "after a parameter with a default!\n"
     613          )
     614          out = self.parse_function_should_fail("""
     615              module os
     616              os.access
     617                  follow_symlinks: bool = True
     618                  something_else: str""")
     619          self.assertEqual(out, expected_msg)
     620  
     621      def disabled_test_converter_arguments(self):
     622          function = self.parse_function("""
     623              module os
     624              os.access
     625                  path: path_t(allow_fd=1)
     626          """)
     627          p = function.parameters['path']
     628          self.assertEqual(1, p.converter.args['allow_fd'])
     629  
     630      def test_function_docstring(self):
     631          function = self.parse_function("""
     632              module os
     633              os.stat as os_stat_fn
     634  
     635                 path: str
     636                     Path to be examined
     637  
     638              Perform a stat system call on the given path.
     639          """)
     640          self.checkDocstring(function, """
     641              stat($module, /, path)
     642              --
     643  
     644              Perform a stat system call on the given path.
     645  
     646                path
     647                  Path to be examined
     648          """)
     649  
     650      def test_explicit_parameters_in_docstring(self):
     651          function = self.parse_function(dedent("""
     652              module foo
     653              foo.bar
     654                x: int
     655                   Documentation for x.
     656                y: int
     657  
     658              This is the documentation for foo.
     659  
     660              Okay, we're done here.
     661          """))
     662          self.checkDocstring(function, """
     663              bar($module, /, x, y)
     664              --
     665  
     666              This is the documentation for foo.
     667  
     668                x
     669                  Documentation for x.
     670  
     671              Okay, we're done here.
     672          """)
     673  
     674      def test_parser_regression_special_character_in_parameter_column_of_docstring_first_line(self):
     675          function = self.parse_function(dedent("""
     676              module os
     677              os.stat
     678                  path: str
     679              This/used to break Clinic!
     680          """))
     681          self.checkDocstring(function, """
     682              stat($module, /, path)
     683              --
     684  
     685              This/used to break Clinic!
     686          """)
     687  
     688      def test_c_name(self):
     689          function = self.parse_function("""
     690              module os
     691              os.stat as os_stat_fn
     692          """)
     693          self.assertEqual("os_stat_fn", function.c_basename)
     694  
     695      def test_return_converter(self):
     696          function = self.parse_function("""
     697              module os
     698              os.stat -> int
     699          """)
     700          self.assertIsInstance(function.return_converter, clinic.int_return_converter)
     701  
     702      def test_star(self):
     703          function = self.parse_function("""
     704              module os
     705              os.access
     706                  *
     707                  follow_symlinks: bool = True
     708          """)
     709          p = function.parameters['follow_symlinks']
     710          self.assertEqual(inspect.Parameter.KEYWORD_ONLY, p.kind)
     711          self.assertEqual(0, p.group)
     712  
     713      def test_group(self):
     714          function = self.parse_function("""
     715              module window
     716              window.border
     717                  [
     718                  ls: int
     719                  ]
     720                  /
     721          """)
     722          p = function.parameters['ls']
     723          self.assertEqual(1, p.group)
     724  
     725      def test_left_group(self):
     726          function = self.parse_function("""
     727              module curses
     728              curses.addch
     729                  [
     730                  y: int
     731                      Y-coordinate.
     732                  x: int
     733                      X-coordinate.
     734                  ]
     735                  ch: char
     736                      Character to add.
     737                  [
     738                  attr: long
     739                      Attributes for the character.
     740                  ]
     741                  /
     742          """)
     743          dataset = (
     744              ('y', -1), ('x', -1),
     745              ('ch', 0),
     746              ('attr', 1),
     747          )
     748          for name, group in dataset:
     749              with self.subTest(name=name, group=group):
     750                  p = function.parameters[name]
     751                  self.assertEqual(p.group, group)
     752                  self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
     753          self.checkDocstring(function, """
     754              addch([y, x,] ch, [attr])
     755  
     756  
     757                y
     758                  Y-coordinate.
     759                x
     760                  X-coordinate.
     761                ch
     762                  Character to add.
     763                attr
     764                  Attributes for the character.
     765          """)
     766  
     767      def test_nested_groups(self):
     768          function = self.parse_function("""
     769              module curses
     770              curses.imaginary
     771                 [
     772                 [
     773                 y1: int
     774                   Y-coordinate.
     775                 y2: int
     776                   Y-coordinate.
     777                 ]
     778                 x1: int
     779                   X-coordinate.
     780                 x2: int
     781                   X-coordinate.
     782                 ]
     783                 ch: char
     784                   Character to add.
     785                 [
     786                 attr1: long
     787                   Attributes for the character.
     788                 attr2: long
     789                   Attributes for the character.
     790                 attr3: long
     791                   Attributes for the character.
     792                 [
     793                 attr4: long
     794                   Attributes for the character.
     795                 attr5: long
     796                   Attributes for the character.
     797                 attr6: long
     798                   Attributes for the character.
     799                 ]
     800                 ]
     801                 /
     802          """)
     803          dataset = (
     804              ('y1', -2), ('y2', -2),
     805              ('x1', -1), ('x2', -1),
     806              ('ch', 0),
     807              ('attr1', 1), ('attr2', 1), ('attr3', 1),
     808              ('attr4', 2), ('attr5', 2), ('attr6', 2),
     809          )
     810          for name, group in dataset:
     811              with self.subTest(name=name, group=group):
     812                  p = function.parameters[name]
     813                  self.assertEqual(p.group, group)
     814                  self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
     815  
     816          self.checkDocstring(function, """
     817              imaginary([[y1, y2,] x1, x2,] ch, [attr1, attr2, attr3, [attr4, attr5,
     818                        attr6]])
     819  
     820  
     821                y1
     822                  Y-coordinate.
     823                y2
     824                  Y-coordinate.
     825                x1
     826                  X-coordinate.
     827                x2
     828                  X-coordinate.
     829                ch
     830                  Character to add.
     831                attr1
     832                  Attributes for the character.
     833                attr2
     834                  Attributes for the character.
     835                attr3
     836                  Attributes for the character.
     837                attr4
     838                  Attributes for the character.
     839                attr5
     840                  Attributes for the character.
     841                attr6
     842                  Attributes for the character.
     843          """)
     844  
     845      def parse_function_should_fail(self, s):
     846          with support.captured_stdout() as stdout:
     847              with self.assertRaises(SystemExit):
     848                  self.parse_function(s)
     849          return stdout.getvalue()
     850  
     851      def test_disallowed_grouping__two_top_groups_on_left(self):
     852          expected_msg = (
     853              'Error on line 0:\n'
     854              'Function two_top_groups_on_left has an unsupported group '
     855              'configuration. (Unexpected state 2.b)\n'
     856          )
     857          out = self.parse_function_should_fail("""
     858              module foo
     859              foo.two_top_groups_on_left
     860                  [
     861                  group1 : int
     862                  ]
     863                  [
     864                  group2 : int
     865                  ]
     866                  param: int
     867          """)
     868          self.assertEqual(out, expected_msg)
     869  
     870      def test_disallowed_grouping__two_top_groups_on_right(self):
     871          out = self.parse_function_should_fail("""
     872              module foo
     873              foo.two_top_groups_on_right
     874                  param: int
     875                  [
     876                  group1 : int
     877                  ]
     878                  [
     879                  group2 : int
     880                  ]
     881          """)
     882          msg = (
     883              "Function two_top_groups_on_right has an unsupported group "
     884              "configuration. (Unexpected state 6.b)"
     885          )
     886          self.assertIn(msg, out)
     887  
     888      def test_disallowed_grouping__parameter_after_group_on_right(self):
     889          out = self.parse_function_should_fail("""
     890              module foo
     891              foo.parameter_after_group_on_right
     892                  param: int
     893                  [
     894                  [
     895                  group1 : int
     896                  ]
     897                  group2 : int
     898                  ]
     899          """)
     900          msg = (
     901              "Function parameter_after_group_on_right has an unsupported group "
     902              "configuration. (Unexpected state 6.a)"
     903          )
     904          self.assertIn(msg, out)
     905  
     906      def test_disallowed_grouping__group_after_parameter_on_left(self):
     907          out = self.parse_function_should_fail("""
     908              module foo
     909              foo.group_after_parameter_on_left
     910                  [
     911                  group2 : int
     912                  [
     913                  group1 : int
     914                  ]
     915                  ]
     916                  param: int
     917          """)
     918          msg = (
     919              "Function group_after_parameter_on_left has an unsupported group "
     920              "configuration. (Unexpected state 2.b)"
     921          )
     922          self.assertIn(msg, out)
     923  
     924      def test_disallowed_grouping__empty_group_on_left(self):
     925          out = self.parse_function_should_fail("""
     926              module foo
     927              foo.empty_group
     928                  [
     929                  [
     930                  ]
     931                  group2 : int
     932                  ]
     933                  param: int
     934          """)
     935          msg = (
     936              "Function empty_group has an empty group.\n"
     937              "All groups must contain at least one parameter."
     938          )
     939          self.assertIn(msg, out)
     940  
     941      def test_disallowed_grouping__empty_group_on_right(self):
     942          out = self.parse_function_should_fail("""
     943              module foo
     944              foo.empty_group
     945                  param: int
     946                  [
     947                  [
     948                  ]
     949                  group2 : int
     950                  ]
     951          """)
     952          msg = (
     953              "Function empty_group has an empty group.\n"
     954              "All groups must contain at least one parameter."
     955          )
     956          self.assertIn(msg, out)
     957  
     958      def test_disallowed_grouping__no_matching_bracket(self):
     959          out = self.parse_function_should_fail("""
     960              module foo
     961              foo.empty_group
     962                  param: int
     963                  ]
     964                  group2: int
     965                  ]
     966          """)
     967          msg = "Function empty_group has a ] without a matching [."
     968          self.assertIn(msg, out)
     969  
     970      def test_no_parameters(self):
     971          function = self.parse_function("""
     972              module foo
     973              foo.bar
     974  
     975              Docstring
     976  
     977          """)
     978          self.assertEqual("bar($module, /)\n--\n\nDocstring", function.docstring)
     979          self.assertEqual(1, len(function.parameters)) # self!
     980  
     981      def test_init_with_no_parameters(self):
     982          function = self.parse_function("""
     983              module foo
     984              class foo.Bar "unused" "notneeded"
     985              foo.Bar.__init__
     986  
     987              Docstring
     988  
     989          """, signatures_in_block=3, function_index=2)
     990  
     991          # self is not in the signature
     992          self.assertEqual("Bar()\n--\n\nDocstring", function.docstring)
     993          # but it *is* a parameter
     994          self.assertEqual(1, len(function.parameters))
     995  
     996      def test_illegal_module_line(self):
     997          out = self.parse_function_should_fail("""
     998              module foo
     999              foo.bar => int
    1000                  /
    1001          """)
    1002          msg = "Illegal function name: foo.bar => int"
    1003          self.assertIn(msg, out)
    1004  
    1005      def test_illegal_c_basename(self):
    1006          out = self.parse_function_should_fail("""
    1007              module foo
    1008              foo.bar as 935
    1009                  /
    1010          """)
    1011          msg = "Illegal C basename: 935"
    1012          self.assertIn(msg, out)
    1013  
    1014      def test_single_star(self):
    1015          out = self.parse_function_should_fail("""
    1016              module foo
    1017              foo.bar
    1018                  *
    1019                  *
    1020          """)
    1021          self.assertIn("Function bar uses '*' more than once.", out)
    1022  
    1023      def test_parameters_required_after_star(self):
    1024          dataset = (
    1025              "module foo\nfoo.bar\n  *",
    1026              "module foo\nfoo.bar\n  *\nDocstring here.",
    1027              "module foo\nfoo.bar\n  this: int\n  *",
    1028              "module foo\nfoo.bar\n  this: int\n  *\nDocstring.",
    1029          )
    1030          msg = "Function bar specifies '*' without any parameters afterwards."
    1031          for block in dataset:
    1032              with self.subTest(block=block):
    1033                  out = self.parse_function_should_fail(block)
    1034                  self.assertIn(msg, out)
    1035  
    1036      def test_single_slash(self):
    1037          out = self.parse_function_should_fail("""
    1038              module foo
    1039              foo.bar
    1040                  /
    1041                  /
    1042          """)
    1043          msg = (
    1044              "Function bar has an unsupported group configuration. "
    1045              "(Unexpected state 0.d)"
    1046          )
    1047          self.assertIn(msg, out)
    1048  
    1049      def test_double_slash(self):
    1050          out = self.parse_function_should_fail("""
    1051              module foo
    1052              foo.bar
    1053                  a: int
    1054                  /
    1055                  b: int
    1056                  /
    1057          """)
    1058          msg = "Function bar uses '/' more than once."
    1059          self.assertIn(msg, out)
    1060  
    1061      def test_mix_star_and_slash(self):
    1062          out = self.parse_function_should_fail("""
    1063              module foo
    1064              foo.bar
    1065                 x: int
    1066                 y: int
    1067                 *
    1068                 z: int
    1069                 /
    1070          """)
    1071          msg = (
    1072              "Function bar mixes keyword-only and positional-only parameters, "
    1073              "which is unsupported."
    1074          )
    1075          self.assertIn(msg, out)
    1076  
    1077      def test_parameters_not_permitted_after_slash_for_now(self):
    1078          out = self.parse_function_should_fail("""
    1079              module foo
    1080              foo.bar
    1081                  /
    1082                  x: int
    1083          """)
    1084          msg = (
    1085              "Function bar has an unsupported group configuration. "
    1086              "(Unexpected state 0.d)"
    1087          )
    1088          self.assertIn(msg, out)
    1089  
    1090      def test_parameters_no_more_than_one_vararg(self):
    1091          expected_msg = (
    1092              "Error on line 0:\n"
    1093              "Too many var args\n"
    1094          )
    1095          out = self.parse_function_should_fail("""
    1096              module foo
    1097              foo.bar
    1098                 *vararg1: object
    1099                 *vararg2: object
    1100          """)
    1101          self.assertEqual(out, expected_msg)
    1102  
    1103      def test_function_not_at_column_0(self):
    1104          function = self.parse_function("""
    1105                module foo
    1106                foo.bar
    1107                  x: int
    1108                    Nested docstring here, goeth.
    1109                  *
    1110                  y: str
    1111                Not at column 0!
    1112          """)
    1113          self.checkDocstring(function, """
    1114              bar($module, /, x, *, y)
    1115              --
    1116  
    1117              Not at column 0!
    1118  
    1119                x
    1120                  Nested docstring here, goeth.
    1121          """)
    1122  
    1123      def test_indent_stack_no_tabs(self):
    1124          out = self.parse_function_should_fail("""
    1125              module foo
    1126              foo.bar
    1127                 *vararg1: object
    1128              \t*vararg2: object
    1129          """)
    1130          msg = "Tab characters are illegal in the Clinic DSL."
    1131          self.assertIn(msg, out)
    1132  
    1133      def test_indent_stack_illegal_outdent(self):
    1134          out = self.parse_function_should_fail("""
    1135              module foo
    1136              foo.bar
    1137                a: object
    1138               b: object
    1139          """)
    1140          self.assertIn("Illegal outdent", out)
    1141  
    1142      def test_directive(self):
    1143          c = FakeClinic()
    1144          parser = DSLParser(c)
    1145          parser.flag = False
    1146          parser.directives['setflag'] = lambda : setattr(parser, 'flag', True)
    1147          block = clinic.Block("setflag")
    1148          parser.parse(block)
    1149          self.assertTrue(parser.flag)
    1150  
    1151      def test_legacy_converters(self):
    1152          block = self.parse('module os\nos.access\n   path: "s"')
    1153          module, function = block.signatures
    1154          conv = (function.parameters['path']).converter
    1155          self.assertIsInstance(conv, clinic.str_converter)
    1156  
    1157      def test_legacy_converters_non_string_constant_annotation(self):
    1158          expected_failure_message = (
    1159              "Error on line 0:\n"
    1160              "Annotations must be either a name, a function call, or a string.\n"
    1161          )
    1162          dataset = (
    1163              'module os\nos.access\n   path: 42',
    1164              'module os\nos.access\n   path: 42.42',
    1165              'module os\nos.access\n   path: 42j',
    1166              'module os\nos.access\n   path: b"42"',
    1167          )
    1168          for block in dataset:
    1169              with self.subTest(block=block):
    1170                  out = self.parse_function_should_fail(block)
    1171                  self.assertEqual(out, expected_failure_message)
    1172  
    1173      def test_other_bizarre_things_in_annotations_fail(self):
    1174          expected_failure_message = (
    1175              "Error on line 0:\n"
    1176              "Annotations must be either a name, a function call, or a string.\n"
    1177          )
    1178          dataset = (
    1179              'module os\nos.access\n   path: {"some": "dictionary"}',
    1180              'module os\nos.access\n   path: ["list", "of", "strings"]',
    1181              'module os\nos.access\n   path: (x for x in range(42))',
    1182          )
    1183          for block in dataset:
    1184              with self.subTest(block=block):
    1185                  out = self.parse_function_should_fail(block)
    1186                  self.assertEqual(out, expected_failure_message)
    1187  
    1188      def test_self_param_placement(self):
    1189          expected_error_msg = (
    1190              "Error on line 0:\n"
    1191              "A 'self' parameter, if specified, must be the very first thing "
    1192              "in the parameter block.\n"
    1193          )
    1194          block = """
    1195              module foo
    1196              foo.func
    1197                  a: int
    1198                  self: self(type="PyObject *")
    1199          """
    1200          out = self.parse_function_should_fail(block)
    1201          self.assertEqual(out, expected_error_msg)
    1202  
    1203      def test_self_param_cannot_be_optional(self):
    1204          expected_error_msg = (
    1205              "Error on line 0:\n"
    1206              "A 'self' parameter cannot be marked optional.\n"
    1207          )
    1208          block = """
    1209              module foo
    1210              foo.func
    1211                  self: self(type="PyObject *") = None
    1212          """
    1213          out = self.parse_function_should_fail(block)
    1214          self.assertEqual(out, expected_error_msg)
    1215  
    1216      def test_defining_class_param_placement(self):
    1217          expected_error_msg = (
    1218              "Error on line 0:\n"
    1219              "A 'defining_class' parameter, if specified, must either be the "
    1220              "first thing in the parameter block, or come just after 'self'.\n"
    1221          )
    1222          block = """
    1223              module foo
    1224              foo.func
    1225                  self: self(type="PyObject *")
    1226                  a: int
    1227                  cls: defining_class
    1228          """
    1229          out = self.parse_function_should_fail(block)
    1230          self.assertEqual(out, expected_error_msg)
    1231  
    1232      def test_defining_class_param_cannot_be_optional(self):
    1233          expected_error_msg = (
    1234              "Error on line 0:\n"
    1235              "A 'defining_class' parameter cannot be marked optional.\n"
    1236          )
    1237          block = """
    1238              module foo
    1239              foo.func
    1240                  cls: defining_class(type="PyObject *") = None
    1241          """
    1242          out = self.parse_function_should_fail(block)
    1243          self.assertEqual(out, expected_error_msg)
    1244  
    1245      def test_slot_methods_cannot_access_defining_class(self):
    1246          block = """
    1247              module foo
    1248              class Foo "" ""
    1249              Foo.__init__
    1250                  cls: defining_class
    1251                  a: object
    1252          """
    1253          msg = "Slot methods cannot access their defining class."
    1254          with self.assertRaisesRegex(ValueError, msg):
    1255              self.parse_function(block)
    1256  
    1257      def test_new_must_be_a_class_method(self):
    1258          expected_error_msg = (
    1259              "Error on line 0:\n"
    1260              "__new__ must be a class method!\n"
    1261          )
    1262          out = self.parse_function_should_fail("""
    1263              module foo
    1264              class Foo "" ""
    1265              Foo.__new__
    1266          """)
    1267          self.assertEqual(out, expected_error_msg)
    1268  
    1269      def test_init_must_be_a_normal_method(self):
    1270          expected_error_msg = (
    1271              "Error on line 0:\n"
    1272              "__init__ must be a normal method, not a class or static method!\n"
    1273          )
    1274          out = self.parse_function_should_fail("""
    1275              module foo
    1276              class Foo "" ""
    1277              @classmethod
    1278              Foo.__init__
    1279          """)
    1280          self.assertEqual(out, expected_error_msg)
    1281  
    1282      def parse(self, text):
    1283          c = FakeClinic()
    1284          parser = DSLParser(c)
    1285          block = clinic.Block(text)
    1286          parser.parse(block)
    1287          return block
    1288  
    1289      def parse_function(self, text, signatures_in_block=2, function_index=1):
    1290          block = self.parse(text)
    1291          s = block.signatures
    1292          self.assertEqual(len(s), signatures_in_block)
    1293          assert isinstance(s[0], clinic.Module)
    1294          assert isinstance(s[function_index], clinic.Function)
    1295          return s[function_index]
    1296  
    1297      def test_scaffolding(self):
    1298          # test repr on special values
    1299          self.assertEqual(repr(clinic.unspecified), '<Unspecified>')
    1300          self.assertEqual(repr(clinic.NULL), '<Null>')
    1301  
    1302          # test that fail fails
    1303          expected = (
    1304              'Error in file "clown.txt" on line 69:\n'
    1305              'The igloos are melting!\n'
    1306          )
    1307          with support.captured_stdout() as stdout:
    1308              with self.assertRaises(SystemExit):
    1309                  clinic.fail('The igloos are melting!',
    1310                              filename='clown.txt', line_number=69)
    1311          actual = stdout.getvalue()
    1312          self.assertEqual(actual, expected)
    1313  
    1314  
    1315  class ESC[4;38;5;81mClinicExternalTest(ESC[4;38;5;149mTestCase):
    1316      maxDiff = None
    1317      clinic_py = os.path.join(test_tools.toolsdir, "clinic", "clinic.py")
    1318  
    1319      def _do_test(self, *args, expect_success=True):
    1320          with subprocess.Popen(
    1321              [sys.executable, "-Xutf8", self.clinic_py, *args],
    1322              encoding="utf-8",
    1323              bufsize=0,
    1324              stdout=subprocess.PIPE,
    1325              stderr=subprocess.PIPE,
    1326          ) as proc:
    1327              proc.wait()
    1328              if expect_success and proc.returncode:
    1329                  self.fail("".join([*proc.stdout, *proc.stderr]))
    1330              stdout = proc.stdout.read()
    1331              stderr = proc.stderr.read()
    1332              # Clinic never writes to stderr.
    1333              self.assertEqual(stderr, "")
    1334              return stdout
    1335  
    1336      def expect_success(self, *args):
    1337          return self._do_test(*args)
    1338  
    1339      def expect_failure(self, *args):
    1340          return self._do_test(*args, expect_success=False)
    1341  
    1342      def test_external(self):
    1343          CLINIC_TEST = 'clinic.test.c'
    1344          source = support.findfile(CLINIC_TEST)
    1345          with open(source, 'r', encoding='utf-8') as f:
    1346              orig_contents = f.read()
    1347  
    1348          # Run clinic CLI and verify that it does not complain.
    1349          self.addCleanup(unlink, TESTFN)
    1350          out = self.expect_success("-f", "-o", TESTFN, source)
    1351          self.assertEqual(out, "")
    1352  
    1353          with open(TESTFN, 'r', encoding='utf-8') as f:
    1354              new_contents = f.read()
    1355  
    1356          self.assertEqual(new_contents, orig_contents)
    1357  
    1358      def test_no_change(self):
    1359          # bpo-42398: Test that the destination file is left unchanged if the
    1360          # content does not change. Moreover, check also that the file
    1361          # modification time does not change in this case.
    1362          code = dedent("""
    1363              /*[clinic input]
    1364              [clinic start generated code]*/
    1365              /*[clinic end generated code: output=da39a3ee5e6b4b0d input=da39a3ee5e6b4b0d]*/
    1366          """)
    1367          with os_helper.temp_dir() as tmp_dir:
    1368              fn = os.path.join(tmp_dir, "test.c")
    1369              with open(fn, "w", encoding="utf-8") as f:
    1370                  f.write(code)
    1371              pre_mtime = os.stat(fn).st_mtime_ns
    1372              self.expect_success(fn)
    1373              post_mtime = os.stat(fn).st_mtime_ns
    1374          # Don't change the file modification time
    1375          # if the content does not change
    1376          self.assertEqual(pre_mtime, post_mtime)
    1377  
    1378      def test_cli_force(self):
    1379          invalid_input = dedent("""
    1380              /*[clinic input]
    1381              output preset block
    1382              module test
    1383              test.fn
    1384                  a: int
    1385              [clinic start generated code]*/
    1386  
    1387              const char *hand_edited = "output block is overwritten";
    1388              /*[clinic end generated code: output=bogus input=bogus]*/
    1389          """)
    1390          fail_msg = dedent("""
    1391              Checksum mismatch!
    1392              Expected: bogus
    1393              Computed: 2ed19
    1394              Suggested fix: remove all generated code including the end marker,
    1395              or use the '-f' option.
    1396          """)
    1397          with os_helper.temp_dir() as tmp_dir:
    1398              fn = os.path.join(tmp_dir, "test.c")
    1399              with open(fn, "w", encoding="utf-8") as f:
    1400                  f.write(invalid_input)
    1401              # First, run the CLI without -f and expect failure.
    1402              # Note, we cannot check the entire fail msg, because the path to
    1403              # the tmp file will change for every run.
    1404              out = self.expect_failure(fn)
    1405              self.assertTrue(out.endswith(fail_msg))
    1406              # Then, force regeneration; success expected.
    1407              out = self.expect_success("-f", fn)
    1408              self.assertEqual(out, "")
    1409              # Verify by checking the checksum.
    1410              checksum = (
    1411                  "/*[clinic end generated code: "
    1412                  "output=6c2289b73f32bc19 input=9543a8d2da235301]*/\n"
    1413              )
    1414              with open(fn, 'r', encoding='utf-8') as f:
    1415                  generated = f.read()
    1416              self.assertTrue(generated.endswith(checksum))
    1417  
    1418      def test_cli_make(self):
    1419          c_code = dedent("""
    1420              /*[clinic input]
    1421              [clinic start generated code]*/
    1422          """)
    1423          py_code = "pass"
    1424          c_files = "file1.c", "file2.c"
    1425          py_files = "file1.py", "file2.py"
    1426  
    1427          def create_files(files, srcdir, code):
    1428              for fn in files:
    1429                  path = os.path.join(srcdir, fn)
    1430                  with open(path, "w", encoding="utf-8") as f:
    1431                      f.write(code)
    1432  
    1433          with os_helper.temp_dir() as tmp_dir:
    1434              # add some folders, some C files and a Python file
    1435              create_files(c_files, tmp_dir, c_code)
    1436              create_files(py_files, tmp_dir, py_code)
    1437  
    1438              # create C files in externals/ dir
    1439              ext_path = os.path.join(tmp_dir, "externals")
    1440              with os_helper.temp_dir(path=ext_path) as externals:
    1441                  create_files(c_files, externals, c_code)
    1442  
    1443                  # run clinic in verbose mode with --make on tmpdir
    1444                  out = self.expect_success("-v", "--make", "--srcdir", tmp_dir)
    1445  
    1446              # expect verbose mode to only mention the C files in tmp_dir
    1447              for filename in c_files:
    1448                  with self.subTest(filename=filename):
    1449                      path = os.path.join(tmp_dir, filename)
    1450                      self.assertIn(path, out)
    1451              for filename in py_files:
    1452                  with self.subTest(filename=filename):
    1453                      path = os.path.join(tmp_dir, filename)
    1454                      self.assertNotIn(path, out)
    1455              # don't expect C files from the externals dir
    1456              for filename in c_files:
    1457                  with self.subTest(filename=filename):
    1458                      path = os.path.join(ext_path, filename)
    1459                      self.assertNotIn(path, out)
    1460  
    1461      def test_cli_verbose(self):
    1462          with os_helper.temp_dir() as tmp_dir:
    1463              fn = os.path.join(tmp_dir, "test.c")
    1464              with open(fn, "w", encoding="utf-8") as f:
    1465                  f.write("")
    1466              out = self.expect_success("-v", fn)
    1467              self.assertEqual(out.strip(), fn)
    1468  
    1469      def test_cli_help(self):
    1470          out = self.expect_success("-h")
    1471          self.assertIn("usage: clinic.py", out)
    1472  
    1473      def test_cli_converters(self):
    1474          prelude = dedent("""
    1475              Legacy converters:
    1476                  B C D L O S U Y Z Z#
    1477                  b c d f h i l p s s# s* u u# w* y y# y* z z# z*
    1478  
    1479              Converters:
    1480          """)
    1481          expected_converters = (
    1482              "bool",
    1483              "byte",
    1484              "char",
    1485              "defining_class",
    1486              "double",
    1487              "fildes",
    1488              "float",
    1489              "int",
    1490              "long",
    1491              "long_long",
    1492              "object",
    1493              "Py_buffer",
    1494              "Py_complex",
    1495              "Py_ssize_t",
    1496              "Py_UNICODE",
    1497              "PyByteArrayObject",
    1498              "PyBytesObject",
    1499              "self",
    1500              "short",
    1501              "size_t",
    1502              "slice_index",
    1503              "str",
    1504              "unicode",
    1505              "unsigned_char",
    1506              "unsigned_int",
    1507              "unsigned_long",
    1508              "unsigned_long_long",
    1509              "unsigned_short",
    1510          )
    1511          finale = dedent("""
    1512              Return converters:
    1513                  bool()
    1514                  double()
    1515                  float()
    1516                  init()
    1517                  int()
    1518                  long()
    1519                  NoneType()
    1520                  Py_ssize_t()
    1521                  size_t()
    1522                  unsigned_int()
    1523                  unsigned_long()
    1524  
    1525              All converters also accept (c_default=None, py_default=None, annotation=None).
    1526              All return converters also accept (py_default=None).
    1527          """)
    1528          out = self.expect_success("--converters")
    1529          # We cannot simply compare the output, because the repr of the *accept*
    1530          # param may change (it's a set, thus unordered). So, let's compare the
    1531          # start and end of the expected output, and then assert that the
    1532          # converters appear lined up in alphabetical order.
    1533          self.assertTrue(out.startswith(prelude), out)
    1534          self.assertTrue(out.endswith(finale), out)
    1535  
    1536          out = out.removeprefix(prelude)
    1537          out = out.removesuffix(finale)
    1538          lines = out.split("\n")
    1539          for converter, line in zip(expected_converters, lines):
    1540              line = line.lstrip()
    1541              with self.subTest(converter=converter):
    1542                  self.assertTrue(
    1543                      line.startswith(converter),
    1544                      f"expected converter {converter!r}, got {line!r}"
    1545                  )
    1546  
    1547      def test_cli_fail_converters_and_filename(self):
    1548          out = self.expect_failure("--converters", "test.c")
    1549          msg = (
    1550              "Usage error: can't specify --converters "
    1551              "and a filename at the same time"
    1552          )
    1553          self.assertIn(msg, out)
    1554  
    1555      def test_cli_fail_no_filename(self):
    1556          out = self.expect_failure()
    1557          self.assertIn("usage: clinic.py", out)
    1558  
    1559      def test_cli_fail_output_and_multiple_files(self):
    1560          out = self.expect_failure("-o", "out.c", "input.c", "moreinput.c")
    1561          msg = "Usage error: can't use -o with multiple filenames"
    1562          self.assertIn(msg, out)
    1563  
    1564      def test_cli_fail_filename_or_output_and_make(self):
    1565          for opts in ("-o", "out.c"), ("filename.c",):
    1566              with self.subTest(opts=opts):
    1567                  out = self.expect_failure("--make", *opts)
    1568                  msg = "Usage error: can't use -o or filenames with --make"
    1569                  self.assertIn(msg, out)
    1570  
    1571      def test_cli_fail_make_without_srcdir(self):
    1572          out = self.expect_failure("--make", "--srcdir", "")
    1573          msg = "Usage error: --srcdir must not be empty with --make"
    1574          self.assertIn(msg, out)
    1575  
    1576  
    1577  try:
    1578      import _testclinic as ac_tester
    1579  except ImportError:
    1580      ac_tester = None
    1581  
    1582  @unittest.skipIf(ac_tester is None, "_testclinic is missing")
    1583  class ESC[4;38;5;81mClinicFunctionalTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
    1584      locals().update((name, getattr(ac_tester, name))
    1585                      for name in dir(ac_tester) if name.startswith('test_'))
    1586  
    1587      def test_objects_converter(self):
    1588          with self.assertRaises(TypeError):
    1589              ac_tester.objects_converter()
    1590          self.assertEqual(ac_tester.objects_converter(1, 2), (1, 2))
    1591          self.assertEqual(ac_tester.objects_converter([], 'whatever class'), ([], 'whatever class'))
    1592          self.assertEqual(ac_tester.objects_converter(1), (1, None))
    1593  
    1594      def test_bytes_object_converter(self):
    1595          with self.assertRaises(TypeError):
    1596              ac_tester.bytes_object_converter(1)
    1597          self.assertEqual(ac_tester.bytes_object_converter(b'BytesObject'), (b'BytesObject',))
    1598  
    1599      def test_byte_array_object_converter(self):
    1600          with self.assertRaises(TypeError):
    1601              ac_tester.byte_array_object_converter(1)
    1602          byte_arr = bytearray(b'ByteArrayObject')
    1603          self.assertEqual(ac_tester.byte_array_object_converter(byte_arr), (byte_arr,))
    1604  
    1605      def test_unicode_converter(self):
    1606          with self.assertRaises(TypeError):
    1607              ac_tester.unicode_converter(1)
    1608          self.assertEqual(ac_tester.unicode_converter('unicode'), ('unicode',))
    1609  
    1610      def test_bool_converter(self):
    1611          with self.assertRaises(TypeError):
    1612              ac_tester.bool_converter(False, False, 'not a int')
    1613          self.assertEqual(ac_tester.bool_converter(), (True, True, True))
    1614          self.assertEqual(ac_tester.bool_converter('', [], 5), (False, False, True))
    1615          self.assertEqual(ac_tester.bool_converter(('not empty',), {1: 2}, 0), (True, True, False))
    1616  
    1617      def test_char_converter(self):
    1618          with self.assertRaises(TypeError):
    1619              ac_tester.char_converter(1)
    1620          with self.assertRaises(TypeError):
    1621              ac_tester.char_converter(b'ab')
    1622          chars = [b'A', b'\a', b'\b', b'\t', b'\n', b'\v', b'\f', b'\r', b'"', b"'", b'?', b'\\', b'\000', b'\377']
    1623          expected = tuple(ord(c) for c in chars)
    1624          self.assertEqual(ac_tester.char_converter(), expected)
    1625          chars = [b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'0', b'a', b'b', b'c', b'd']
    1626          expected = tuple(ord(c) for c in chars)
    1627          self.assertEqual(ac_tester.char_converter(*chars), expected)
    1628  
    1629      def test_unsigned_char_converter(self):
    1630          from _testcapi import UCHAR_MAX
    1631          with self.assertRaises(OverflowError):
    1632              ac_tester.unsigned_char_converter(-1)
    1633          with self.assertRaises(OverflowError):
    1634              ac_tester.unsigned_char_converter(UCHAR_MAX + 1)
    1635          with self.assertRaises(OverflowError):
    1636              ac_tester.unsigned_char_converter(0, UCHAR_MAX + 1)
    1637          with self.assertRaises(TypeError):
    1638              ac_tester.unsigned_char_converter([])
    1639          self.assertEqual(ac_tester.unsigned_char_converter(), (12, 34, 56))
    1640          self.assertEqual(ac_tester.unsigned_char_converter(0, 0, UCHAR_MAX + 1), (0, 0, 0))
    1641          self.assertEqual(ac_tester.unsigned_char_converter(0, 0, (UCHAR_MAX + 1) * 3 + 123), (0, 0, 123))
    1642  
    1643      def test_short_converter(self):
    1644          from _testcapi import SHRT_MIN, SHRT_MAX
    1645          with self.assertRaises(OverflowError):
    1646              ac_tester.short_converter(SHRT_MIN - 1)
    1647          with self.assertRaises(OverflowError):
    1648              ac_tester.short_converter(SHRT_MAX + 1)
    1649          with self.assertRaises(TypeError):
    1650              ac_tester.short_converter([])
    1651          self.assertEqual(ac_tester.short_converter(-1234), (-1234,))
    1652          self.assertEqual(ac_tester.short_converter(4321), (4321,))
    1653  
    1654      def test_unsigned_short_converter(self):
    1655          from _testcapi import USHRT_MAX
    1656          with self.assertRaises(ValueError):
    1657              ac_tester.unsigned_short_converter(-1)
    1658          with self.assertRaises(OverflowError):
    1659              ac_tester.unsigned_short_converter(USHRT_MAX + 1)
    1660          with self.assertRaises(OverflowError):
    1661              ac_tester.unsigned_short_converter(0, USHRT_MAX + 1)
    1662          with self.assertRaises(TypeError):
    1663              ac_tester.unsigned_short_converter([])
    1664          self.assertEqual(ac_tester.unsigned_short_converter(), (12, 34, 56))
    1665          self.assertEqual(ac_tester.unsigned_short_converter(0, 0, USHRT_MAX + 1), (0, 0, 0))
    1666          self.assertEqual(ac_tester.unsigned_short_converter(0, 0, (USHRT_MAX + 1) * 3 + 123), (0, 0, 123))
    1667  
    1668      def test_int_converter(self):
    1669          from _testcapi import INT_MIN, INT_MAX
    1670          with self.assertRaises(OverflowError):
    1671              ac_tester.int_converter(INT_MIN - 1)
    1672          with self.assertRaises(OverflowError):
    1673              ac_tester.int_converter(INT_MAX + 1)
    1674          with self.assertRaises(TypeError):
    1675              ac_tester.int_converter(1, 2, 3)
    1676          with self.assertRaises(TypeError):
    1677              ac_tester.int_converter([])
    1678          self.assertEqual(ac_tester.int_converter(), (12, 34, 45))
    1679          self.assertEqual(ac_tester.int_converter(1, 2, '3'), (1, 2, ord('3')))
    1680  
    1681      def test_unsigned_int_converter(self):
    1682          from _testcapi import UINT_MAX
    1683          with self.assertRaises(ValueError):
    1684              ac_tester.unsigned_int_converter(-1)
    1685          with self.assertRaises(OverflowError):
    1686              ac_tester.unsigned_int_converter(UINT_MAX + 1)
    1687          with self.assertRaises(OverflowError):
    1688              ac_tester.unsigned_int_converter(0, UINT_MAX + 1)
    1689          with self.assertRaises(TypeError):
    1690              ac_tester.unsigned_int_converter([])
    1691          self.assertEqual(ac_tester.unsigned_int_converter(), (12, 34, 56))
    1692          self.assertEqual(ac_tester.unsigned_int_converter(0, 0, UINT_MAX + 1), (0, 0, 0))
    1693          self.assertEqual(ac_tester.unsigned_int_converter(0, 0, (UINT_MAX + 1) * 3 + 123), (0, 0, 123))
    1694  
    1695      def test_long_converter(self):
    1696          from _testcapi import LONG_MIN, LONG_MAX
    1697          with self.assertRaises(OverflowError):
    1698              ac_tester.long_converter(LONG_MIN - 1)
    1699          with self.assertRaises(OverflowError):
    1700              ac_tester.long_converter(LONG_MAX + 1)
    1701          with self.assertRaises(TypeError):
    1702              ac_tester.long_converter([])
    1703          self.assertEqual(ac_tester.long_converter(), (12,))
    1704          self.assertEqual(ac_tester.long_converter(-1234), (-1234,))
    1705  
    1706      def test_unsigned_long_converter(self):
    1707          from _testcapi import ULONG_MAX
    1708          with self.assertRaises(ValueError):
    1709              ac_tester.unsigned_long_converter(-1)
    1710          with self.assertRaises(OverflowError):
    1711              ac_tester.unsigned_long_converter(ULONG_MAX + 1)
    1712          with self.assertRaises(OverflowError):
    1713              ac_tester.unsigned_long_converter(0, ULONG_MAX + 1)
    1714          with self.assertRaises(TypeError):
    1715              ac_tester.unsigned_long_converter([])
    1716          self.assertEqual(ac_tester.unsigned_long_converter(), (12, 34, 56))
    1717          self.assertEqual(ac_tester.unsigned_long_converter(0, 0, ULONG_MAX + 1), (0, 0, 0))
    1718          self.assertEqual(ac_tester.unsigned_long_converter(0, 0, (ULONG_MAX + 1) * 3 + 123), (0, 0, 123))
    1719  
    1720      def test_long_long_converter(self):
    1721          from _testcapi import LLONG_MIN, LLONG_MAX
    1722          with self.assertRaises(OverflowError):
    1723              ac_tester.long_long_converter(LLONG_MIN - 1)
    1724          with self.assertRaises(OverflowError):
    1725              ac_tester.long_long_converter(LLONG_MAX + 1)
    1726          with self.assertRaises(TypeError):
    1727              ac_tester.long_long_converter([])
    1728          self.assertEqual(ac_tester.long_long_converter(), (12,))
    1729          self.assertEqual(ac_tester.long_long_converter(-1234), (-1234,))
    1730  
    1731      def test_unsigned_long_long_converter(self):
    1732          from _testcapi import ULLONG_MAX
    1733          with self.assertRaises(ValueError):
    1734              ac_tester.unsigned_long_long_converter(-1)
    1735          with self.assertRaises(OverflowError):
    1736              ac_tester.unsigned_long_long_converter(ULLONG_MAX + 1)
    1737          with self.assertRaises(OverflowError):
    1738              ac_tester.unsigned_long_long_converter(0, ULLONG_MAX + 1)
    1739          with self.assertRaises(TypeError):
    1740              ac_tester.unsigned_long_long_converter([])
    1741          self.assertEqual(ac_tester.unsigned_long_long_converter(), (12, 34, 56))
    1742          self.assertEqual(ac_tester.unsigned_long_long_converter(0, 0, ULLONG_MAX + 1), (0, 0, 0))
    1743          self.assertEqual(ac_tester.unsigned_long_long_converter(0, 0, (ULLONG_MAX + 1) * 3 + 123), (0, 0, 123))
    1744  
    1745      def test_py_ssize_t_converter(self):
    1746          from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX
    1747          with self.assertRaises(OverflowError):
    1748              ac_tester.py_ssize_t_converter(PY_SSIZE_T_MIN - 1)
    1749          with self.assertRaises(OverflowError):
    1750              ac_tester.py_ssize_t_converter(PY_SSIZE_T_MAX + 1)
    1751          with self.assertRaises(TypeError):
    1752              ac_tester.py_ssize_t_converter([])
    1753          self.assertEqual(ac_tester.py_ssize_t_converter(), (12, 34, 56))
    1754          self.assertEqual(ac_tester.py_ssize_t_converter(1, 2, None), (1, 2, 56))
    1755  
    1756      def test_slice_index_converter(self):
    1757          from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX
    1758          with self.assertRaises(TypeError):
    1759              ac_tester.slice_index_converter([])
    1760          self.assertEqual(ac_tester.slice_index_converter(), (12, 34, 56))
    1761          self.assertEqual(ac_tester.slice_index_converter(1, 2, None), (1, 2, 56))
    1762          self.assertEqual(ac_tester.slice_index_converter(PY_SSIZE_T_MAX, PY_SSIZE_T_MAX + 1, PY_SSIZE_T_MAX + 1234),
    1763                           (PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX))
    1764          self.assertEqual(ac_tester.slice_index_converter(PY_SSIZE_T_MIN, PY_SSIZE_T_MIN - 1, PY_SSIZE_T_MIN - 1234),
    1765                           (PY_SSIZE_T_MIN, PY_SSIZE_T_MIN, PY_SSIZE_T_MIN))
    1766  
    1767      def test_size_t_converter(self):
    1768          with self.assertRaises(ValueError):
    1769              ac_tester.size_t_converter(-1)
    1770          with self.assertRaises(TypeError):
    1771              ac_tester.size_t_converter([])
    1772          self.assertEqual(ac_tester.size_t_converter(), (12,))
    1773  
    1774      def test_float_converter(self):
    1775          with self.assertRaises(TypeError):
    1776              ac_tester.float_converter([])
    1777          self.assertEqual(ac_tester.float_converter(), (12.5,))
    1778          self.assertEqual(ac_tester.float_converter(-0.5), (-0.5,))
    1779  
    1780      def test_double_converter(self):
    1781          with self.assertRaises(TypeError):
    1782              ac_tester.double_converter([])
    1783          self.assertEqual(ac_tester.double_converter(), (12.5,))
    1784          self.assertEqual(ac_tester.double_converter(-0.5), (-0.5,))
    1785  
    1786      def test_py_complex_converter(self):
    1787          with self.assertRaises(TypeError):
    1788              ac_tester.py_complex_converter([])
    1789          self.assertEqual(ac_tester.py_complex_converter(complex(1, 2)), (complex(1, 2),))
    1790          self.assertEqual(ac_tester.py_complex_converter(complex('-1-2j')), (complex('-1-2j'),))
    1791          self.assertEqual(ac_tester.py_complex_converter(-0.5), (-0.5,))
    1792          self.assertEqual(ac_tester.py_complex_converter(10), (10,))
    1793  
    1794      def test_str_converter(self):
    1795          with self.assertRaises(TypeError):
    1796              ac_tester.str_converter(1)
    1797          with self.assertRaises(TypeError):
    1798              ac_tester.str_converter('a', 'b', 'c')
    1799          with self.assertRaises(ValueError):
    1800              ac_tester.str_converter('a', b'b\0b', 'c')
    1801          self.assertEqual(ac_tester.str_converter('a', b'b', 'c'), ('a', 'b', 'c'))
    1802          self.assertEqual(ac_tester.str_converter('a', b'b', b'c'), ('a', 'b', 'c'))
    1803          self.assertEqual(ac_tester.str_converter('a', b'b', 'c\0c'), ('a', 'b', 'c\0c'))
    1804  
    1805      def test_str_converter_encoding(self):
    1806          with self.assertRaises(TypeError):
    1807              ac_tester.str_converter_encoding(1)
    1808          self.assertEqual(ac_tester.str_converter_encoding('a', 'b', 'c'), ('a', 'b', 'c'))
    1809          with self.assertRaises(TypeError):
    1810              ac_tester.str_converter_encoding('a', b'b\0b', 'c')
    1811          self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c')])), ('a', 'b', 'c'))
    1812          self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c'), 0, ord('c')])),
    1813                           ('a', 'b', 'c\x00c'))
    1814          self.assertEqual(ac_tester.str_converter_encoding('a', b'b', b'c\x00c'), ('a', 'b', 'c\x00c'))
    1815  
    1816      def test_py_buffer_converter(self):
    1817          with self.assertRaises(TypeError):
    1818              ac_tester.py_buffer_converter('a', 'b')
    1819          self.assertEqual(ac_tester.py_buffer_converter('abc', bytearray([1, 2, 3])), (b'abc', b'\x01\x02\x03'))
    1820  
    1821      def test_keywords(self):
    1822          self.assertEqual(ac_tester.keywords(1, 2), (1, 2))
    1823          self.assertEqual(ac_tester.keywords(1, b=2), (1, 2))
    1824          self.assertEqual(ac_tester.keywords(a=1, b=2), (1, 2))
    1825  
    1826      def test_keywords_kwonly(self):
    1827          with self.assertRaises(TypeError):
    1828              ac_tester.keywords_kwonly(1, 2)
    1829          self.assertEqual(ac_tester.keywords_kwonly(1, b=2), (1, 2))
    1830          self.assertEqual(ac_tester.keywords_kwonly(a=1, b=2), (1, 2))
    1831  
    1832      def test_keywords_opt(self):
    1833          self.assertEqual(ac_tester.keywords_opt(1), (1, None, None))
    1834          self.assertEqual(ac_tester.keywords_opt(1, 2), (1, 2, None))
    1835          self.assertEqual(ac_tester.keywords_opt(1, 2, 3), (1, 2, 3))
    1836          self.assertEqual(ac_tester.keywords_opt(1, b=2), (1, 2, None))
    1837          self.assertEqual(ac_tester.keywords_opt(1, 2, c=3), (1, 2, 3))
    1838          self.assertEqual(ac_tester.keywords_opt(a=1, c=3), (1, None, 3))
    1839          self.assertEqual(ac_tester.keywords_opt(a=1, b=2, c=3), (1, 2, 3))
    1840  
    1841      def test_keywords_opt_kwonly(self):
    1842          self.assertEqual(ac_tester.keywords_opt_kwonly(1), (1, None, None, None))
    1843          self.assertEqual(ac_tester.keywords_opt_kwonly(1, 2), (1, 2, None, None))
    1844          with self.assertRaises(TypeError):
    1845              ac_tester.keywords_opt_kwonly(1, 2, 3)
    1846          self.assertEqual(ac_tester.keywords_opt_kwonly(1, b=2), (1, 2, None, None))
    1847          self.assertEqual(ac_tester.keywords_opt_kwonly(1, 2, c=3), (1, 2, 3, None))
    1848          self.assertEqual(ac_tester.keywords_opt_kwonly(a=1, c=3), (1, None, 3, None))
    1849          self.assertEqual(ac_tester.keywords_opt_kwonly(a=1, b=2, c=3, d=4), (1, 2, 3, 4))
    1850  
    1851      def test_keywords_kwonly_opt(self):
    1852          self.assertEqual(ac_tester.keywords_kwonly_opt(1), (1, None, None))
    1853          with self.assertRaises(TypeError):
    1854              ac_tester.keywords_kwonly_opt(1, 2)
    1855          self.assertEqual(ac_tester.keywords_kwonly_opt(1, b=2), (1, 2, None))
    1856          self.assertEqual(ac_tester.keywords_kwonly_opt(a=1, c=3), (1, None, 3))
    1857          self.assertEqual(ac_tester.keywords_kwonly_opt(a=1, b=2, c=3), (1, 2, 3))
    1858  
    1859      def test_posonly_keywords(self):
    1860          with self.assertRaises(TypeError):
    1861              ac_tester.posonly_keywords(1)
    1862          with self.assertRaises(TypeError):
    1863              ac_tester.posonly_keywords(a=1, b=2)
    1864          self.assertEqual(ac_tester.posonly_keywords(1, 2), (1, 2))
    1865          self.assertEqual(ac_tester.posonly_keywords(1, b=2), (1, 2))
    1866  
    1867      def test_posonly_kwonly(self):
    1868          with self.assertRaises(TypeError):
    1869              ac_tester.posonly_kwonly(1)
    1870          with self.assertRaises(TypeError):
    1871              ac_tester.posonly_kwonly(1, 2)
    1872          with self.assertRaises(TypeError):
    1873              ac_tester.posonly_kwonly(a=1, b=2)
    1874          self.assertEqual(ac_tester.posonly_kwonly(1, b=2), (1, 2))
    1875  
    1876      def test_posonly_keywords_kwonly(self):
    1877          with self.assertRaises(TypeError):
    1878              ac_tester.posonly_keywords_kwonly(1)
    1879          with self.assertRaises(TypeError):
    1880              ac_tester.posonly_keywords_kwonly(1, 2, 3)
    1881          with self.assertRaises(TypeError):
    1882              ac_tester.posonly_keywords_kwonly(a=1, b=2, c=3)
    1883          self.assertEqual(ac_tester.posonly_keywords_kwonly(1, 2, c=3), (1, 2, 3))
    1884          self.assertEqual(ac_tester.posonly_keywords_kwonly(1, b=2, c=3), (1, 2, 3))
    1885  
    1886      def test_posonly_keywords_opt(self):
    1887          with self.assertRaises(TypeError):
    1888              ac_tester.posonly_keywords_opt(1)
    1889          self.assertEqual(ac_tester.posonly_keywords_opt(1, 2), (1, 2, None, None))
    1890          self.assertEqual(ac_tester.posonly_keywords_opt(1, 2, 3), (1, 2, 3, None))
    1891          self.assertEqual(ac_tester.posonly_keywords_opt(1, 2, 3, 4), (1, 2, 3, 4))
    1892          self.assertEqual(ac_tester.posonly_keywords_opt(1, b=2), (1, 2, None, None))
    1893          self.assertEqual(ac_tester.posonly_keywords_opt(1, 2, c=3), (1, 2, 3, None))
    1894          with self.assertRaises(TypeError):
    1895              ac_tester.posonly_keywords_opt(a=1, b=2, c=3, d=4)
    1896          self.assertEqual(ac_tester.posonly_keywords_opt(1, b=2, c=3, d=4), (1, 2, 3, 4))
    1897  
    1898      def test_posonly_opt_keywords_opt(self):
    1899          self.assertEqual(ac_tester.posonly_opt_keywords_opt(1), (1, None, None, None))
    1900          self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2), (1, 2, None, None))
    1901          self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, 3), (1, 2, 3, None))
    1902          self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, 3, 4), (1, 2, 3, 4))
    1903          with self.assertRaises(TypeError):
    1904              ac_tester.posonly_opt_keywords_opt(1, b=2)
    1905          self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, c=3), (1, 2, 3, None))
    1906          self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, c=3, d=4), (1, 2, 3, 4))
    1907          with self.assertRaises(TypeError):
    1908              ac_tester.posonly_opt_keywords_opt(a=1, b=2, c=3, d=4)
    1909  
    1910      def test_posonly_kwonly_opt(self):
    1911          with self.assertRaises(TypeError):
    1912              ac_tester.posonly_kwonly_opt(1)
    1913          with self.assertRaises(TypeError):
    1914              ac_tester.posonly_kwonly_opt(1, 2)
    1915          self.assertEqual(ac_tester.posonly_kwonly_opt(1, b=2), (1, 2, None, None))
    1916          self.assertEqual(ac_tester.posonly_kwonly_opt(1, b=2, c=3), (1, 2, 3, None))
    1917          self.assertEqual(ac_tester.posonly_kwonly_opt(1, b=2, c=3, d=4), (1, 2, 3, 4))
    1918          with self.assertRaises(TypeError):
    1919              ac_tester.posonly_kwonly_opt(a=1, b=2, c=3, d=4)
    1920  
    1921      def test_posonly_opt_kwonly_opt(self):
    1922          self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1), (1, None, None, None))
    1923          self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1, 2), (1, 2, None, None))
    1924          with self.assertRaises(TypeError):
    1925              ac_tester.posonly_opt_kwonly_opt(1, 2, 3)
    1926          with self.assertRaises(TypeError):
    1927              ac_tester.posonly_opt_kwonly_opt(1, b=2)
    1928          self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None))
    1929          self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4))
    1930  
    1931      def test_posonly_keywords_kwonly_opt(self):
    1932          with self.assertRaises(TypeError):
    1933              ac_tester.posonly_keywords_kwonly_opt(1)
    1934          with self.assertRaises(TypeError):
    1935              ac_tester.posonly_keywords_kwonly_opt(1, 2)
    1936          with self.assertRaises(TypeError):
    1937              ac_tester.posonly_keywords_kwonly_opt(1, b=2)
    1938          with self.assertRaises(TypeError):
    1939              ac_tester.posonly_keywords_kwonly_opt(1, 2, 3)
    1940          with self.assertRaises(TypeError):
    1941              ac_tester.posonly_keywords_kwonly_opt(a=1, b=2, c=3)
    1942          self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None))
    1943          self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, b=2, c=3), (1, 2, 3, None, None))
    1944          self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4, None))
    1945          self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4, e=5), (1, 2, 3, 4, 5))
    1946  
    1947      def test_posonly_keywords_opt_kwonly_opt(self):
    1948          with self.assertRaises(TypeError):
    1949              ac_tester.posonly_keywords_opt_kwonly_opt(1)
    1950          self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None, None))
    1951          self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2), (1, 2, None, None, None))
    1952          with self.assertRaises(TypeError):
    1953              ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, 4)
    1954          with self.assertRaises(TypeError):
    1955              ac_tester.posonly_keywords_opt_kwonly_opt(a=1, b=2)
    1956          self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None))
    1957          self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2, c=3), (1, 2, 3, None, None))
    1958          self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4, None))
    1959          self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4, None))
    1960          self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4, e=5), (1, 2, 3, 4, 5))
    1961          self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4, e=5), (1, 2, 3, 4, 5))
    1962  
    1963      def test_posonly_opt_keywords_opt_kwonly_opt(self):
    1964          self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1), (1, None, None, None))
    1965          self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None))
    1966          with self.assertRaises(TypeError):
    1967              ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, b=2)
    1968          self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3), (1, 2, 3, None))
    1969          self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None))
    1970          self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4))
    1971          self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4))
    1972          with self.assertRaises(TypeError):
    1973              ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3, 4)
    1974  
    1975      def test_keyword_only_parameter(self):
    1976          with self.assertRaises(TypeError):
    1977              ac_tester.keyword_only_parameter()
    1978          with self.assertRaises(TypeError):
    1979              ac_tester.keyword_only_parameter(1)
    1980          self.assertEqual(ac_tester.keyword_only_parameter(a=1), (1,))
    1981  
    1982      def test_posonly_vararg(self):
    1983          with self.assertRaises(TypeError):
    1984              ac_tester.posonly_vararg()
    1985          self.assertEqual(ac_tester.posonly_vararg(1, 2), (1, 2, ()))
    1986          self.assertEqual(ac_tester.posonly_vararg(1, b=2), (1, 2, ()))
    1987          self.assertEqual(ac_tester.posonly_vararg(1, 2, 3, 4), (1, 2, (3, 4)))
    1988  
    1989      def test_vararg_and_posonly(self):
    1990          with self.assertRaises(TypeError):
    1991              ac_tester.vararg_and_posonly()
    1992          with self.assertRaises(TypeError):
    1993              ac_tester.vararg_and_posonly(1, b=2)
    1994          self.assertEqual(ac_tester.vararg_and_posonly(1, 2, 3, 4), (1, (2, 3, 4)))
    1995  
    1996      def test_vararg(self):
    1997          with self.assertRaises(TypeError):
    1998              ac_tester.vararg()
    1999          with self.assertRaises(TypeError):
    2000              ac_tester.vararg(1, b=2)
    2001          self.assertEqual(ac_tester.vararg(1, 2, 3, 4), (1, (2, 3, 4)))
    2002  
    2003      def test_vararg_with_default(self):
    2004          with self.assertRaises(TypeError):
    2005              ac_tester.vararg_with_default()
    2006          self.assertEqual(ac_tester.vararg_with_default(1, b=False), (1, (), False))
    2007          self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4), (1, (2, 3, 4), False))
    2008          self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4, b=True), (1, (2, 3, 4), True))
    2009  
    2010      def test_vararg_with_only_defaults(self):
    2011          self.assertEqual(ac_tester.vararg_with_only_defaults(), ((), None))
    2012          self.assertEqual(ac_tester.vararg_with_only_defaults(b=2), ((), 2))
    2013          self.assertEqual(ac_tester.vararg_with_only_defaults(1, b=2), ((1, ), 2))
    2014          self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4), ((1, 2, 3, 4), None))
    2015          self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4, b=5), ((1, 2, 3, 4), 5))
    2016  
    2017      def test_gh_32092_oob(self):
    2018          ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6)
    2019  
    2020      def test_gh_32092_kw_pass(self):
    2021          ac_tester.gh_32092_kw_pass(1, 2, 3)
    2022  
    2023      def test_gh_99233_refcount(self):
    2024          arg = '*A unique string is not referenced by anywhere else.*'
    2025          arg_refcount_origin = sys.getrefcount(arg)
    2026          ac_tester.gh_99233_refcount(arg)
    2027          arg_refcount_after = sys.getrefcount(arg)
    2028          self.assertEqual(arg_refcount_origin, arg_refcount_after)
    2029  
    2030      def test_gh_99240_double_free(self):
    2031          expected_error = r'gh_99240_double_free\(\) argument 2 must be encoded string without null bytes, not str'
    2032          with self.assertRaisesRegex(TypeError, expected_error):
    2033              ac_tester.gh_99240_double_free('a', '\0b')
    2034  
    2035  
    2036  class ESC[4;38;5;81mPermutationTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
    2037      """Test permutation support functions."""
    2038  
    2039      def test_permute_left_option_groups(self):
    2040          expected = (
    2041              (),
    2042              (3,),
    2043              (2, 3),
    2044              (1, 2, 3),
    2045          )
    2046          data = list(zip([1, 2, 3]))  # Generate a list of 1-tuples.
    2047          actual = tuple(clinic.permute_left_option_groups(data))
    2048          self.assertEqual(actual, expected)
    2049  
    2050      def test_permute_right_option_groups(self):
    2051          expected = (
    2052              (),
    2053              (1,),
    2054              (1, 2),
    2055              (1, 2, 3),
    2056          )
    2057          data = list(zip([1, 2, 3]))  # Generate a list of 1-tuples.
    2058          actual = tuple(clinic.permute_right_option_groups(data))
    2059          self.assertEqual(actual, expected)
    2060  
    2061      def test_permute_optional_groups(self):
    2062          empty = {
    2063              "left": (), "required": (), "right": (),
    2064              "expected": ((),),
    2065          }
    2066          noleft1 = {
    2067              "left": (), "required": ("b",), "right": ("c",),
    2068              "expected": (
    2069                  ("b",),
    2070                  ("b", "c"),
    2071              ),
    2072          }
    2073          noleft2 = {
    2074              "left": (), "required": ("b", "c",), "right": ("d",),
    2075              "expected": (
    2076                  ("b", "c"),
    2077                  ("b", "c", "d"),
    2078              ),
    2079          }
    2080          noleft3 = {
    2081              "left": (), "required": ("b", "c",), "right": ("d", "e"),
    2082              "expected": (
    2083                  ("b", "c"),
    2084                  ("b", "c", "d"),
    2085                  ("b", "c", "d", "e"),
    2086              ),
    2087          }
    2088          noright1 = {
    2089              "left": ("a",), "required": ("b",), "right": (),
    2090              "expected": (
    2091                  ("b",),
    2092                  ("a", "b"),
    2093              ),
    2094          }
    2095          noright2 = {
    2096              "left": ("a",), "required": ("b", "c"), "right": (),
    2097              "expected": (
    2098                  ("b", "c"),
    2099                  ("a", "b", "c"),
    2100              ),
    2101          }
    2102          noright3 = {
    2103              "left": ("a", "b"), "required": ("c",), "right": (),
    2104              "expected": (
    2105                  ("c",),
    2106                  ("b", "c"),
    2107                  ("a", "b", "c"),
    2108              ),
    2109          }
    2110          leftandright1 = {
    2111              "left": ("a",), "required": ("b",), "right": ("c",),
    2112              "expected": (
    2113                  ("b",),
    2114                  ("a", "b"),  # Prefer left.
    2115                  ("a", "b", "c"),
    2116              ),
    2117          }
    2118          leftandright2 = {
    2119              "left": ("a", "b"), "required": ("c", "d"), "right": ("e", "f"),
    2120              "expected": (
    2121                  ("c", "d"),
    2122                  ("b", "c", "d"),       # Prefer left.
    2123                  ("a", "b", "c", "d"),  # Prefer left.
    2124                  ("a", "b", "c", "d", "e"),
    2125                  ("a", "b", "c", "d", "e", "f"),
    2126              ),
    2127          }
    2128          dataset = (
    2129              empty,
    2130              noleft1, noleft2, noleft3,
    2131              noright1, noright2, noright3,
    2132              leftandright1, leftandright2,
    2133          )
    2134          for params in dataset:
    2135              with self.subTest(**params):
    2136                  left, required, right, expected = params.values()
    2137                  permutations = clinic.permute_optional_groups(left, required, right)
    2138                  actual = tuple(permutations)
    2139                  self.assertEqual(actual, expected)
    2140  
    2141  
    2142  if __name__ == "__main__":
    2143      unittest.main()