@@ -117,6 +117,7 @@ def __repr__(self):
117117
118118
119119class ClinicWholeFileTest (TestCase ):
120+ maxDiff = None
120121
121122 def expect_failure (self , raw , errmsg , * , filename = None , lineno = None ):
122123 _expect_failure (self , self .clinic .parse , raw , errmsg ,
@@ -426,6 +427,230 @@ def test_module_already_got_one(self):
426427 """
427428 self .expect_failure (block , err , lineno = 3 )
428429
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+
429654
430655class ClinicGroupPermuterTest (TestCase ):
431656 def _test (self , l , m , r , output ):
@@ -1496,6 +1721,16 @@ class Foo "" ""
14961721 """
14971722 self .expect_failure (block , err , lineno = 3 )
14981723
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+
14991734 def test_unused_param (self ):
15001735 block = self .parse ("""
15011736 module foo
@@ -1931,6 +2166,67 @@ def test_cli_fail_make_without_srcdir(self):
19312166 msg = "error: --srcdir must not be empty with --make"
19322167 self .assertIn (msg , err )
19332168
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 )
19342230
19352231try :
19362232 import _testclinic as ac_tester
0 commit comments