[3.14] gh-133403: Type Tools/build/update_file.py and check it with mypy (GH-133404) (#133603)

gh-133403: Type `Tools/build/update_file.py` and check it with `mypy` (GH-133404)
(cherry picked from commit 50b52cba2d)

Co-authored-by: sobolevn <mail@sobolevn.me>
Co-authored-by: Zachary Ware <zach@python.org>
This commit is contained in:
Miss Islington (bot) 2025-05-08 08:32:05 +02:00 committed by GitHub
parent f12e576128
commit e8c279f394
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 4 deletions

View file

@ -1,7 +1,9 @@
[mypy] [mypy]
files = files =
Tools/build/compute-changes.py, Tools/build/compute-changes.py,
Tools/build/generate_sbom.py Tools/build/generate_sbom.py,
Tools/build/update_file.py
pretty = True pretty = True
# Make sure Python can still be built # Make sure Python can still be built
@ -10,6 +12,8 @@ python_version = 3.10
# ...And be strict: # ...And be strict:
strict = True strict = True
strict_bytes = True
local_partial_types = True
extra_checks = True extra_checks = True
enable_error_code = ignore-without-code,redundant-expr,truthy-bool,possibly-undefined enable_error_code = ignore-without-code,redundant-expr,truthy-bool,possibly-undefined
warn_unreachable = True warn_unreachable = True

View file

@ -6,14 +6,27 @@ This avoids wholesale rebuilds when a code (re)generation phase does not
actually change the in-tree generated code. actually change the in-tree generated code.
""" """
from __future__ import annotations
import contextlib import contextlib
import os import os
import os.path import os.path
import sys import sys
TYPE_CHECKING = False
if TYPE_CHECKING:
import typing
from collections.abc import Iterator
from io import TextIOWrapper
_Outcome: typing.TypeAlias = typing.Literal['created', 'updated', 'same']
@contextlib.contextmanager @contextlib.contextmanager
def updating_file_with_tmpfile(filename, tmpfile=None): def updating_file_with_tmpfile(
filename: str,
tmpfile: str | None = None,
) -> Iterator[tuple[TextIOWrapper, TextIOWrapper]]:
"""A context manager for updating a file via a temp file. """A context manager for updating a file via a temp file.
The context manager provides two open files: the source file open The context manager provides two open files: the source file open
@ -46,13 +59,18 @@ def updating_file_with_tmpfile(filename, tmpfile=None):
update_file_with_tmpfile(filename, tmpfile) update_file_with_tmpfile(filename, tmpfile)
def update_file_with_tmpfile(filename, tmpfile, *, create=False): def update_file_with_tmpfile(
filename: str,
tmpfile: str,
*,
create: bool = False,
) -> _Outcome:
try: try:
targetfile = open(filename, 'rb') targetfile = open(filename, 'rb')
except FileNotFoundError: except FileNotFoundError:
if not create: if not create:
raise # re-raise raise # re-raise
outcome = 'created' outcome: _Outcome = 'created'
os.replace(tmpfile, filename) os.replace(tmpfile, filename)
else: else:
with targetfile: with targetfile: