diff options
author | Victor Stinner <vstinner@redhat.com> | 2018-09-03 21:17:20 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-03 21:17:20 (GMT) |
commit | 65fc98e7b1f62c2e621f04780a3a77c3498cc195 (patch) | |
tree | 48a7f0e2578d1ca9381ac98a3d27e3996e1b6868 /Tools/clinic | |
parent | 73b00becbdd40f6a80cfa00abf1ae650a2b5e454 (diff) | |
download | cpython-65fc98e7b1f62c2e621f04780a3a77c3498cc195.zip cpython-65fc98e7b1f62c2e621f04780a3a77c3498cc195.tar.gz cpython-65fc98e7b1f62c2e621f04780a3a77c3498cc195.tar.bz2 |
bpo-26901: Fix the Argument Clinic test suite (GH-8879)
* Fix Tools/clinic/clinic_test.py: add missing
FakeClinic.destination_buffers attribute and pass a file argument
to Clinic().
* Rename Tools/clinic/clinic_test.py to Lib/test/test_clinic.py:
add temporary Tools/clinic/ to sys.path to import the clinic
module.
Co-Authored-By: Pablo Galindo <pablogsal@gmail.com>
Diffstat (limited to 'Tools/clinic')
-rw-r--r-- | Tools/clinic/clinic_test.py | 791 |
1 files changed, 0 insertions, 791 deletions
diff --git a/Tools/clinic/clinic_test.py b/Tools/clinic/clinic_test.py deleted file mode 100644 index a9479a6..0000000 --- a/Tools/clinic/clinic_test.py +++ /dev/null @@ -1,791 +0,0 @@ -# Argument Clinic -# Copyright 2012-2013 by Larry Hastings. -# Licensed to the PSF under a contributor agreement. -# - -import clinic -from clinic import DSLParser -import collections -import inspect -from test import support -import sys -import unittest -from unittest import TestCase - - -class FakeConverter: - def __init__(self, name, args): - self.name = name - self.args = args - - -class FakeConverterFactory: - def __init__(self, name): - self.name = name - - def __call__(self, name, default, **kwargs): - return FakeConverter(self.name, kwargs) - - -class FakeConvertersDict: - def __init__(self): - self.used_converters = {} - - def get(self, name, default): - return self.used_converters.setdefault(name, FakeConverterFactory(name)) - -clinic.Clinic.presets_text = '' -c = clinic.Clinic(language='C') - -class FakeClinic: - def __init__(self): - self.converters = FakeConvertersDict() - self.legacy_converters = FakeConvertersDict() - self.language = clinic.CLanguage(None) - self.filename = None - self.block_parser = clinic.BlockParser('', self.language) - self.modules = collections.OrderedDict() - self.classes = collections.OrderedDict() - clinic.clinic = self - self.name = "FakeClinic" - self.line_prefix = self.line_suffix = '' - self.destinations = {} - self.add_destination("block", "buffer") - self.add_destination("file", "buffer") - self.add_destination("suppress", "suppress") - d = self.destinations.get - self.field_destinations = collections.OrderedDict(( - ('docstring_prototype', d('suppress')), - ('docstring_definition', d('block')), - ('methoddef_define', d('block')), - ('impl_prototype', d('block')), - ('parser_prototype', d('suppress')), - ('parser_definition', d('block')), - ('impl_definition', d('block')), - )) - - def get_destination(self, name): - d = self.destinations.get(name) - if not d: - sys.exit("Destination does not exist: " + repr(name)) - return d - - def add_destination(self, name, type, *args): - if name in self.destinations: - sys.exit("Destination already exists: " + repr(name)) - self.destinations[name] = clinic.Destination(name, type, self, *args) - - def is_directive(self, name): - return name == "module" - - def directive(self, name, args): - self.called_directives[name] = args - - _module_and_class = clinic.Clinic._module_and_class - -class ClinicWholeFileTest(TestCase): - def test_eol(self): - # regression test: - # clinic's block parser didn't recognize - # the "end line" for the block if it - # didn't end in "\n" (as in, the last) - # byte of the file was '/'. - # so it would spit out an end line for you. - # and since you really already had one, - # the last line of the block got corrupted. - c = clinic.Clinic(clinic.CLanguage(None)) - raw = "/*[clinic]\nfoo\n[clinic]*/" - cooked = c.parse(raw).splitlines() - end_line = cooked[2].rstrip() - # this test is redundant, it's just here explicitly to catch - # the regression test so we don't forget what it looked like - self.assertNotEqual(end_line, "[clinic]*/[clinic]*/") - self.assertEqual(end_line, "[clinic]*/") - - - -class ClinicGroupPermuterTest(TestCase): - def _test(self, l, m, r, output): - computed = clinic.permute_optional_groups(l, m, r) - self.assertEqual(output, computed) - - def test_range(self): - self._test([['start']], ['stop'], [['step']], - ( - ('stop',), - ('start', 'stop',), - ('start', 'stop', 'step',), - )) - - def test_add_window(self): - self._test([['x', 'y']], ['ch'], [['attr']], - ( - ('ch',), - ('ch', 'attr'), - ('x', 'y', 'ch',), - ('x', 'y', 'ch', 'attr'), - )) - - def test_ludicrous(self): - self._test([['a1', 'a2', 'a3'], ['b1', 'b2']], ['c1'], [['d1', 'd2'], ['e1', 'e2', 'e3']], - ( - ('c1',), - ('b1', 'b2', 'c1'), - ('b1', 'b2', 'c1', 'd1', 'd2'), - ('a1', 'a2', 'a3', 'b1', 'b2', 'c1'), - ('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2'), - ('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2', 'e1', 'e2', 'e3'), - )) - - def test_right_only(self): - self._test([], [], [['a'],['b'],['c']], - ( - (), - ('a',), - ('a', 'b'), - ('a', 'b', 'c') - )) - - def test_have_left_options_but_required_is_empty(self): - def fn(): - clinic.permute_optional_groups(['a'], [], []) - self.assertRaises(AssertionError, fn) - - -class ClinicLinearFormatTest(TestCase): - def _test(self, input, output, **kwargs): - computed = clinic.linear_format(input, **kwargs) - self.assertEqual(output, computed) - - def test_empty_strings(self): - self._test('', '') - - def test_solo_newline(self): - self._test('\n', '\n') - - def test_no_substitution(self): - self._test(""" - abc - """, """ - abc - """) - - def test_empty_substitution(self): - self._test(""" - abc - {name} - def - """, """ - abc - def - """, name='') - - def test_single_line_substitution(self): - self._test(""" - abc - {name} - def - """, """ - abc - GARGLE - def - """, name='GARGLE') - - def test_multiline_substitution(self): - self._test(""" - abc - {name} - def - """, """ - abc - bingle - bungle - - def - """, name='bingle\nbungle\n') - -class InertParser: - def __init__(self, clinic): - pass - - def parse(self, block): - pass - -class CopyParser: - def __init__(self, clinic): - pass - - def parse(self, block): - block.output = block.input - - -class ClinicBlockParserTest(TestCase): - def _test(self, input, output): - language = clinic.CLanguage(None) - - blocks = list(clinic.BlockParser(input, language)) - writer = clinic.BlockPrinter(language) - for block in blocks: - writer.print_block(block) - output = writer.f.getvalue() - assert output == input, "output != input!\n\noutput " + repr(output) + "\n\n input " + repr(input) - - def round_trip(self, input): - return self._test(input, input) - - def test_round_trip_1(self): - self.round_trip(""" - verbatim text here - lah dee dah -""") - def test_round_trip_2(self): - self.round_trip(""" - verbatim text here - lah dee dah -/*[inert] -abc -[inert]*/ -def -/*[inert checksum: 7b18d017f89f61cf17d47f92749ea6930a3f1deb]*/ -xyz -""") - - def _test_clinic(self, input, output): - language = clinic.CLanguage(None) - c = clinic.Clinic(language) - c.parsers['inert'] = InertParser(c) - c.parsers['copy'] = CopyParser(c) - computed = c.parse(input) - self.assertEqual(output, computed) - - def test_clinic_1(self): - self._test_clinic(""" - verbatim text here - lah dee dah -/*[copy input] -def -[copy start generated code]*/ -abc -/*[copy end generated code: output=03cfd743661f0797 input=7b18d017f89f61cf]*/ -xyz -""", """ - verbatim text here - lah dee dah -/*[copy input] -def -[copy start generated code]*/ -def -/*[copy end generated code: output=7b18d017f89f61cf input=7b18d017f89f61cf]*/ -xyz -""") - - -class ClinicParserTest(TestCase): - def test_trivial(self): - parser = DSLParser(FakeClinic()) - block = clinic.Block("module os\nos.access") - parser.parse(block) - module, function = block.signatures - self.assertEqual("access", function.name) - self.assertEqual("os", module.name) - - def test_ignore_line(self): - block = self.parse("#\nmodule os\nos.access") - module, function = block.signatures - self.assertEqual("access", function.name) - self.assertEqual("os", module.name) - - def test_param(self): - function = self.parse_function("module os\nos.access\n path: int") - self.assertEqual("access", function.name) - self.assertEqual(2, len(function.parameters)) - p = function.parameters['path'] - self.assertEqual('path', p.name) - self.assertIsInstance(p.converter, clinic.int_converter) - - def test_param_default(self): - function = self.parse_function("module os\nos.access\n follow_symlinks: bool = True") - p = function.parameters['follow_symlinks'] - self.assertEqual(True, p.default) - - def test_param_with_continuations(self): - function = self.parse_function("module os\nos.access\n follow_symlinks: \\\n bool \\\n =\\\n True") - p = function.parameters['follow_symlinks'] - self.assertEqual(True, p.default) - - def test_param_default_expression(self): - function = self.parse_function("module os\nos.access\n follow_symlinks: int(c_default='MAXSIZE') = sys.maxsize") - p = function.parameters['follow_symlinks'] - self.assertEqual(sys.maxsize, p.default) - self.assertEqual("MAXSIZE", p.converter.c_default) - - s = self.parse_function_should_fail("module os\nos.access\n follow_symlinks: int = sys.maxsize") - 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") - - def test_param_no_docstring(self): - function = self.parse_function(""" -module os -os.access - follow_symlinks: bool = True - something_else: str = ''""") - p = function.parameters['follow_symlinks'] - self.assertEqual(3, len(function.parameters)) - self.assertIsInstance(function.parameters['something_else'].converter, clinic.str_converter) - - def test_param_default_parameters_out_of_order(self): - s = self.parse_function_should_fail(""" -module os -os.access - follow_symlinks: bool = True - something_else: str""") - self.assertEqual(s, """Error on line 0: -Can't have a parameter without a default ('something_else') -after a parameter with a default! -""") - - def disabled_test_converter_arguments(self): - function = self.parse_function("module os\nos.access\n path: path_t(allow_fd=1)") - p = function.parameters['path'] - self.assertEqual(1, p.converter.args['allow_fd']) - - def test_function_docstring(self): - function = self.parse_function(""" -module os -os.stat as os_stat_fn - - path: str - Path to be examined - -Perform a stat system call on the given path.""") - self.assertEqual(""" -stat($module, /, path) --- - -Perform a stat system call on the given path. - - path - Path to be examined -""".strip(), function.docstring) - - def test_explicit_parameters_in_docstring(self): - function = self.parse_function(""" -module foo -foo.bar - x: int - Documentation for x. - y: int - -This is the documentation for foo. - -Okay, we're done here. -""") - self.assertEqual(""" -bar($module, /, x, y) --- - -This is the documentation for foo. - - x - Documentation for x. - -Okay, we're done here. -""".strip(), function.docstring) - - def test_parser_regression_special_character_in_parameter_column_of_docstring_first_line(self): - function = self.parse_function(""" -module os -os.stat - path: str -This/used to break Clinic! -""") - self.assertEqual("stat($module, /, path)\n--\n\nThis/used to break Clinic!", function.docstring) - - def test_c_name(self): - function = self.parse_function("module os\nos.stat as os_stat_fn") - self.assertEqual("os_stat_fn", function.c_basename) - - def test_return_converter(self): - function = self.parse_function("module os\nos.stat -> int") - self.assertIsInstance(function.return_converter, clinic.int_return_converter) - - def test_star(self): - function = self.parse_function("module os\nos.access\n *\n follow_symlinks: bool = True") - p = function.parameters['follow_symlinks'] - self.assertEqual(inspect.Parameter.KEYWORD_ONLY, p.kind) - self.assertEqual(0, p.group) - - def test_group(self): - function = self.parse_function("module window\nwindow.border\n [\n ls : int\n ]\n /\n") - p = function.parameters['ls'] - self.assertEqual(1, p.group) - - def test_left_group(self): - function = self.parse_function(""" -module curses -curses.addch - [ - y: int - Y-coordinate. - x: int - X-coordinate. - ] - ch: char - Character to add. - [ - attr: long - Attributes for the character. - ] - / -""") - for name, group in ( - ('y', -1), ('x', -1), - ('ch', 0), - ('attr', 1), - ): - p = function.parameters[name] - self.assertEqual(p.group, group) - self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) - self.assertEqual(function.docstring.strip(), """ -addch([y, x,] ch, [attr]) - - - y - Y-coordinate. - x - X-coordinate. - ch - Character to add. - attr - Attributes for the character. - """.strip()) - - def test_nested_groups(self): - function = self.parse_function(""" -module curses -curses.imaginary - [ - [ - y1: int - Y-coordinate. - y2: int - Y-coordinate. - ] - x1: int - X-coordinate. - x2: int - X-coordinate. - ] - ch: char - Character to add. - [ - attr1: long - Attributes for the character. - attr2: long - Attributes for the character. - attr3: long - Attributes for the character. - [ - attr4: long - Attributes for the character. - attr5: long - Attributes for the character. - attr6: long - Attributes for the character. - ] - ] - / -""") - for name, group in ( - ('y1', -2), ('y2', -2), - ('x1', -1), ('x2', -1), - ('ch', 0), - ('attr1', 1), ('attr2', 1), ('attr3', 1), - ('attr4', 2), ('attr5', 2), ('attr6', 2), - ): - p = function.parameters[name] - self.assertEqual(p.group, group) - self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) - - self.assertEqual(function.docstring.strip(), """ -imaginary([[y1, y2,] x1, x2,] ch, [attr1, attr2, attr3, [attr4, attr5, - attr6]]) - - - y1 - Y-coordinate. - y2 - Y-coordinate. - x1 - X-coordinate. - x2 - X-coordinate. - ch - Character to add. - attr1 - Attributes for the character. - attr2 - Attributes for the character. - attr3 - Attributes for the character. - attr4 - Attributes for the character. - attr5 - Attributes for the character. - attr6 - Attributes for the character. - """.strip()) - - def parse_function_should_fail(self, s): - with support.captured_stdout() as stdout: - with self.assertRaises(SystemExit): - self.parse_function(s) - return stdout.getvalue() - - def test_disallowed_grouping__two_top_groups_on_left(self): - s = self.parse_function_should_fail(""" -module foo -foo.two_top_groups_on_left - [ - group1 : int - ] - [ - group2 : int - ] - param: int - """) - self.assertEqual(s, - ('Error on line 0:\n' - 'Function two_top_groups_on_left has an unsupported group configuration. (Unexpected state 2.b)\n')) - - def test_disallowed_grouping__two_top_groups_on_right(self): - self.parse_function_should_fail(""" -module foo -foo.two_top_groups_on_right - param: int - [ - group1 : int - ] - [ - group2 : int - ] - """) - - def test_disallowed_grouping__parameter_after_group_on_right(self): - self.parse_function_should_fail(""" -module foo -foo.parameter_after_group_on_right - param: int - [ - [ - group1 : int - ] - group2 : int - ] - """) - - def test_disallowed_grouping__group_after_parameter_on_left(self): - self.parse_function_should_fail(""" -module foo -foo.group_after_parameter_on_left - [ - group2 : int - [ - group1 : int - ] - ] - param: int - """) - - def test_disallowed_grouping__empty_group_on_left(self): - self.parse_function_should_fail(""" -module foo -foo.empty_group - [ - [ - ] - group2 : int - ] - param: int - """) - - def test_disallowed_grouping__empty_group_on_right(self): - self.parse_function_should_fail(""" -module foo -foo.empty_group - param: int - [ - [ - ] - group2 : int - ] - """) - - def test_no_parameters(self): - function = self.parse_function(""" -module foo -foo.bar - -Docstring - -""") - self.assertEqual("bar($module, /)\n--\n\nDocstring", function.docstring) - self.assertEqual(1, len(function.parameters)) # self! - - def test_init_with_no_parameters(self): - function = self.parse_function(""" -module foo -class foo.Bar "unused" "notneeded" -foo.Bar.__init__ - -Docstring - -""", signatures_in_block=3, function_index=2) - # self is not in the signature - self.assertEqual("Bar()\n--\n\nDocstring", function.docstring) - # but it *is* a parameter - self.assertEqual(1, len(function.parameters)) - - def test_illegal_module_line(self): - self.parse_function_should_fail(""" -module foo -foo.bar => int - / -""") - - def test_illegal_c_basename(self): - self.parse_function_should_fail(""" -module foo -foo.bar as 935 - / -""") - - def test_single_star(self): - self.parse_function_should_fail(""" -module foo -foo.bar - * - * -""") - - def test_parameters_required_after_star_without_initial_parameters_or_docstring(self): - self.parse_function_should_fail(""" -module foo -foo.bar - * -""") - - def test_parameters_required_after_star_without_initial_parameters_with_docstring(self): - self.parse_function_should_fail(""" -module foo -foo.bar - * -Docstring here. -""") - - def test_parameters_required_after_star_with_initial_parameters_without_docstring(self): - self.parse_function_should_fail(""" -module foo -foo.bar - this: int - * -""") - - def test_parameters_required_after_star_with_initial_parameters_and_docstring(self): - self.parse_function_should_fail(""" -module foo -foo.bar - this: int - * -Docstring. -""") - - def test_single_slash(self): - self.parse_function_should_fail(""" -module foo -foo.bar - / - / -""") - - def test_mix_star_and_slash(self): - self.parse_function_should_fail(""" -module foo -foo.bar - x: int - y: int - * - z: int - / -""") - - def test_parameters_not_permitted_after_slash_for_now(self): - self.parse_function_should_fail(""" -module foo -foo.bar - / - x: int -""") - - def test_function_not_at_column_0(self): - function = self.parse_function(""" - module foo - foo.bar - x: int - Nested docstring here, goeth. - * - y: str - Not at column 0! -""") - self.assertEqual(""" -bar($module, /, x, *, y) --- - -Not at column 0! - - x - Nested docstring here, goeth. -""".strip(), function.docstring) - - def test_directive(self): - c = FakeClinic() - parser = DSLParser(c) - parser.flag = False - parser.directives['setflag'] = lambda : setattr(parser, 'flag', True) - block = clinic.Block("setflag") - parser.parse(block) - self.assertTrue(parser.flag) - - def test_legacy_converters(self): - block = self.parse('module os\nos.access\n path: "s"') - module, function = block.signatures - self.assertIsInstance((function.parameters['path']).converter, clinic.str_converter) - - def parse(self, text): - c = FakeClinic() - parser = DSLParser(c) - block = clinic.Block(text) - parser.parse(block) - return block - - def parse_function(self, text, signatures_in_block=2, function_index=1): - block = self.parse(text) - s = block.signatures - self.assertEqual(len(s), signatures_in_block) - assert isinstance(s[0], clinic.Module) - assert isinstance(s[function_index], clinic.Function) - return s[function_index] - - def test_scaffolding(self): - # test repr on special values - self.assertEqual(repr(clinic.unspecified), '<Unspecified>') - self.assertEqual(repr(clinic.NULL), '<Null>') - - # test that fail fails - with support.captured_stdout() as stdout: - with self.assertRaises(SystemExit): - clinic.fail('The igloos are melting!', filename='clown.txt', line_number=69) - self.assertEqual(stdout.getvalue(), 'Error in file "clown.txt" on line 69:\nThe igloos are melting!\n') - - -if __name__ == "__main__": - unittest.main() |