I have the following code
def parse_names(tex_names: list[str]) -> set[str]:
# the list comprehension in question
return set(parsed_name for parsed_name in [_parse_name(tex_name) for tex_name in tex_names] if parsed_name)
def _parse_name(tex_name: str) -> Optional[str]:
tex_regex = re.compile(r"^%? ?([\w() äöüÄÖÜß]+)( \((ab|bis) \d{2}:\d{2} Uhr\))?,")
match = tex_regex.match(tex_name)
if match:
return match.groups()[0]
return None
with an example usage
def test_parse_names():
raw_names = [
"% Valid Name,",
" Without percent,",
"Without space,",
"% Another (valid) name,",
"% Max Mustermann (ab 13:00 Uhr),",
"% Maxi Mustermann (bis 14:00 Uhr),",
"% Mara Musterfrau (von 13:00 Uhr),", # invalid
"% Lara Musterfrau von 13:00 Uhr,", # invalid
"12345", # invalid
"%% some message", # invalid
"Missing comma", # invalid
]
expected = {
"Valid Name",
"Without percent",
"Without space",
"Another (valid) name",
"Max Mustermann",
"Maxi Mustermann"
}
actual = parse_names(raw_names)
assert actual == expected
Is it possible to simplify the list comprehension while maintaining correct typing? E.g.
def parse_names(tex_names: list[str]) -> set[str]:
return set(_parse_name(tex_name) for tex_name in tex_names if _parse_name(tex_name))
triggers the mypy error
error: List comprehension has incompatible type List[Optional[str]]; expected List[str]