Write any pending changes to disk.
(self)
| 702 | self._locked = False |
| 703 | |
| 704 | def flush(self): |
| 705 | """Write any pending changes to disk.""" |
| 706 | if not self._pending: |
| 707 | if self._pending_sync: |
| 708 | # Messages have only been added, so syncing the file |
| 709 | # is enough. |
| 710 | _sync_flush(self._file) |
| 711 | self._pending_sync = False |
| 712 | return |
| 713 | |
| 714 | # In order to be writing anything out at all, self._toc must |
| 715 | # already have been generated (and presumably has been modified |
| 716 | # by adding or deleting an item). |
| 717 | assert self._toc is not None |
| 718 | |
| 719 | # Check length of self._file; if it's changed, some other process |
| 720 | # has modified the mailbox since we scanned it. |
| 721 | self._file.seek(0, 2) |
| 722 | cur_len = self._file.tell() |
| 723 | if cur_len != self._file_length: |
| 724 | raise ExternalClashError('Size of mailbox file changed ' |
| 725 | '(expected %i, found %i)' % |
| 726 | (self._file_length, cur_len)) |
| 727 | |
| 728 | new_file = _create_temporary(self._path) |
| 729 | try: |
| 730 | new_toc = {} |
| 731 | self._pre_mailbox_hook(new_file) |
| 732 | for key in sorted(self._toc.keys()): |
| 733 | start, stop = self._toc[key] |
| 734 | self._file.seek(start) |
| 735 | self._pre_message_hook(new_file) |
| 736 | new_start = new_file.tell() |
| 737 | while True: |
| 738 | buffer = self._file.read(min(4096, |
| 739 | stop - self._file.tell())) |
| 740 | if not buffer: |
| 741 | break |
| 742 | new_file.write(buffer) |
| 743 | new_toc[key] = (new_start, new_file.tell()) |
| 744 | self._post_message_hook(new_file) |
| 745 | self._file_length = new_file.tell() |
| 746 | except: |
| 747 | new_file.close() |
| 748 | os.remove(new_file.name) |
| 749 | raise |
| 750 | _sync_close(new_file) |
| 751 | # self._file is about to get replaced, so no need to sync. |
| 752 | self._file.close() |
| 753 | # Make sure the new file's mode and owner are the same as the old file's |
| 754 | info = os.stat(self._path) |
| 755 | os.chmod(new_file.name, info.st_mode) |
| 756 | try: |
| 757 | os.chown(new_file.name, info.st_uid, info.st_gid) |
| 758 | except (AttributeError, OSError): |
| 759 | pass |
| 760 | try: |
| 761 | os.rename(new_file.name, self._path) |
no test coverage detected