Skip to content

Commit dc54714

Browse files
authored
gh-113317: Finish splitting Argument Clinic into sub-files (#117513)
Add libclinic.parser module and move the following classes and functions there: * Parser * PythonParser * create_parser_namespace() Add libclinic.dsl_parser module and move the following classes, functions and variables there: * ConverterArgs * DSLParser * FunctionNames * IndentStack * ParamState * StateKeeper * eval_ast_expr() * unsupported_special_methods Add libclinic.app module and move the Clinic class there. Add libclinic.cli module and move the following functions there: * create_cli() * main() * parse_file() * run_clinic()
1 parent 8584334 commit dc54714

File tree

10 files changed

+2238
-2194
lines changed

10 files changed

+2238
-2194
lines changed

Lib/test/test_clinic.py

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,26 @@
1717
test_tools.skip_if_missing('clinic')
1818
with test_tools.imports_under_tool('clinic'):
1919
import libclinic
20-
from libclinic.converters import int_converter, str_converter
20+
from libclinic import ClinicError, unspecified, NULL, fail
21+
from libclinic.converters import int_converter, str_converter, self_converter
2122
from libclinic.function import (
23+
Module, Class, Function, FunctionKind, Parameter,
2224
permute_optional_groups, permute_right_option_groups,
2325
permute_left_option_groups)
2426
import clinic
25-
from clinic import DSLParser
27+
from libclinic.clanguage import CLanguage
28+
from libclinic.converter import converters, legacy_converters
29+
from libclinic.return_converters import return_converters, int_return_converter
30+
from libclinic.block_parser import Block, BlockParser
31+
from libclinic.codegen import BlockPrinter, Destination
32+
from libclinic.dsl_parser import DSLParser
33+
from libclinic.cli import parse_file, Clinic
2634

2735

2836
def _make_clinic(*, filename='clinic_tests', limited_capi=False):
29-
clang = clinic.CLanguage(filename)
30-
c = clinic.Clinic(clang, filename=filename, limited_capi=limited_capi)
31-
c.block_parser = clinic.BlockParser('', clang)
37+
clang = CLanguage(filename)
38+
c = Clinic(clang, filename=filename, limited_capi=limited_capi)
39+
c.block_parser = BlockParser('', clang)
3240
return c
3341

3442

@@ -47,7 +55,7 @@ def _expect_failure(tc, parser, code, errmsg, *, filename=None, lineno=None,
4755
if strip:
4856
code = code.strip()
4957
errmsg = re.escape(errmsg)
50-
with tc.assertRaisesRegex(clinic.ClinicError, errmsg) as cm:
58+
with tc.assertRaisesRegex(ClinicError, errmsg) as cm:
5159
parser(code)
5260
if filename is not None:
5361
tc.assertEqual(cm.exception.filename, filename)
@@ -62,12 +70,12 @@ def restore_dict(converters, old_converters):
6270

6371

6472
def save_restore_converters(testcase):
65-
testcase.addCleanup(restore_dict, clinic.converters,
66-
clinic.converters.copy())
67-
testcase.addCleanup(restore_dict, clinic.legacy_converters,
68-
clinic.legacy_converters.copy())
69-
testcase.addCleanup(restore_dict, clinic.return_converters,
70-
clinic.return_converters.copy())
73+
testcase.addCleanup(restore_dict, converters,
74+
converters.copy())
75+
testcase.addCleanup(restore_dict, legacy_converters,
76+
legacy_converters.copy())
77+
testcase.addCleanup(restore_dict, return_converters,
78+
return_converters.copy())
7179

7280

7381
class ClinicWholeFileTest(TestCase):
@@ -140,11 +148,11 @@ def test_whitespace_before_stop_line(self):
140148
self.expect_failure(raw, err, filename="test.c", lineno=2)
141149

142150
def test_parse_with_body_prefix(self):
143-
clang = clinic.CLanguage(None)
151+
clang = CLanguage(None)
144152
clang.body_prefix = "//"
145153
clang.start_line = "//[{dsl_name} start]"
146154
clang.stop_line = "//[{dsl_name} stop]"
147-
cl = clinic.Clinic(clang, filename="test.c", limited_capi=False)
155+
cl = Clinic(clang, filename="test.c", limited_capi=False)
148156
raw = dedent("""
149157
//[clinic start]
150158
//module test
@@ -660,8 +668,8 @@ def expect_parsing_failure(
660668
self, *, filename, expected_error, verify=True, output=None
661669
):
662670
errmsg = re.escape(dedent(expected_error).strip())
663-
with self.assertRaisesRegex(clinic.ClinicError, errmsg):
664-
clinic.parse_file(filename, limited_capi=False)
671+
with self.assertRaisesRegex(ClinicError, errmsg):
672+
parse_file(filename, limited_capi=False)
665673

666674
def test_parse_file_no_extension(self) -> None:
667675
self.expect_parsing_failure(
@@ -782,13 +790,13 @@ def test_multiline_substitution(self):
782790

783791
def test_text_before_block_marker(self):
784792
regex = re.escape("found before '{marker}'")
785-
with self.assertRaisesRegex(clinic.ClinicError, regex):
793+
with self.assertRaisesRegex(ClinicError, regex):
786794
libclinic.linear_format("no text before marker for you! {marker}",
787795
marker="not allowed!")
788796

789797
def test_text_after_block_marker(self):
790798
regex = re.escape("found after '{marker}'")
791-
with self.assertRaisesRegex(clinic.ClinicError, regex):
799+
with self.assertRaisesRegex(ClinicError, regex):
792800
libclinic.linear_format("{marker} no text after marker for you!",
793801
marker="not allowed!")
794802

@@ -810,10 +818,10 @@ def parse(self, block):
810818

811819
class ClinicBlockParserTest(TestCase):
812820
def _test(self, input, output):
813-
language = clinic.CLanguage(None)
821+
language = CLanguage(None)
814822

815-
blocks = list(clinic.BlockParser(input, language))
816-
writer = clinic.BlockPrinter(language)
823+
blocks = list(BlockParser(input, language))
824+
writer = BlockPrinter(language)
817825
c = _make_clinic()
818826
for block in blocks:
819827
writer.print_block(block, limited_capi=c.limited_capi, header_includes=c.includes)
@@ -841,8 +849,8 @@ def test_round_trip_2(self):
841849
""")
842850

843851
def _test_clinic(self, input, output):
844-
language = clinic.CLanguage(None)
845-
c = clinic.Clinic(language, filename="file", limited_capi=False)
852+
language = CLanguage(None)
853+
c = Clinic(language, filename="file", limited_capi=False)
846854
c.parsers['inert'] = InertParser(c)
847855
c.parsers['copy'] = CopyParser(c)
848856
computed = c.parse(input)
@@ -875,16 +883,16 @@ class ClinicParserTest(TestCase):
875883
def parse(self, text):
876884
c = _make_clinic()
877885
parser = DSLParser(c)
878-
block = clinic.Block(text)
886+
block = Block(text)
879887
parser.parse(block)
880888
return block
881889

882890
def parse_function(self, text, signatures_in_block=2, function_index=1):
883891
block = self.parse(text)
884892
s = block.signatures
885893
self.assertEqual(len(s), signatures_in_block)
886-
assert isinstance(s[0], clinic.Module)
887-
assert isinstance(s[function_index], clinic.Function)
894+
assert isinstance(s[0], Module)
895+
assert isinstance(s[function_index], Function)
888896
return s[function_index]
889897

890898
def expect_failure(self, block, err, *,
@@ -899,7 +907,7 @@ def checkDocstring(self, fn, expected):
899907

900908
def test_trivial(self):
901909
parser = DSLParser(_make_clinic())
902-
block = clinic.Block("""
910+
block = Block("""
903911
module os
904912
os.access
905913
""")
@@ -1188,7 +1196,7 @@ def test_base_invalid_syntax(self):
11881196
Function 'stat' has an invalid parameter declaration:
11891197
\s+'invalid syntax: int = 42'
11901198
""").strip()
1191-
with self.assertRaisesRegex(clinic.ClinicError, err):
1199+
with self.assertRaisesRegex(ClinicError, err):
11921200
self.parse_function(block)
11931201

11941202
def test_param_default_invalid_syntax(self):
@@ -1220,7 +1228,7 @@ def test_return_converter(self):
12201228
module os
12211229
os.stat -> int
12221230
""")
1223-
self.assertIsInstance(function.return_converter, clinic.int_return_converter)
1231+
self.assertIsInstance(function.return_converter, int_return_converter)
12241232

12251233
def test_return_converter_invalid_syntax(self):
12261234
block = """
@@ -2036,7 +2044,7 @@ def test_directive(self):
20362044
parser = DSLParser(_make_clinic())
20372045
parser.flag = False
20382046
parser.directives['setflag'] = lambda : setattr(parser, 'flag', True)
2039-
block = clinic.Block("setflag")
2047+
block = Block("setflag")
20402048
parser.parse(block)
20412049
self.assertTrue(parser.flag)
20422050

@@ -2301,14 +2309,14 @@ def test_unused_param(self):
23012309

23022310
def test_scaffolding(self):
23032311
# test repr on special values
2304-
self.assertEqual(repr(clinic.unspecified), '<Unspecified>')
2305-
self.assertEqual(repr(clinic.NULL), '<Null>')
2312+
self.assertEqual(repr(unspecified), '<Unspecified>')
2313+
self.assertEqual(repr(NULL), '<Null>')
23062314

23072315
# test that fail fails
23082316
with support.captured_stdout() as stdout:
23092317
errmsg = 'The igloos are melting'
2310-
with self.assertRaisesRegex(clinic.ClinicError, errmsg) as cm:
2311-
clinic.fail(errmsg, filename='clown.txt', line_number=69)
2318+
with self.assertRaisesRegex(ClinicError, errmsg) as cm:
2319+
fail(errmsg, filename='clown.txt', line_number=69)
23122320
exc = cm.exception
23132321
self.assertEqual(exc.filename, 'clown.txt')
23142322
self.assertEqual(exc.lineno, 69)
@@ -3998,15 +4006,15 @@ def test_suffix_all_lines(self):
39984006

39994007
class ClinicReprTests(unittest.TestCase):
40004008
def test_Block_repr(self):
4001-
block = clinic.Block("foo")
4009+
block = Block("foo")
40024010
expected_repr = "<clinic.Block 'text' input='foo' output=None>"
40034011
self.assertEqual(repr(block), expected_repr)
40044012

4005-
block2 = clinic.Block("bar", "baz", [], "eggs", "spam")
4013+
block2 = Block("bar", "baz", [], "eggs", "spam")
40064014
expected_repr_2 = "<clinic.Block 'baz' input='bar' output='eggs'>"
40074015
self.assertEqual(repr(block2), expected_repr_2)
40084016

4009-
block3 = clinic.Block(
4017+
block3 = Block(
40104018
input="longboi_" * 100,
40114019
dsl_name="wow_so_long",
40124020
signatures=[],
@@ -4021,47 +4029,47 @@ def test_Block_repr(self):
40214029
def test_Destination_repr(self):
40224030
c = _make_clinic()
40234031

4024-
destination = clinic.Destination(
4032+
destination = Destination(
40254033
"foo", type="file", clinic=c, args=("eggs",)
40264034
)
40274035
self.assertEqual(
40284036
repr(destination), "<clinic.Destination 'foo' type='file' file='eggs'>"
40294037
)
40304038

4031-
destination2 = clinic.Destination("bar", type="buffer", clinic=c)
4039+
destination2 = Destination("bar", type="buffer", clinic=c)
40324040
self.assertEqual(repr(destination2), "<clinic.Destination 'bar' type='buffer'>")
40334041

40344042
def test_Module_repr(self):
4035-
module = clinic.Module("foo", _make_clinic())
4043+
module = Module("foo", _make_clinic())
40364044
self.assertRegex(repr(module), r"<clinic.Module 'foo' at \d+>")
40374045

40384046
def test_Class_repr(self):
4039-
cls = clinic.Class("foo", _make_clinic(), None, 'some_typedef', 'some_type_object')
4047+
cls = Class("foo", _make_clinic(), None, 'some_typedef', 'some_type_object')
40404048
self.assertRegex(repr(cls), r"<clinic.Class 'foo' at \d+>")
40414049

40424050
def test_FunctionKind_repr(self):
40434051
self.assertEqual(
4044-
repr(clinic.FunctionKind.INVALID), "<clinic.FunctionKind.INVALID>"
4052+
repr(FunctionKind.INVALID), "<clinic.FunctionKind.INVALID>"
40454053
)
40464054
self.assertEqual(
4047-
repr(clinic.FunctionKind.CLASS_METHOD), "<clinic.FunctionKind.CLASS_METHOD>"
4055+
repr(FunctionKind.CLASS_METHOD), "<clinic.FunctionKind.CLASS_METHOD>"
40484056
)
40494057

40504058
def test_Function_and_Parameter_reprs(self):
4051-
function = clinic.Function(
4059+
function = Function(
40524060
name='foo',
40534061
module=_make_clinic(),
40544062
cls=None,
40554063
c_basename=None,
40564064
full_name='foofoo',
4057-
return_converter=clinic.int_return_converter(),
4058-
kind=clinic.FunctionKind.METHOD_INIT,
4065+
return_converter=int_return_converter(),
4066+
kind=FunctionKind.METHOD_INIT,
40594067
coexist=False
40604068
)
40614069
self.assertEqual(repr(function), "<clinic.Function 'foo'>")
40624070

4063-
converter = clinic.self_converter('bar', 'bar', function)
4064-
parameter = clinic.Parameter(
4071+
converter = self_converter('bar', 'bar', function)
4072+
parameter = Parameter(
40654073
"bar",
40664074
kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
40674075
function=function,

0 commit comments

Comments
 (0)