Skip to content
Open
Changes from 11 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
c2bf11e
[mypyc] feat: improve LoadLiteral annotation determinism
BobTheBuidler Oct 7, 2025
d750ec1
Update emit.py
BobTheBuidler Oct 7, 2025
486f9f0
new sort key
BobTheBuidler Oct 7, 2025
c30a727
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 7, 2025
d174f4e
use new safe key
BobTheBuidler Oct 7, 2025
28c0399
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 7, 2025
be0de78
Update emit.py
BobTheBuidler Oct 7, 2025
d33d2d9
Update emit.py
BobTheBuidler Oct 7, 2025
650d99d
Update emit.py
BobTheBuidler Oct 7, 2025
da22785
Update emit.py
BobTheBuidler Oct 7, 2025
96aa63e
refactor
BobTheBuidler Oct 7, 2025
58e4b67
Update emit.py
BobTheBuidler Oct 7, 2025
ca1e97f
Merge branch 'master' into anns-determinism
BobTheBuidler Oct 14, 2025
ff337de
Merge branch 'master' into anns-determinism
BobTheBuidler Jan 6, 2026
629f1cf
extract func pformat_deterministic
BobTheBuidler Jan 6, 2026
ac8f3ff
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 6, 2026
866d86e
add tests
BobTheBuidler Jan 6, 2026
e31ad86
Merge branch 'anns-determinism' of https://github.com/BobTheBuidler/m…
BobTheBuidler Jan 6, 2026
6e0153a
fix test
BobTheBuidler Jan 6, 2026
5aa3d40
fix test
BobTheBuidler Jan 6, 2026
ab520a2
fix test
BobTheBuidler Jan 6, 2026
99a07ea
fix recursion
BobTheBuidler Jan 6, 2026
0656926
use subclass
BobTheBuidler Jan 6, 2026
3b19181
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 6, 2026
09328d5
fix test
BobTheBuidler Jan 6, 2026
e3e9813
Merge branch 'anns-determinism' of https://github.com/BobTheBuidler/m…
BobTheBuidler Jan 6, 2026
f64440f
Merge branch 'master' into anns-determinism
BobTheBuidler Jan 17, 2026
a76a89c
test(mypyc): add hash-seed stability checks for deterministic pformat…
BobTheBuidler Feb 20, 2026
16931f9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 20, 2026
9dd8b75
fix(mypyc): stabilize nested frozenset literal formatting determinist…
BobTheBuidler Feb 20, 2026
fa97ab6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 20, 2026
a4f1253
fix(mypyc): type deterministic pprint hooks to unblock CI self-check
BobTheBuidler Feb 21, 2026
38113c3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 21, 2026
8aed63b
Merge branch 'master' into anns-determinism
BobTheBuidler Feb 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions mypyc/codegen/emit.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,17 @@ def object_annotation(self, obj: object, line: str) -> str:

If it contains illegal characters, an empty string is returned."""
line_width = self._indent + len(line)

# temporarily override pprint._safe_key
default_safe_key = pprint._safe_key # type: ignore [attr-defined]
pprint._safe_key = _mypyc_safe_key # type: ignore [attr-defined]

# pretty print the object
formatted = pprint.pformat(obj, compact=True, width=max(90 - line_width, 20))

# replace the _safe_key
pprint._safe_key = default_safe_key # type: ignore [attr-defined]

if any(x in formatted for x in ("/*", "*/", "\0")):
return ""

Expand Down Expand Up @@ -1226,3 +1236,13 @@ def c_array_initializer(components: list[str], *, indented: bool = False) -> str
# Multi-line result
res.append(indent + ", ".join(current))
return "{\n " + ",\n ".join(res) + "\n" + indent + "}"


def _mypyc_safe_key(obj: object) -> str:
"""A custom sort key implementation for pprint that makes the output deterministic
for all literal types supported by mypyc.

This is NOT safe for use as a sort key for other types, so we MUST replace the
original pprint._safe_key once we've pprinted our object.
"""
return str(type(obj)) + repr(obj)
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.

Actually, isn't this still random? repr(obj) might not be a deterministic ordering? Or is it deterministic because maybe frozenset is the same repr based on the same input (I would check but... lazy).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's deterministic so long as the objects contained within the tuple are supported mypyc literal types, and this should have already been validated by this point in the code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh wait, you're correct in one case: if the frozenset contains another frozenset

This can be mitigated by replacing repr with pformat (to ensure the frozenset goes thru the same ordering process)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've implemented this recursive pformatting, let me know if this works for you