Skip to content
Prev Previous commit
Next Next commit
Improve str_converter unsupported combination of args error message
  • Loading branch information
erlend-aasland committed Feb 7, 2024
commit 94e082e45be8c354833980402badc9d5eabc900e
9 changes: 9 additions & 0 deletions Lib/test/test_clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2028,6 +2028,15 @@ def test_legacy_converters_non_string_constant_annotation(self):
with self.subTest(block=block):
self.expect_failure(block, err, lineno=2)

def test_str_converter_invalid_format_unit(self):
block = """
module foo
foo.bar
a: str(encoding='foo', zeroes=True, accept={})
"""
err = "unsupported combination of str converter arguments"
self.expect_failure(block, err, lineno=2)

def test_other_bizarre_things_in_annotations_fail(self):
err = "Annotations must be either a name, a function call, or a string"
dataset = (
Expand Down
26 changes: 21 additions & 5 deletions Tools/clinic/clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4043,14 +4043,27 @@ class buffer: pass
class rwbuffer: pass
class robuffer: pass

StrConverterKeyType = tuple[frozenset[type[object]], bool, bool]
@dc.dataclass
class StrConverterKey:
accept: frozenset[type[object]]
encoding: bool
zeroes: bool

def __hash__(self) -> int:
return hash((self.accept, self.encoding, self.zeroes))

def __str__(self) -> str:
accept = "{" + ", ".join([tp.__name__ for tp in self.accept]) + "}"
encoding = 'encodingname' if self.encoding else None
zeroes = self.zeroes
return f"{accept=!r}, {encoding=!r}, {zeroes=!r}"

def str_converter_key(
types: TypeSet, encoding: bool | str | None, zeroes: bool
) -> StrConverterKeyType:
return (frozenset(types), bool(encoding), bool(zeroes))
) -> StrConverterKey:
return StrConverterKey(frozenset(types), bool(encoding), bool(zeroes))

str_converter_argument_map: dict[StrConverterKeyType, str] = {}
str_converter_argument_map: dict[StrConverterKey, str] = {}

class str_converter(CConverter):
type = 'const char *'
Expand All @@ -4068,7 +4081,10 @@ def converter_init(
key = str_converter_key(accept, encoding, zeroes)
format_unit = str_converter_argument_map.get(key)
if not format_unit:
fail("str_converter: illegal combination of arguments", key)
fail("unsupported combination of str converter arguments: "
f"{accept=!r}, {encoding=!r}, {zeroes=!r}; "
"allowed combinations are:\n\n"
f"{'\n'.join([str(k) for k in str_converter_argument_map.keys()])}")

self.format_unit = format_unit
self.length = bool(zeroes)
Expand Down