Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/boltons/mboxutils.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
| author | shellac |
|---|---|
| date | Mon, 22 Mar 2021 18:12:50 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:4f3585e2f14b |
|---|---|
| 1 # -*- coding: utf-8 -*- | |
| 2 """Useful utilities for working with the `mbox`_-formatted | |
| 3 mailboxes. Credit to Mark Williams for these. | |
| 4 | |
| 5 .. _mbox: https://en.wikipedia.org/wiki/Mbox | |
| 6 """ | |
| 7 | |
| 8 import mailbox | |
| 9 import tempfile | |
| 10 | |
| 11 | |
| 12 DEFAULT_MAXMEM = 4 * 1024 * 1024 # 4MB | |
| 13 | |
| 14 | |
| 15 class mbox_readonlydir(mailbox.mbox): | |
| 16 """A subclass of :class:`mailbox.mbox` suitable for use with mboxs | |
| 17 insides a read-only mail directory, e.g., ``/var/mail``. Otherwise | |
| 18 the API is exactly the same as the built-in mbox. | |
| 19 | |
| 20 Deletes messages via truncation, in the manner of `Heirloom mailx`_. | |
| 21 | |
| 22 Args: | |
| 23 path (str): Path to the mbox file. | |
| 24 factory (type): Message type (defaults to :class:`rfc822.Message`) | |
| 25 create (bool): Create mailbox if it does not exist. (defaults | |
| 26 to ``True``) | |
| 27 maxmem (int): Specifies, in bytes, the largest sized mailbox | |
| 28 to attempt to copy into memory. Larger mailboxes | |
| 29 will be copied incrementally which is more | |
| 30 hazardous. (defaults to 4MB) | |
| 31 | |
| 32 .. note:: | |
| 33 | |
| 34 Because this truncates and rewrites parts of the mbox file, | |
| 35 this class can corrupt your mailbox. Only use this if you know | |
| 36 the built-in :class:`mailbox.mbox` does not work for your use | |
| 37 case. | |
| 38 | |
| 39 .. _Heirloom mailx: http://heirloom.sourceforge.net/mailx.html | |
| 40 """ | |
| 41 def __init__(self, path, factory=None, create=True, maxmem=1024 * 1024): | |
| 42 mailbox.mbox.__init__(self, path, factory, create) | |
| 43 self.maxmem = maxmem | |
| 44 | |
| 45 def flush(self): | |
| 46 """Write any pending changes to disk. This is called on mailbox | |
| 47 close and is usually not called explicitly. | |
| 48 | |
| 49 .. note:: | |
| 50 | |
| 51 This deletes messages via truncation. Interruptions may | |
| 52 corrupt your mailbox. | |
| 53 """ | |
| 54 | |
| 55 # Appending and basic assertions are the same as in mailbox.mbox.flush. | |
| 56 if not self._pending: | |
| 57 if self._pending_sync: | |
| 58 # Messages have only been added, so syncing the file | |
| 59 # is enough. | |
| 60 mailbox._sync_flush(self._file) | |
| 61 self._pending_sync = False | |
| 62 return | |
| 63 | |
| 64 # In order to be writing anything out at all, self._toc must | |
| 65 # already have been generated (and presumably has been modified | |
| 66 # by adding or deleting an item). | |
| 67 assert self._toc is not None | |
| 68 | |
| 69 # Check length of self._file; if it's changed, some other process | |
| 70 # has modified the mailbox since we scanned it. | |
| 71 self._file.seek(0, 2) | |
| 72 cur_len = self._file.tell() | |
| 73 if cur_len != self._file_length: | |
| 74 raise mailbox.ExternalClashError('Size of mailbox file changed ' | |
| 75 '(expected %i, found %i)' % | |
| 76 (self._file_length, cur_len)) | |
| 77 | |
| 78 self._file.seek(0) | |
| 79 | |
| 80 # Truncation logic begins here. Mostly the same except we | |
| 81 # can use tempfile because we're not doing rename(2). | |
| 82 with tempfile.TemporaryFile() as new_file: | |
| 83 new_toc = {} | |
| 84 self._pre_mailbox_hook(new_file) | |
| 85 for key in sorted(self._toc.keys()): | |
| 86 start, stop = self._toc[key] | |
| 87 self._file.seek(start) | |
| 88 self._pre_message_hook(new_file) | |
| 89 new_start = new_file.tell() | |
| 90 while True: | |
| 91 buffer = self._file.read(min(4096, | |
| 92 stop - self._file.tell())) | |
| 93 if buffer == '': | |
| 94 break | |
| 95 new_file.write(buffer) | |
| 96 new_toc[key] = (new_start, new_file.tell()) | |
| 97 self._post_message_hook(new_file) | |
| 98 self._file_length = new_file.tell() | |
| 99 | |
| 100 self._file.seek(0) | |
| 101 new_file.seek(0) | |
| 102 | |
| 103 # Copy back our messages | |
| 104 if self._file_length <= self.maxmem: | |
| 105 self._file.write(new_file.read()) | |
| 106 else: | |
| 107 while True: | |
| 108 buffer = new_file.read(4096) | |
| 109 if not buffer: | |
| 110 break | |
| 111 self._file.write(buffer) | |
| 112 | |
| 113 # Delete the rest. | |
| 114 self._file.truncate() | |
| 115 | |
| 116 # Same wrap up. | |
| 117 self._toc = new_toc | |
| 118 self._pending = False | |
| 119 self._pending_sync = False | |
| 120 if self._locked: | |
| 121 mailbox._lock_file(self._file, dotlock=False) |
