Skip to content

Conversation

AlexWaygood
Copy link
Member

@AlexWaygood AlexWaygood commented Jul 7, 2023

I tried long and hard to see if there was a sane way of annotating the output field of the Block class. In the end I concluded that, from a typing perspective, the current code is somewhat insane, so there's no sane way of doing it without substantially refactoring the code first 🙃 For now, I propose that we annotate it with Any and leave it for another day.

The issue is that output usually has type str | None, as stated by the docstring here:

cpython/Tools/clinic/clinic.py

Lines 1659 to 1660 in 363f4f9

output is either str or None. If str, it's the output
from this block, with embedded '\n' characters.

But whenever self.block is referenced from inside the DSLParser class, it's of type list[str] (I'm pretty confident self.block is an instance of Block):

cpython/Tools/clinic/clinic.py

Lines 4471 to 4476 in 363f4f9

def directive_dump(self, name: str) -> None:
self.block.output.append(self.clinic.get_destination(name).dump())
def directive_printout(self, *args: str) -> None:
self.block.output.append(' '.join(args))
self.block.output.append('\n')

This is because DSLParser.parse() sets block.output to a list at the beginning of the function, and then sets it back to a string at the end of the function:

block.output = []

cpython/Tools/clinic/clinic.py

Lines 4515 to 4518 in 363f4f9

if self.preserve_output:
if block.output:
fail("'preserve' only works for blocks that don't produce any output!")
block.output = self.saved_output

Needless to say, this makes mypy furious if you give Block.output a type that isn't Any 🙃

@erlend-aasland
Copy link
Contributor

Good digging, there! Wow, yeah, we need to refactor this piece of code :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants