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