@@ -117,6 +117,7 @@ def __repr__(self):
117
117
118
118
119
119
class ClinicWholeFileTest (TestCase ):
120
+ maxDiff = None
120
121
121
122
def expect_failure (self , raw , errmsg , * , filename = None , lineno = None ):
122
123
_expect_failure (self , self .clinic .parse , raw , errmsg ,
@@ -426,6 +427,230 @@ def test_module_already_got_one(self):
426
427
"""
427
428
self .expect_failure (block , err , lineno = 3 )
428
429
430
+ def test_destination_already_got_one (self ):
431
+ err = "Destination already exists: 'test'"
432
+ block = """
433
+ /*[clinic input]
434
+ destination test new buffer
435
+ destination test new buffer
436
+ [clinic start generated code]*/
437
+ """
438
+ self .expect_failure (block , err , lineno = 3 )
439
+
440
+ def test_destination_does_not_exist (self ):
441
+ err = "Destination does not exist: '/dev/null'"
442
+ block = """
443
+ /*[clinic input]
444
+ output everything /dev/null
445
+ [clinic start generated code]*/
446
+ """
447
+ self .expect_failure (block , err , lineno = 2 )
448
+
449
+ def test_class_already_got_one (self ):
450
+ err = "Already defined class 'C'!"
451
+ block = """
452
+ /*[clinic input]
453
+ class C "" ""
454
+ class C "" ""
455
+ [clinic start generated code]*/
456
+ """
457
+ self .expect_failure (block , err , lineno = 3 )
458
+
459
+ def test_cant_nest_module_inside_class (self ):
460
+ err = "Can't nest a module inside a class!"
461
+ block = """
462
+ /*[clinic input]
463
+ class C "" ""
464
+ module C.m
465
+ [clinic start generated code]*/
466
+ """
467
+ self .expect_failure (block , err , lineno = 3 )
468
+
469
+ def test_dest_buffer_not_empty_at_eof (self ):
470
+ expected_warning = ("Destination buffer 'buffer' not empty at "
471
+ "end of file, emptying." )
472
+ expected_generated = dedent ("""
473
+ /*[clinic input]
474
+ output everything buffer
475
+ fn
476
+ a: object
477
+ /
478
+ [clinic start generated code]*/
479
+ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=1c4668687f5fd002]*/
480
+
481
+ /*[clinic input]
482
+ dump buffer
483
+ [clinic start generated code]*/
484
+
485
+ PyDoc_VAR(fn__doc__);
486
+
487
+ PyDoc_STRVAR(fn__doc__,
488
+ "fn($module, a, /)\\ n"
489
+ "--\\ n"
490
+ "\\ n");
491
+
492
+ #define FN_METHODDEF \\
493
+ {"fn", (PyCFunction)fn, METH_O, fn__doc__},
494
+
495
+ static PyObject *
496
+ fn(PyObject *module, PyObject *a)
497
+ /*[clinic end generated code: output=be6798b148ab4e53 input=524ce2e021e4eba6]*/
498
+ """ )
499
+ block = dedent ("""
500
+ /*[clinic input]
501
+ output everything buffer
502
+ fn
503
+ a: object
504
+ /
505
+ [clinic start generated code]*/
506
+ """ )
507
+ with support .captured_stdout () as stdout :
508
+ generated = self .clinic .parse (block )
509
+ self .assertIn (expected_warning , stdout .getvalue ())
510
+ self .assertEqual (generated , expected_generated )
511
+
512
+ def test_directive_set_misuse (self ):
513
+ err = "unknown variable 'ets'"
514
+ block = """
515
+ /*[clinic input]
516
+ set ets tse
517
+ [clinic start generated code]*/
518
+ """
519
+ self .expect_failure (block , err , lineno = 2 )
520
+
521
+ def test_directive_set_prefix (self ):
522
+ block = dedent ("""
523
+ /*[clinic input]
524
+ set line_prefix '// '
525
+ output everything suppress
526
+ output docstring_prototype buffer
527
+ fn
528
+ a: object
529
+ /
530
+ [clinic start generated code]*/
531
+ /* We need to dump the buffer.
532
+ * If not, Argument Clinic will emit a warning */
533
+ /*[clinic input]
534
+ dump buffer
535
+ [clinic start generated code]*/
536
+ """ )
537
+ generated = self .clinic .parse (block )
538
+ expected_docstring_prototype = "// PyDoc_VAR(fn__doc__);"
539
+ self .assertIn (expected_docstring_prototype , generated )
540
+
541
+ def test_directive_set_suffix (self ):
542
+ block = dedent ("""
543
+ /*[clinic input]
544
+ set line_suffix ' // test'
545
+ output everything suppress
546
+ output docstring_prototype buffer
547
+ fn
548
+ a: object
549
+ /
550
+ [clinic start generated code]*/
551
+ /* We need to dump the buffer.
552
+ * If not, Argument Clinic will emit a warning */
553
+ /*[clinic input]
554
+ dump buffer
555
+ [clinic start generated code]*/
556
+ """ )
557
+ generated = self .clinic .parse (block )
558
+ expected_docstring_prototype = "PyDoc_VAR(fn__doc__); // test"
559
+ self .assertIn (expected_docstring_prototype , generated )
560
+
561
+ def test_directive_set_prefix_and_suffix (self ):
562
+ block = dedent ("""
563
+ /*[clinic input]
564
+ set line_prefix '{block comment start} '
565
+ set line_suffix ' {block comment end}'
566
+ output everything suppress
567
+ output docstring_prototype buffer
568
+ fn
569
+ a: object
570
+ /
571
+ [clinic start generated code]*/
572
+ /* We need to dump the buffer.
573
+ * If not, Argument Clinic will emit a warning */
574
+ /*[clinic input]
575
+ dump buffer
576
+ [clinic start generated code]*/
577
+ """ )
578
+ generated = self .clinic .parse (block )
579
+ expected_docstring_prototype = "/* PyDoc_VAR(fn__doc__); */"
580
+ self .assertIn (expected_docstring_prototype , generated )
581
+
582
+ def test_directive_printout (self ):
583
+ block = dedent ("""
584
+ /*[clinic input]
585
+ output everything buffer
586
+ printout test
587
+ [clinic start generated code]*/
588
+ """ )
589
+ expected = dedent ("""
590
+ /*[clinic input]
591
+ output everything buffer
592
+ printout test
593
+ [clinic start generated code]*/
594
+ test
595
+ /*[clinic end generated code: output=4e1243bd22c66e76 input=898f1a32965d44ca]*/
596
+ """ )
597
+ generated = self .clinic .parse (block )
598
+ self .assertEqual (generated , expected )
599
+
600
+ def test_directive_preserve_twice (self ):
601
+ err = "Can't have preserve twice in one block!"
602
+ block = """
603
+ /*[clinic input]
604
+ preserve
605
+ preserve
606
+ [clinic start generated code]*/
607
+ """
608
+ self .expect_failure (block , err , lineno = 3 )
609
+
610
+ def test_directive_preserve_input (self ):
611
+ err = "'preserve' only works for blocks that don't produce any output!"
612
+ block = """
613
+ /*[clinic input]
614
+ preserve
615
+ fn
616
+ a: object
617
+ /
618
+ [clinic start generated code]*/
619
+ """
620
+ self .expect_failure (block , err , lineno = 6 )
621
+
622
+ def test_directive_preserve_output (self ):
623
+ err = "'preserve' only works for blocks that don't produce any output!"
624
+ block = dedent ("""
625
+ /*[clinic input]
626
+ output everything buffer
627
+ preserve
628
+ [clinic start generated code]*/
629
+ // Preserve this
630
+ /*[clinic end generated code: output=eaa49677ae4c1f7d input=559b5db18fddae6a]*/
631
+ /*[clinic input]
632
+ dump buffer
633
+ [clinic start generated code]*/
634
+ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/
635
+ """ )
636
+ generated = self .clinic .parse (block )
637
+ self .assertEqual (generated , block )
638
+
639
+ def test_directive_output_invalid_command (self ):
640
+ err = (
641
+ "Invalid command / destination name 'cmd', must be one of:\n "
642
+ " preset push pop print everything cpp_if docstring_prototype "
643
+ "docstring_definition methoddef_define impl_prototype "
644
+ "parser_prototype parser_definition cpp_endif methoddef_ifndef "
645
+ "impl_definition"
646
+ )
647
+ block = """
648
+ /*[clinic input]
649
+ output cmd buffer
650
+ [clinic start generated code]*/
651
+ """
652
+ self .expect_failure (block , err , lineno = 2 )
653
+
429
654
430
655
class ClinicGroupPermuterTest (TestCase ):
431
656
def _test (self , l , m , r , output ):
@@ -1496,6 +1721,16 @@ class Foo "" ""
1496
1721
"""
1497
1722
self .expect_failure (block , err , lineno = 3 )
1498
1723
1724
+ def test_duplicate_coexist (self ):
1725
+ err = "Called @coexist twice"
1726
+ block = """
1727
+ module m
1728
+ @coexist
1729
+ @coexist
1730
+ m.fn
1731
+ """
1732
+ self .expect_failure (block , err , lineno = 2 )
1733
+
1499
1734
def test_unused_param (self ):
1500
1735
block = self .parse ("""
1501
1736
module foo
@@ -1931,6 +2166,67 @@ def test_cli_fail_make_without_srcdir(self):
1931
2166
msg = "error: --srcdir must not be empty with --make"
1932
2167
self .assertIn (msg , err )
1933
2168
2169
+ def test_file_dest (self ):
2170
+ block = dedent ("""
2171
+ /*[clinic input]
2172
+ destination test new file {path}.h
2173
+ output everything test
2174
+ func
2175
+ a: object
2176
+ /
2177
+ [clinic start generated code]*/
2178
+ """ )
2179
+ expected_checksum_line = (
2180
+ "/*[clinic end generated code: "
2181
+ "output=da39a3ee5e6b4b0d input=b602ab8e173ac3bd]*/\n "
2182
+ )
2183
+ expected_output = dedent ("""\
2184
+ /*[clinic input]
2185
+ preserve
2186
+ [clinic start generated code]*/
2187
+
2188
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
2189
+ # include "pycore_gc.h" // PyGC_Head
2190
+ # include "pycore_runtime.h" // _Py_ID()
2191
+ #endif
2192
+
2193
+
2194
+ PyDoc_VAR(func__doc__);
2195
+
2196
+ PyDoc_STRVAR(func__doc__,
2197
+ "func($module, a, /)\\ n"
2198
+ "--\\ n"
2199
+ "\\ n");
2200
+
2201
+ #define FUNC_METHODDEF \\
2202
+ {"func", (PyCFunction)func, METH_O, func__doc__},
2203
+
2204
+ static PyObject *
2205
+ func(PyObject *module, PyObject *a)
2206
+ /*[clinic end generated code: output=56c09670e89a0d9a input=a9049054013a1b77]*/
2207
+ """ )
2208
+ with os_helper .temp_dir () as tmp_dir :
2209
+ in_fn = os .path .join (tmp_dir , "test.c" )
2210
+ out_fn = os .path .join (tmp_dir , "test.c.h" )
2211
+ with open (in_fn , "w" , encoding = "utf-8" ) as f :
2212
+ f .write (block )
2213
+ with open (out_fn , "w" , encoding = "utf-8" ) as f :
2214
+ f .write ("" ) # Write an empty output file!
2215
+ # Clinic should complain about the empty output file.
2216
+ _ , err = self .expect_failure (in_fn )
2217
+ expected_err = (f"Modified destination file { out_fn !r} , "
2218
+ "not overwriting!" )
2219
+ self .assertIn (expected_err , err )
2220
+ # Run clinic again, this time with the -f option.
2221
+ out = self .expect_success ("-f" , in_fn )
2222
+ # Read back the generated output.
2223
+ with open (in_fn , encoding = "utf-8" ) as f :
2224
+ data = f .read ()
2225
+ expected_block = f"{ block } { expected_checksum_line } "
2226
+ self .assertEqual (data , expected_block )
2227
+ with open (out_fn , encoding = "utf-8" ) as f :
2228
+ data = f .read ()
2229
+ self .assertEqual (data , expected_output )
1934
2230
1935
2231
try :
1936
2232
import _testclinic as ac_tester
0 commit comments