ยปCore Development>Code coverage>Tools/clinic/clinic_test.py

Python code coverage for Tools/clinic/clinic_test.py

#countcontent
1n/a# Argument Clinic
2n/a# Copyright 2012-2013 by Larry Hastings.
3n/a# Licensed to the PSF under a contributor agreement.
4n/a#
5n/a
6n/aimport clinic
7n/afrom clinic import DSLParser
8n/aimport collections
9n/aimport inspect
10n/afrom test import support
11n/aimport sys
12n/aimport unittest
13n/afrom unittest import TestCase
14n/a
15n/a
16n/aclass FakeConverter:
17n/a def __init__(self, name, args):
18n/a self.name = name
19n/a self.args = args
20n/a
21n/a
22n/aclass FakeConverterFactory:
23n/a def __init__(self, name):
24n/a self.name = name
25n/a
26n/a def __call__(self, name, default, **kwargs):
27n/a return FakeConverter(self.name, kwargs)
28n/a
29n/a
30n/aclass FakeConvertersDict:
31n/a def __init__(self):
32n/a self.used_converters = {}
33n/a
34n/a def get(self, name, default):
35n/a return self.used_converters.setdefault(name, FakeConverterFactory(name))
36n/a
37n/aclinic.Clinic.presets_text = ''
38n/ac = clinic.Clinic(language='C')
39n/a
40n/aclass FakeClinic:
41n/a def __init__(self):
42n/a self.converters = FakeConvertersDict()
43n/a self.legacy_converters = FakeConvertersDict()
44n/a self.language = clinic.CLanguage(None)
45n/a self.filename = None
46n/a self.block_parser = clinic.BlockParser('', self.language)
47n/a self.modules = collections.OrderedDict()
48n/a self.classes = collections.OrderedDict()
49n/a clinic.clinic = self
50n/a self.name = "FakeClinic"
51n/a self.line_prefix = self.line_suffix = ''
52n/a self.destinations = {}
53n/a self.add_destination("block", "buffer")
54n/a self.add_destination("file", "buffer")
55n/a self.add_destination("suppress", "suppress")
56n/a d = self.destinations.get
57n/a self.field_destinations = collections.OrderedDict((
58n/a ('docstring_prototype', d('suppress')),
59n/a ('docstring_definition', d('block')),
60n/a ('methoddef_define', d('block')),
61n/a ('impl_prototype', d('block')),
62n/a ('parser_prototype', d('suppress')),
63n/a ('parser_definition', d('block')),
64n/a ('impl_definition', d('block')),
65n/a ))
66n/a
67n/a def get_destination(self, name):
68n/a d = self.destinations.get(name)
69n/a if not d:
70n/a sys.exit("Destination does not exist: " + repr(name))
71n/a return d
72n/a
73n/a def add_destination(self, name, type, *args):
74n/a if name in self.destinations:
75n/a sys.exit("Destination already exists: " + repr(name))
76n/a self.destinations[name] = clinic.Destination(name, type, self, *args)
77n/a
78n/a def is_directive(self, name):
79n/a return name == "module"
80n/a
81n/a def directive(self, name, args):
82n/a self.called_directives[name] = args
83n/a
84n/a _module_and_class = clinic.Clinic._module_and_class
85n/a
86n/aclass ClinicWholeFileTest(TestCase):
87n/a def test_eol(self):
88n/a # regression test:
89n/a # clinic's block parser didn't recognize
90n/a # the "end line" for the block if it
91n/a # didn't end in "\n" (as in, the last)
92n/a # byte of the file was '/'.
93n/a # so it would spit out an end line for you.
94n/a # and since you really already had one,
95n/a # the last line of the block got corrupted.
96n/a c = clinic.Clinic(clinic.CLanguage(None))
97n/a raw = "/*[clinic]\nfoo\n[clinic]*/"
98n/a cooked = c.parse(raw).splitlines()
99n/a end_line = cooked[2].rstrip()
100n/a # this test is redundant, it's just here explicitly to catch
101n/a # the regression test so we don't forget what it looked like
102n/a self.assertNotEqual(end_line, "[clinic]*/[clinic]*/")
103n/a self.assertEqual(end_line, "[clinic]*/")
104n/a
105n/a
106n/a
107n/aclass ClinicGroupPermuterTest(TestCase):
108n/a def _test(self, l, m, r, output):
109n/a computed = clinic.permute_optional_groups(l, m, r)
110n/a self.assertEqual(output, computed)
111n/a
112n/a def test_range(self):
113n/a self._test([['start']], ['stop'], [['step']],
114n/a (
115n/a ('stop',),
116n/a ('start', 'stop',),
117n/a ('start', 'stop', 'step',),
118n/a ))
119n/a
120n/a def test_add_window(self):
121n/a self._test([['x', 'y']], ['ch'], [['attr']],
122n/a (
123n/a ('ch',),
124n/a ('ch', 'attr'),
125n/a ('x', 'y', 'ch',),
126n/a ('x', 'y', 'ch', 'attr'),
127n/a ))
128n/a
129n/a def test_ludicrous(self):
130n/a self._test([['a1', 'a2', 'a3'], ['b1', 'b2']], ['c1'], [['d1', 'd2'], ['e1', 'e2', 'e3']],
131n/a (
132n/a ('c1',),
133n/a ('b1', 'b2', 'c1'),
134n/a ('b1', 'b2', 'c1', 'd1', 'd2'),
135n/a ('a1', 'a2', 'a3', 'b1', 'b2', 'c1'),
136n/a ('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2'),
137n/a ('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2', 'e1', 'e2', 'e3'),
138n/a ))
139n/a
140n/a def test_right_only(self):
141n/a self._test([], [], [['a'],['b'],['c']],
142n/a (
143n/a (),
144n/a ('a',),
145n/a ('a', 'b'),
146n/a ('a', 'b', 'c')
147n/a ))
148n/a
149n/a def test_have_left_options_but_required_is_empty(self):
150n/a def fn():
151n/a clinic.permute_optional_groups(['a'], [], [])
152n/a self.assertRaises(AssertionError, fn)
153n/a
154n/a
155n/aclass ClinicLinearFormatTest(TestCase):
156n/a def _test(self, input, output, **kwargs):
157n/a computed = clinic.linear_format(input, **kwargs)
158n/a self.assertEqual(output, computed)
159n/a
160n/a def test_empty_strings(self):
161n/a self._test('', '')
162n/a
163n/a def test_solo_newline(self):
164n/a self._test('\n', '\n')
165n/a
166n/a def test_no_substitution(self):
167n/a self._test("""
168n/a abc
169n/a """, """
170n/a abc
171n/a """)
172n/a
173n/a def test_empty_substitution(self):
174n/a self._test("""
175n/a abc
176n/a {name}
177n/a def
178n/a """, """
179n/a abc
180n/a def
181n/a """, name='')
182n/a
183n/a def test_single_line_substitution(self):
184n/a self._test("""
185n/a abc
186n/a {name}
187n/a def
188n/a """, """
189n/a abc
190n/a GARGLE
191n/a def
192n/a """, name='GARGLE')
193n/a
194n/a def test_multiline_substitution(self):
195n/a self._test("""
196n/a abc
197n/a {name}
198n/a def
199n/a """, """
200n/a abc
201n/a bingle
202n/a bungle
203n/a
204n/a def
205n/a """, name='bingle\nbungle\n')
206n/a
207n/aclass InertParser:
208n/a def __init__(self, clinic):
209n/a pass
210n/a
211n/a def parse(self, block):
212n/a pass
213n/a
214n/aclass CopyParser:
215n/a def __init__(self, clinic):
216n/a pass
217n/a
218n/a def parse(self, block):
219n/a block.output = block.input
220n/a
221n/a
222n/aclass ClinicBlockParserTest(TestCase):
223n/a def _test(self, input, output):
224n/a language = clinic.CLanguage(None)
225n/a
226n/a blocks = list(clinic.BlockParser(input, language))
227n/a writer = clinic.BlockPrinter(language)
228n/a for block in blocks:
229n/a writer.print_block(block)
230n/a output = writer.f.getvalue()
231n/a assert output == input, "output != input!\n\noutput " + repr(output) + "\n\n input " + repr(input)
232n/a
233n/a def round_trip(self, input):
234n/a return self._test(input, input)
235n/a
236n/a def test_round_trip_1(self):
237n/a self.round_trip("""
238n/a verbatim text here
239n/a lah dee dah
240n/a""")
241n/a def test_round_trip_2(self):
242n/a self.round_trip("""
243n/a verbatim text here
244n/a lah dee dah
245n/a/*[inert]
246n/aabc
247n/a[inert]*/
248n/adef
249n/a/*[inert checksum: 7b18d017f89f61cf17d47f92749ea6930a3f1deb]*/
250n/axyz
251n/a""")
252n/a
253n/a def _test_clinic(self, input, output):
254n/a language = clinic.CLanguage(None)
255n/a c = clinic.Clinic(language)
256n/a c.parsers['inert'] = InertParser(c)
257n/a c.parsers['copy'] = CopyParser(c)
258n/a computed = c.parse(input)
259n/a self.assertEqual(output, computed)
260n/a
261n/a def test_clinic_1(self):
262n/a self._test_clinic("""
263n/a verbatim text here
264n/a lah dee dah
265n/a/*[copy input]
266n/adef
267n/a[copy start generated code]*/
268n/aabc
269n/a/*[copy end generated code: output=03cfd743661f0797 input=7b18d017f89f61cf]*/
270n/axyz
271n/a""", """
272n/a verbatim text here
273n/a lah dee dah
274n/a/*[copy input]
275n/adef
276n/a[copy start generated code]*/
277n/adef
278n/a/*[copy end generated code: output=7b18d017f89f61cf input=7b18d017f89f61cf]*/
279n/axyz
280n/a""")
281n/a
282n/a
283n/aclass ClinicParserTest(TestCase):
284n/a def test_trivial(self):
285n/a parser = DSLParser(FakeClinic())
286n/a block = clinic.Block("module os\nos.access")
287n/a parser.parse(block)
288n/a module, function = block.signatures
289n/a self.assertEqual("access", function.name)
290n/a self.assertEqual("os", module.name)
291n/a
292n/a def test_ignore_line(self):
293n/a block = self.parse("#\nmodule os\nos.access")
294n/a module, function = block.signatures
295n/a self.assertEqual("access", function.name)
296n/a self.assertEqual("os", module.name)
297n/a
298n/a def test_param(self):
299n/a function = self.parse_function("module os\nos.access\n path: int")
300n/a self.assertEqual("access", function.name)
301n/a self.assertEqual(2, len(function.parameters))
302n/a p = function.parameters['path']
303n/a self.assertEqual('path', p.name)
304n/a self.assertIsInstance(p.converter, clinic.int_converter)
305n/a
306n/a def test_param_default(self):
307n/a function = self.parse_function("module os\nos.access\n follow_symlinks: bool = True")
308n/a p = function.parameters['follow_symlinks']
309n/a self.assertEqual(True, p.default)
310n/a
311n/a def test_param_with_continuations(self):
312n/a function = self.parse_function("module os\nos.access\n follow_symlinks: \\\n bool \\\n =\\\n True")
313n/a p = function.parameters['follow_symlinks']
314n/a self.assertEqual(True, p.default)
315n/a
316n/a def test_param_default_expression(self):
317n/a function = self.parse_function("module os\nos.access\n follow_symlinks: int(c_default='MAXSIZE') = sys.maxsize")
318n/a p = function.parameters['follow_symlinks']
319n/a self.assertEqual(sys.maxsize, p.default)
320n/a self.assertEqual("MAXSIZE", p.converter.c_default)
321n/a
322n/a s = self.parse_function_should_fail("module os\nos.access\n follow_symlinks: int = sys.maxsize")
323n/a self.assertEqual(s, "Error on line 0:\nWhen you specify a named constant ('sys.maxsize') as your default value,\nyou MUST specify a valid c_default.\n")
324n/a
325n/a def test_param_no_docstring(self):
326n/a function = self.parse_function("""
327n/amodule os
328n/aos.access
329n/a follow_symlinks: bool = True
330n/a something_else: str = ''""")
331n/a p = function.parameters['follow_symlinks']
332n/a self.assertEqual(3, len(function.parameters))
333n/a self.assertIsInstance(function.parameters['something_else'].converter, clinic.str_converter)
334n/a
335n/a def test_param_default_parameters_out_of_order(self):
336n/a s = self.parse_function_should_fail("""
337n/amodule os
338n/aos.access
339n/a follow_symlinks: bool = True
340n/a something_else: str""")
341n/a self.assertEqual(s, """Error on line 0:
342n/aCan't have a parameter without a default ('something_else')
343n/aafter a parameter with a default!
344n/a""")
345n/a
346n/a def disabled_test_converter_arguments(self):
347n/a function = self.parse_function("module os\nos.access\n path: path_t(allow_fd=1)")
348n/a p = function.parameters['path']
349n/a self.assertEqual(1, p.converter.args['allow_fd'])
350n/a
351n/a def test_function_docstring(self):
352n/a function = self.parse_function("""
353n/amodule os
354n/aos.stat as os_stat_fn
355n/a
356n/a path: str
357n/a Path to be examined
358n/a
359n/aPerform a stat system call on the given path.""")
360n/a self.assertEqual("""
361n/astat($module, /, path)
362n/a--
363n/a
364n/aPerform a stat system call on the given path.
365n/a
366n/a path
367n/a Path to be examined
368n/a""".strip(), function.docstring)
369n/a
370n/a def test_explicit_parameters_in_docstring(self):
371n/a function = self.parse_function("""
372n/amodule foo
373n/afoo.bar
374n/a x: int
375n/a Documentation for x.
376n/a y: int
377n/a
378n/aThis is the documentation for foo.
379n/a
380n/aOkay, we're done here.
381n/a""")
382n/a self.assertEqual("""
383n/abar($module, /, x, y)
384n/a--
385n/a
386n/aThis is the documentation for foo.
387n/a
388n/a x
389n/a Documentation for x.
390n/a
391n/aOkay, we're done here.
392n/a""".strip(), function.docstring)
393n/a
394n/a def test_parser_regression_special_character_in_parameter_column_of_docstring_first_line(self):
395n/a function = self.parse_function("""
396n/amodule os
397n/aos.stat
398n/a path: str
399n/aThis/used to break Clinic!
400n/a""")
401n/a self.assertEqual("stat($module, /, path)\n--\n\nThis/used to break Clinic!", function.docstring)
402n/a
403n/a def test_c_name(self):
404n/a function = self.parse_function("module os\nos.stat as os_stat_fn")
405n/a self.assertEqual("os_stat_fn", function.c_basename)
406n/a
407n/a def test_return_converter(self):
408n/a function = self.parse_function("module os\nos.stat -> int")
409n/a self.assertIsInstance(function.return_converter, clinic.int_return_converter)
410n/a
411n/a def test_star(self):
412n/a function = self.parse_function("module os\nos.access\n *\n follow_symlinks: bool = True")
413n/a p = function.parameters['follow_symlinks']
414n/a self.assertEqual(inspect.Parameter.KEYWORD_ONLY, p.kind)
415n/a self.assertEqual(0, p.group)
416n/a
417n/a def test_group(self):
418n/a function = self.parse_function("module window\nwindow.border\n [\n ls : int\n ]\n /\n")
419n/a p = function.parameters['ls']
420n/a self.assertEqual(1, p.group)
421n/a
422n/a def test_left_group(self):
423n/a function = self.parse_function("""
424n/amodule curses
425n/acurses.addch
426n/a [
427n/a y: int
428n/a Y-coordinate.
429n/a x: int
430n/a X-coordinate.
431n/a ]
432n/a ch: char
433n/a Character to add.
434n/a [
435n/a attr: long
436n/a Attributes for the character.
437n/a ]
438n/a /
439n/a""")
440n/a for name, group in (
441n/a ('y', -1), ('x', -1),
442n/a ('ch', 0),
443n/a ('attr', 1),
444n/a ):
445n/a p = function.parameters[name]
446n/a self.assertEqual(p.group, group)
447n/a self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
448n/a self.assertEqual(function.docstring.strip(), """
449n/aaddch([y, x,] ch, [attr])
450n/a
451n/a
452n/a y
453n/a Y-coordinate.
454n/a x
455n/a X-coordinate.
456n/a ch
457n/a Character to add.
458n/a attr
459n/a Attributes for the character.
460n/a """.strip())
461n/a
462n/a def test_nested_groups(self):
463n/a function = self.parse_function("""
464n/amodule curses
465n/acurses.imaginary
466n/a [
467n/a [
468n/a y1: int
469n/a Y-coordinate.
470n/a y2: int
471n/a Y-coordinate.
472n/a ]
473n/a x1: int
474n/a X-coordinate.
475n/a x2: int
476n/a X-coordinate.
477n/a ]
478n/a ch: char
479n/a Character to add.
480n/a [
481n/a attr1: long
482n/a Attributes for the character.
483n/a attr2: long
484n/a Attributes for the character.
485n/a attr3: long
486n/a Attributes for the character.
487n/a [
488n/a attr4: long
489n/a Attributes for the character.
490n/a attr5: long
491n/a Attributes for the character.
492n/a attr6: long
493n/a Attributes for the character.
494n/a ]
495n/a ]
496n/a /
497n/a""")
498n/a for name, group in (
499n/a ('y1', -2), ('y2', -2),
500n/a ('x1', -1), ('x2', -1),
501n/a ('ch', 0),
502n/a ('attr1', 1), ('attr2', 1), ('attr3', 1),
503n/a ('attr4', 2), ('attr5', 2), ('attr6', 2),
504n/a ):
505n/a p = function.parameters[name]
506n/a self.assertEqual(p.group, group)
507n/a self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
508n/a
509n/a self.assertEqual(function.docstring.strip(), """
510n/aimaginary([[y1, y2,] x1, x2,] ch, [attr1, attr2, attr3, [attr4, attr5,
511n/a attr6]])
512n/a
513n/a
514n/a y1
515n/a Y-coordinate.
516n/a y2
517n/a Y-coordinate.
518n/a x1
519n/a X-coordinate.
520n/a x2
521n/a X-coordinate.
522n/a ch
523n/a Character to add.
524n/a attr1
525n/a Attributes for the character.
526n/a attr2
527n/a Attributes for the character.
528n/a attr3
529n/a Attributes for the character.
530n/a attr4
531n/a Attributes for the character.
532n/a attr5
533n/a Attributes for the character.
534n/a attr6
535n/a Attributes for the character.
536n/a """.strip())
537n/a
538n/a def parse_function_should_fail(self, s):
539n/a with support.captured_stdout() as stdout:
540n/a with self.assertRaises(SystemExit):
541n/a self.parse_function(s)
542n/a return stdout.getvalue()
543n/a
544n/a def test_disallowed_grouping__two_top_groups_on_left(self):
545n/a s = self.parse_function_should_fail("""
546n/amodule foo
547n/afoo.two_top_groups_on_left
548n/a [
549n/a group1 : int
550n/a ]
551n/a [
552n/a group2 : int
553n/a ]
554n/a param: int
555n/a """)
556n/a self.assertEqual(s,
557n/a ('Error on line 0:\n'
558n/a 'Function two_top_groups_on_left has an unsupported group configuration. (Unexpected state 2.b)\n'))
559n/a
560n/a def test_disallowed_grouping__two_top_groups_on_right(self):
561n/a self.parse_function_should_fail("""
562n/amodule foo
563n/afoo.two_top_groups_on_right
564n/a param: int
565n/a [
566n/a group1 : int
567n/a ]
568n/a [
569n/a group2 : int
570n/a ]
571n/a """)
572n/a
573n/a def test_disallowed_grouping__parameter_after_group_on_right(self):
574n/a self.parse_function_should_fail("""
575n/amodule foo
576n/afoo.parameter_after_group_on_right
577n/a param: int
578n/a [
579n/a [
580n/a group1 : int
581n/a ]
582n/a group2 : int
583n/a ]
584n/a """)
585n/a
586n/a def test_disallowed_grouping__group_after_parameter_on_left(self):
587n/a self.parse_function_should_fail("""
588n/amodule foo
589n/afoo.group_after_parameter_on_left
590n/a [
591n/a group2 : int
592n/a [
593n/a group1 : int
594n/a ]
595n/a ]
596n/a param: int
597n/a """)
598n/a
599n/a def test_disallowed_grouping__empty_group_on_left(self):
600n/a self.parse_function_should_fail("""
601n/amodule foo
602n/afoo.empty_group
603n/a [
604n/a [
605n/a ]
606n/a group2 : int
607n/a ]
608n/a param: int
609n/a """)
610n/a
611n/a def test_disallowed_grouping__empty_group_on_right(self):
612n/a self.parse_function_should_fail("""
613n/amodule foo
614n/afoo.empty_group
615n/a param: int
616n/a [
617n/a [
618n/a ]
619n/a group2 : int
620n/a ]
621n/a """)
622n/a
623n/a def test_no_parameters(self):
624n/a function = self.parse_function("""
625n/amodule foo
626n/afoo.bar
627n/a
628n/aDocstring
629n/a
630n/a""")
631n/a self.assertEqual("bar($module, /)\n--\n\nDocstring", function.docstring)
632n/a self.assertEqual(1, len(function.parameters)) # self!
633n/a
634n/a def test_init_with_no_parameters(self):
635n/a function = self.parse_function("""
636n/amodule foo
637n/aclass foo.Bar "unused" "notneeded"
638n/afoo.Bar.__init__
639n/a
640n/aDocstring
641n/a
642n/a""", signatures_in_block=3, function_index=2)
643n/a # self is not in the signature
644n/a self.assertEqual("Bar()\n--\n\nDocstring", function.docstring)
645n/a # but it *is* a parameter
646n/a self.assertEqual(1, len(function.parameters))
647n/a
648n/a def test_illegal_module_line(self):
649n/a self.parse_function_should_fail("""
650n/amodule foo
651n/afoo.bar => int
652n/a /
653n/a""")
654n/a
655n/a def test_illegal_c_basename(self):
656n/a self.parse_function_should_fail("""
657n/amodule foo
658n/afoo.bar as 935
659n/a /
660n/a""")
661n/a
662n/a def test_single_star(self):
663n/a self.parse_function_should_fail("""
664n/amodule foo
665n/afoo.bar
666n/a *
667n/a *
668n/a""")
669n/a
670n/a def test_parameters_required_after_star_without_initial_parameters_or_docstring(self):
671n/a self.parse_function_should_fail("""
672n/amodule foo
673n/afoo.bar
674n/a *
675n/a""")
676n/a
677n/a def test_parameters_required_after_star_without_initial_parameters_with_docstring(self):
678n/a self.parse_function_should_fail("""
679n/amodule foo
680n/afoo.bar
681n/a *
682n/aDocstring here.
683n/a""")
684n/a
685n/a def test_parameters_required_after_star_with_initial_parameters_without_docstring(self):
686n/a self.parse_function_should_fail("""
687n/amodule foo
688n/afoo.bar
689n/a this: int
690n/a *
691n/a""")
692n/a
693n/a def test_parameters_required_after_star_with_initial_parameters_and_docstring(self):
694n/a self.parse_function_should_fail("""
695n/amodule foo
696n/afoo.bar
697n/a this: int
698n/a *
699n/aDocstring.
700n/a""")
701n/a
702n/a def test_single_slash(self):
703n/a self.parse_function_should_fail("""
704n/amodule foo
705n/afoo.bar
706n/a /
707n/a /
708n/a""")
709n/a
710n/a def test_mix_star_and_slash(self):
711n/a self.parse_function_should_fail("""
712n/amodule foo
713n/afoo.bar
714n/a x: int
715n/a y: int
716n/a *
717n/a z: int
718n/a /
719n/a""")
720n/a
721n/a def test_parameters_not_permitted_after_slash_for_now(self):
722n/a self.parse_function_should_fail("""
723n/amodule foo
724n/afoo.bar
725n/a /
726n/a x: int
727n/a""")
728n/a
729n/a def test_function_not_at_column_0(self):
730n/a function = self.parse_function("""
731n/a module foo
732n/a foo.bar
733n/a x: int
734n/a Nested docstring here, goeth.
735n/a *
736n/a y: str
737n/a Not at column 0!
738n/a""")
739n/a self.assertEqual("""
740n/abar($module, /, x, *, y)
741n/a--
742n/a
743n/aNot at column 0!
744n/a
745n/a x
746n/a Nested docstring here, goeth.
747n/a""".strip(), function.docstring)
748n/a
749n/a def test_directive(self):
750n/a c = FakeClinic()
751n/a parser = DSLParser(c)
752n/a parser.flag = False
753n/a parser.directives['setflag'] = lambda : setattr(parser, 'flag', True)
754n/a block = clinic.Block("setflag")
755n/a parser.parse(block)
756n/a self.assertTrue(parser.flag)
757n/a
758n/a def test_legacy_converters(self):
759n/a block = self.parse('module os\nos.access\n path: "s"')
760n/a module, function = block.signatures
761n/a self.assertIsInstance((function.parameters['path']).converter, clinic.str_converter)
762n/a
763n/a def parse(self, text):
764n/a c = FakeClinic()
765n/a parser = DSLParser(c)
766n/a block = clinic.Block(text)
767n/a parser.parse(block)
768n/a return block
769n/a
770n/a def parse_function(self, text, signatures_in_block=2, function_index=1):
771n/a block = self.parse(text)
772n/a s = block.signatures
773n/a self.assertEqual(len(s), signatures_in_block)
774n/a assert isinstance(s[0], clinic.Module)
775n/a assert isinstance(s[function_index], clinic.Function)
776n/a return s[function_index]
777n/a
778n/a def test_scaffolding(self):
779n/a # test repr on special values
780n/a self.assertEqual(repr(clinic.unspecified), '<Unspecified>')
781n/a self.assertEqual(repr(clinic.NULL), '<Null>')
782n/a
783n/a # test that fail fails
784n/a with support.captured_stdout() as stdout:
785n/a with self.assertRaises(SystemExit):
786n/a clinic.fail('The igloos are melting!', filename='clown.txt', line_number=69)
787n/a self.assertEqual(stdout.getvalue(), 'Error in file "clown.txt" on line 69:\nThe igloos are melting!\n')
788n/a
789n/a
790n/aif __name__ == "__main__":
791n/a unittest.main()