Skip to content

start fixing mypy issues #5772

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open

Conversation

graingert
Copy link

@graingert graingert commented Apr 27, 2025

starts work on #5773

this also builds on pre-commit being run #5717

Please review the following checklist.

  • Docstrings on all new or modified functions / classes
  • Updated documentation
  • Updated CHANGELOG.md (where appropriate)

@graingert graingert marked this pull request as ready for review April 27, 2025 08:30
Copy link
Collaborator

@willmcgugan willmcgugan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not keen on changes which make things slower purely to satisfy the type checker.

One-off asserts or casts I can accept. But I'd prefer to avoid code within loops that isn't required for runtime.

@@ -33,42 +33,41 @@ class WorkerDeclarationError(Exception):
"""An error in the declaration of a worker method."""


if TYPE_CHECKING:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this? Given that the overloads are not needed at runtime, this check is a small win for startup time.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not supported by mypy, it needs the definition in the same block as the overrides

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tried, and Mypy seems happy with the condition. Do we have different versions of Mypy?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assumed I had the one from the poetry lock file, I'll check

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have 1.14.1

for example when I run mypy I get no-overload-impl for this patten.

mypy src/textual/walk.py
src/textual/walk.py:88: error: An overloaded function outside a stub file must have an implementation  [no-overload-impl]
src/textual/walk.py:104: error: Name "walk_breadth_first" already defined on line 88  [no-redef]
Found 2 errors in 1 file (checked 1 source file)

however not for this case:

mypy src/textual/_work_decorator.py
src/textual/_work_decorator.py:71: error: Type variable "textual._work_decorator.ReturnType" is unbound  [valid-type]
src/textual/_work_decorator.py:71: note: (Hint: Use "Generic[ReturnType]" or "Protocol[ReturnType]" base class to bind "ReturnType" inside a class)
src/textual/_work_decorator.py:71: note: (Hint: Use "ReturnType" in function signature to bind "ReturnType" inside a function)

while (node := node._parent) is not None:
add_node(node)
return cast("list[DOMNode]", nodes)
nodes = [self]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change will make this method slower. If it is to satisfy Mypy, can we not have both fast and correct?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the add_node = node.append trick is actually slower now

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last time I looked in to this, nodes.append version was still slower. Although the difference is much smaller in recent Pythons.

The node is not None also adds work, and I doesn't appear to be neccesary.


captures = query.captures(self._syntax_tree.root_node, **captures_kwargs)
return captures

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is more than typing. Can you explain why this change was necessary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed for the new interface in tree-sitter, it's a breaking change in v24

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latest tree-sitter also drops support for Python3.9, which Textual hasn't yet. We've already decided to drop syntax support for 3.9, but we would need to update the pyproject.toml accordingly.

while (node := node._parent) is not None:
add_node(node)
return cast("list[DOMNode]", nodes)
nodes = []
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.


if WINDOWS:
if sys.platform == "win32":
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are going to do this, do we need the WINDOWS constant?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect the WINDOWS constant is redundant

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest we remove it.

@@ -243,7 +243,7 @@ def is_attached(self) -> bool:
except NoActiveAppError:
return False
node: MessagePump | None = self
while (node := node._parent) is not None:
while node is not None and (node := node._parent) is not None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds an additional check per loop, which is never going to be truthy. I think we should find another way to satisfy Mypy if that is why this was added.

@@ -150,7 +151,7 @@ def __rich_repr__(self) -> rich.repr.Result:
yield "name", getattr(self, "name", None), None

@classmethod
def _clear_watchers(cls, obj: Reactable) -> None:
def _clear_watchers(cls, obj: MessagePump) -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that a Reactable is a DOMNode, why is this change neccesary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_clear_watchers is called with a less specific type than Reactable or DOMNode elsewhere

@@ -17,22 +17,20 @@
WalkType = TypeVar("WalkType", bound=DOMNode)


if TYPE_CHECKING:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment re overloads. They just add to startup time.

@@ -979,15 +986,14 @@ def get_child_by_id(
)
return child

if TYPE_CHECKING:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overloads again

runner = run_callable
else:
raise WorkerError("Unsupported attempt to run a thread worker")
return await loop.run_in_executor(None, run_coroutine, self._work) # type: ignore[arg-type]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really better? Can't we modify the original in a simpler way to satisfy Mypy?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type for the runner local is very complicated and would need to be explicitly stated here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants