Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 91 additions & 3 deletions Lib/test/test_clinic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,7 +69,7 @@ def __init__(self):
self.converters = FakeConvertersDict()
self.legacy_converters = FakeConvertersDict()
self.language = clinic.CLanguage(None)
self.filename = None
self.filename = "clinic_tests"
self.destination_buffers = {}
self.block_parser = clinic.BlockParser('', self.language)
self.modules = collections.OrderedDict()
Expand DownExpand Up@@ -1849,10 +1849,10 @@ def test_non_ascii_character_in_docstring(self):
self.parse(block)
# The line numbers are off; this is a known limitation.
expected = dedent("""\
Warning on line 0:
Warning in file 'clinic_tests' on line 0:
Non-ascii characters are not allowed in docstrings: 'á'

Warning on line 0:
Warning in file 'clinic_tests' on line 0:
Non-ascii characters are not allowed in docstrings: 'ü', 'á', 'ß'

""")
Expand DownExpand Up@@ -3030,5 +3030,93 @@ def test_suffix_all_lines(self):
self.assertEqual(out, expected)


class ClinicReprTests(unittest.TestCase):
def test_Block_repr(self):
block = clinic.Block("foo")
expected_repr = "<clinic.Block 'text' input='foo' output=None>"
self.assertEqual(repr(block), expected_repr)

block2 = clinic.Block("bar", "baz", [], "eggs", "spam")
expected_repr_2 = "<clinic.Block 'baz' input='bar' output='eggs'>"
self.assertEqual(repr(block2), expected_repr_2)

block3 = clinic.Block(
input="longboi_" * 100,
dsl_name="wow_so_long",
signatures=[],
output="very_long_" * 100,
indent=""
)
expected_repr_3 = (
"<clinic.Block 'wow_so_long' input='longboi_longboi_longboi_l...' output='very_long_very_long_very_...'>"
)
self.assertEqual(repr(block3), expected_repr_3)

def test_Destination_repr(self):
destination = clinic.Destination(
"foo", type="file", clinic=FakeClinic(), args=("eggs",)
)
self.assertEqual(
repr(destination), "<clinic.Destination 'foo' type='file' file='eggs'>"
)

destination2 = clinic.Destination("bar", type="buffer", clinic=FakeClinic())
self.assertEqual(repr(destination2), "<clinic.Destination 'bar' type='buffer'>")

def test_Module_repr(self):
module = clinic.Module("foo", FakeClinic())
self.assertRegex(repr(module), r"<clinic.Module 'foo' at \d+>")

def test_Class_repr(self):
cls = clinic.Class("foo", FakeClinic(), None, 'some_typedef', 'some_type_object')
self.assertRegex(repr(cls), r"<clinic.Class 'foo' at \d+>")

def test_FunctionKind_repr(self):
self.assertEqual(
repr(clinic.FunctionKind.INVALID), "<clinic.FunctionKind.INVALID>"
)
self.assertEqual(
repr(clinic.FunctionKind.CLASS_METHOD), "<clinic.FunctionKind.CLASS_METHOD>"
)

def test_Function_and_Parameter_reprs(self):
function = clinic.Function(
name='foo',
module=FakeClinic(),
cls=None,
c_basename=None,
full_name='foofoo',
return_converter=clinic.init_return_converter(),
kind=clinic.FunctionKind.METHOD_INIT,
coexist=False
)
self.assertEqual(repr(function), "<clinic.Function 'foo'>")

converter = clinic.self_converter('bar', 'bar', function)
parameter = clinic.Parameter(
"bar",
kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
function=function,
converter=converter
)
self.assertEqual(repr(parameter), "<clinic.Parameter 'bar'>")

def test_Monitor_repr(self):
monitor = clinic.cpp.Monitor()
self.assertRegex(repr(monitor), r"<clinic.Monitor \d+ line=0 condition=''>")

monitor.line_number = 42
monitor.stack.append(("token1", "condition1"))
self.assertRegex(
repr(monitor), r"<clinic.Monitor \d+ line=42 condition='condition1'>"
)

monitor.stack.append(("token2", "condition2"))
self.assertRegex(
repr(monitor),
r"<clinic.Monitor \d+ line=42 condition='condition1 && condition2'>"
)


if __name__ == "__main__":
unittest.main()
20 changes: 12 additions & 8 deletions Tools/clinic/clinic.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -1728,8 +1728,12 @@ def summarize(s: object) -> str:
if len(s) > 30:
return s[:26] + "..." + s[0]
return s
return "".join((
"<Block ", dsl_name, " input=", summarize(self.input), " output=", summarize(self.output), ">"))
parts = (
repr(dsl_name),
f"input={summarize(self.input)}",
f"output={summarize(self.output)}"
)
return f"<clinic.Block {' '.join(parts)}>"


class BlockParser:
Expand DownExpand Up@@ -2037,10 +2041,10 @@ def __post_init__(self, args: tuple[str, ...]) -> None:

def __repr__(self) -> str:
if self.type == 'file':
file_repr = " " + repr(self.filename)
type_repr = f"type='file' file={self.filename!r}"
else:
file_repr = ''
return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
type_repr = f"type={self.type!r}"
return f"<clinic.Destination {self.name!r} {type_repr}>"

def clear(self) -> None:
if self.type != 'buffer':
Expand DownExpand Up@@ -2500,7 +2504,7 @@ def new_or_init(self) -> bool:
return self in {FunctionKind.METHOD_INIT, FunctionKind.METHOD_NEW}

def __repr__(self) -> str:
return f"<FunctionKind.{self.name}>"
return f"<clinic.FunctionKind.{self.name}>"


INVALID: Final = FunctionKind.INVALID
Expand DownExpand Up@@ -2577,7 +2581,7 @@ def methoddef_flags(self) -> str | None:
return '|'.join(flags)

def __repr__(self) -> str:
return '<clinic.Function ' + self.name + '>'
return f'<clinic.Function {self.name!r}>'

def copy(self, **overrides: Any) -> Function:
f = dc.replace(self, **overrides)
Expand DownExpand Up@@ -2605,7 +2609,7 @@ class Parameter:
right_bracket_count: int = dc.field(init=False, default=0)

def __repr__(self) -> str:
return '<clinic.Parameter ' + self.name + '>'
return f'<clinic.Parameter {self.name!r}>'

def is_keyword_only(self) -> bool:
return self.kind == inspect.Parameter.KEYWORD_ONLY
Expand Down
7 changes: 5 additions & 2 deletions Tools/clinic/cpp.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,12 @@ def __post_init__(self) -> None:
self.line_number = 0

def __repr__(self) -> str:
return (
f"<Monitor {id(self)} line={self.line_number} condition={self.condition()!r}>"
parts = (
str(id(self)),
f"line={self.line_number}",
f"condition={self.condition()!r}"
)
return f"<clinic.Monitor {' '.join(parts)}>"

def status(self) -> str:
return str(self.line_number).rjust(4) + ": " + self.condition()
Expand Down