|  | 
| 6 | 6 | actually change the in-tree generated code. | 
| 7 | 7 | """ | 
| 8 | 8 | 
 | 
|  | 9 | +from __future__ import annotations | 
|  | 10 | + | 
| 9 | 11 | import contextlib | 
| 10 | 12 | import os | 
| 11 | 13 | import os.path | 
| 12 | 14 | import sys | 
|  | 15 | +import typing | 
|  | 16 | + | 
|  | 17 | +if typing.TYPE_CHECKING: | 
|  | 18 | +    from collections.abc import Iterator | 
|  | 19 | +    from io import TextIOWrapper | 
|  | 20 | + | 
|  | 21 | +    _Outcome: typing.TypeAlias = typing.Literal['created', 'updated', 'same'] | 
| 13 | 22 | 
 | 
| 14 | 23 | 
 | 
| 15 | 24 | @contextlib.contextmanager | 
| 16 |  | -def updating_file_with_tmpfile(filename, tmpfile=None): | 
|  | 25 | +def updating_file_with_tmpfile( | 
|  | 26 | +    filename: str, | 
|  | 27 | +    tmpfile: str | None = None, | 
|  | 28 | +) -> Iterator[tuple[TextIOWrapper, TextIOWrapper]]: | 
| 17 | 29 |     """A context manager for updating a file via a temp file. | 
| 18 | 30 | 
 | 
| 19 | 31 |     The context manager provides two open files: the source file open | 
| @@ -46,13 +58,18 @@ def updating_file_with_tmpfile(filename, tmpfile=None): | 
| 46 | 58 |     update_file_with_tmpfile(filename, tmpfile) | 
| 47 | 59 | 
 | 
| 48 | 60 | 
 | 
| 49 |  | -def update_file_with_tmpfile(filename, tmpfile, *, create=False): | 
|  | 61 | +def update_file_with_tmpfile( | 
|  | 62 | +    filename: str, | 
|  | 63 | +    tmpfile: str, | 
|  | 64 | +    *, | 
|  | 65 | +    create: bool = False, | 
|  | 66 | +) -> _Outcome: | 
| 50 | 67 |     try: | 
| 51 | 68 |         targetfile = open(filename, 'rb') | 
| 52 | 69 |     except FileNotFoundError: | 
| 53 | 70 |         if not create: | 
| 54 | 71 |             raise  # re-raise | 
| 55 |  | -        outcome = 'created' | 
|  | 72 | +        outcome: _Outcome = 'created' | 
| 56 | 73 |         os.replace(tmpfile, filename) | 
| 57 | 74 |     else: | 
| 58 | 75 |         with targetfile: | 
|  | 
0 commit comments