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()