| 450 | |
| 451 | |
| 452 | class _AtomicFile: |
| 453 | def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: |
| 454 | self._f = f |
| 455 | self._tmp_filename = tmp_filename |
| 456 | self._real_filename = real_filename |
| 457 | self.closed = False |
| 458 | |
| 459 | @property |
| 460 | def name(self) -> str: |
| 461 | return self._real_filename |
| 462 | |
| 463 | def close(self, delete: bool = False) -> None: |
| 464 | if self.closed: |
| 465 | return |
| 466 | self._f.close() |
| 467 | os.replace(self._tmp_filename, self._real_filename) |
| 468 | self.closed = True |
| 469 | |
| 470 | def __getattr__(self, name: str) -> t.Any: |
| 471 | return getattr(self._f, name) |
| 472 | |
| 473 | def __enter__(self) -> _AtomicFile: |
| 474 | return self |
| 475 | |
| 476 | def __exit__( |
| 477 | self, |
| 478 | exc_type: type[BaseException] | None, |
| 479 | exc_value: BaseException | None, |
| 480 | tb: TracebackType | None, |
| 481 | ) -> None: |
| 482 | self.close(delete=exc_type is not None) |
| 483 | |
| 484 | def __repr__(self) -> str: |
| 485 | return repr(self._f) |
| 486 | |
| 487 | |
| 488 | def strip_ansi(value: str) -> str: |