FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Send early errors to workers by ilevkivskyi · Pull Request #20822 · python/mypy · GitHub

Repository navigation

Send early errors to workers - #20822

Merged
ilevkivskyi merged 6 commits into
python:masterfrom
ilevkivskyi:send-errors-to-worers
Feb 17, 2026
Merged

ilevkivskyi merged 6 commits into
python:masterfrom
ilevkivskyi:send-errors-to-worers

Conversation

ilevkivskyi commented Feb 16, 2026 •
edited
Loading

Copy link
Copy Markdown
Member

Ref #933

When parallel parsing is ready, we will not run load_graph() in each worker. So, we need to send early errors (mostly import errors) to the relevant workers. Couple notes here:

  • Now only_once messages are shown only once per worker. It is hard to fix, and I don't think we should really bother. It doesn't affect correctness, and may only slightly increase noise. Btw they were never truly only_once, when reading errors from cache we can get multiple occurrences of the same error/note.
  • While I am at it, I switch few more error to the standard file.py: error: some message format.

This comment has been minimized.

ilevkivskyi marked this pull request as ready for review February 16, 2026 13:45

This comment has been minimized.

ilevkivskyi commented Feb 16, 2026 •
edited
Loading

Copy link
Copy Markdown
Member Author

Btw @hauntsaninja mypy_primer output looks like we aren't really checking attrs now (but it is probably important). To clear, that error is a blocker.

JukkaL left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I have some questions, mostly about things that I don't fully understand. Otherwise looks good.

Comment thread mypy/build_worker/worker.py Outdated
try:
for id in scc.mod_ids:
state = graph[id]
# Extra step below is needed only because we are using local graph.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This comment wasn't clear to me. I'm not sure which extra step this refers to (parse_file or the state.tree is None check?).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

It refers to the whole if/else block. It can be avoided if we would not call load_graph() in the worker.

# Extra step below is needed only because we are using local graph.
# TODO: clone options when switching to coordinator graph.
if state.tree is None:
state.parse_file()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Why are we parsing the file here? Is this related to error processing?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Yes, we want to get the side effect of setting ignored/skipped lines.

Comment thread mypy/build.py Outdated
source_set = BuildSourceSet(sources)
cached_read = fscache.read
errors = Errors(options, read_source=lambda path: read_py_file(path, cached_read))
# Record import errors so that they sn be replayed by the workers.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Typo: sn

Comment thread mypy/build.py
# We don't need parsed trees in coordinator process, we parse only to
# compute dependencies.
state.tree = None
if not temporary:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Should we only have the del statement behind the not temporary condition?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

No, we need the tree until it is used by the caller who created temporary state to check for is_partial_stub_package, I will delete it there to make it more clear.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Actually, I decided to add a little cache for partial packages, otherwise it looks like a lot of potential overhead for a niche use case.

util.hard_exit(0)


def serve(server: IPCServer, ctx: ServerContext) -> None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Unrelated: Add a docstring here?

Comment thread mypy/build.py

for id in graph:
manager.import_map[id] = set(graph[id].dependencies + graph[id].suppressed)
manager.import_map[id] = graph[id].dependencies_set

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Is this change related to error processing or the earlier changes to how we process suppressed modules?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This is just a minor perf optimization (we never check for imports of suppressed deps after graph is loaded). I was scrolling past this line and decided it is not worth a separate PR.

Comment thread mypy/build.py
# Cache for transitive dependency check (expensive).
self.transitive_deps_cache: dict[tuple[int, int], bool] = {}
# Resolved paths for each module in build.
self.path_by_id: dict[str, str] = {}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Is this because we now delete modules in the middle of a build, or is there another reason for maintaing this here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This is mostly for convenience, to avoid passing graph around just for the purpose of mapping id to xpath. In most cases we identify modules by id, but in error-tracking-related code it is always xpath.

Comment thread mypy/build.py
def __init__(self, *, graph: Graph, missing_modules: set[str]) -> None:
self.graph = graph
self.missing_modules = missing_modules
self.from_cache = {mod_id for mod_id in graph if graph[mod_id].meta}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

It looks like we might calculate this on demand using graph, and it wouldn't be much slower than a set lookup. Why are we storing this separately here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

The receiver will not be able to do this after we stop calling load_graph() there. This is because we don't serialize State.meta (it would double the size). The worker only needs to know whether the state is from cache or was already parsed by coordinator. I will try to restructure some code in other places to make this more obvious.

Copy link
Copy Markdown
Member Author

Btw @hauntsaninja mypy_primer output looks like we aren't really checking attrs now (but it is probably important). To clear, that error is a blocker.

hauntsaninja/mypy_primer#241 should fix this.

Copy link
Copy Markdown
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

attrs (https://github.com/python-attrs/attrs)
- mypy: can't read file 'tests/typing_example.py': No such file or directory
+ mypy: error: cannot read file 'tests/typing_example.py': No such file or directory

ilevkivskyi merged commit 70de10e into python:master Feb 17, 2026
25 checks passed
ilevkivskyi deleted the send-errors-to-worers branch February 17, 2026 10:42
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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


Back | FazBrowse Home | New Git URL