Back to index

python3.2  3.2.2
Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes
mailbox.Babyl Class Reference
Inheritance diagram for mailbox.Babyl:
Inheritance graph
[legend]
Collaboration diagram for mailbox.Babyl:
Collaboration graph
[legend]

List of all members.

Public Member Functions

def __init__
def add
def remove
def __setitem__
def get_message
def get_bytes
def get_file
def get_labels
def iterkeys
def __contains__
def __len__
def lock
def unlock
def flush
def close
def __delitem__
def discard
def get
def __getitem__
def get_string
def keys
def itervalues
def __iter__
def values
def iteritems
def items
def clear
def pop
def popitem
def update

Private Member Functions

def _generate_toc
def _pre_mailbox_hook
def _pre_message_hook
def _post_message_hook
def _install_message

Private Attributes

 _labels
 _toc
 _next_key
 _file_length

Static Private Attributes

tuple _special_labels

Detailed Description

An Rmail-style Babyl mailbox.

Definition at line 1204 of file mailbox.py.


Constructor & Destructor Documentation

def mailbox.Babyl.__init__ (   self,
  path,
  factory = None,
  create = True 
)
Initialize a Babyl mailbox.

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1210 of file mailbox.py.

01210 
01211     def __init__(self, path, factory=None, create=True):
01212         """Initialize a Babyl mailbox."""
01213         _singlefileMailbox.__init__(self, path, factory, create)
01214         self._labels = {}

Here is the caller graph for this function:


Member Function Documentation

def mailbox._singlefileMailbox.__contains__ (   self,
  key 
) [inherited]
Return True if the keyed message exists, False otherwise.

Reimplemented from mailbox.Mailbox.

Definition at line 622 of file mailbox.py.

00622 
00623     def __contains__(self, key):
00624         """Return True if the keyed message exists, False otherwise."""
00625         self._lookup()
00626         return key in self._toc

Here is the call graph for this function:

def mailbox.Mailbox.__delitem__ (   self,
  key 
) [inherited]

Definition at line 54 of file mailbox.py.

00054 
00055     def __delitem__(self, key):
00056         self.remove(key)

Here is the call graph for this function:

def mailbox.Mailbox.__getitem__ (   self,
  key 
) [inherited]
Return the keyed message; raise KeyError if it doesn't exist.

Definition at line 75 of file mailbox.py.

00075 
00076     def __getitem__(self, key):
00077         """Return the keyed message; raise KeyError if it doesn't exist."""
00078         if not self._factory:
00079             return self.get_message(key)
00080         else:
00081             with contextlib.closing(self.get_file(key)) as file:
00082                 return self._factory(file)

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Mailbox.__iter__ (   self) [inherited]

Definition at line 119 of file mailbox.py.

00119 
00120     def __iter__(self):
00121         return self.itervalues()

Here is the call graph for this function:

def mailbox._singlefileMailbox.__len__ (   self) [inherited]
Return a count of messages in the mailbox.

Reimplemented from mailbox.Mailbox.

Definition at line 627 of file mailbox.py.

00627 
00628     def __len__(self):
00629         """Return a count of messages in the mailbox."""
00630         self._lookup()
00631         return len(self._toc)

Here is the call graph for this function:

def mailbox.Babyl.__setitem__ (   self,
  key,
  message 
)
Replace the keyed message; raise KeyError if it doesn't exist.

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1228 of file mailbox.py.

01228 
01229     def __setitem__(self, key, message):
01230         """Replace the keyed message; raise KeyError if it doesn't exist."""
01231         _singlefileMailbox.__setitem__(self, key, message)
01232         if isinstance(message, BabylMessage):
01233             self._labels[key] = message.get_labels()

def mailbox.Babyl._generate_toc (   self) [private]
Generate key-to-(start, stop) table of contents.

Definition at line 1297 of file mailbox.py.

01297 
01298     def _generate_toc(self):
01299         """Generate key-to-(start, stop) table of contents."""
01300         starts, stops = [], []
01301         self._file.seek(0)
01302         next_pos = 0
01303         label_lists = []
01304         while True:
01305             line_pos = next_pos
01306             line = self._file.readline()
01307             next_pos = self._file.tell()
01308             if line == b'\037\014' + linesep:
01309                 if len(stops) < len(starts):
01310                     stops.append(line_pos - len(linesep))
01311                 starts.append(next_pos)
01312                 labels = [label.strip() for label
01313                                         in self._file.readline()[1:].split(b',')
01314                                         if label.strip()]
01315                 label_lists.append(labels)
01316             elif line == b'\037' or line == b'\037' + linesep:
01317                 if len(stops) < len(starts):
01318                     stops.append(line_pos - len(linesep))
01319             elif not line:
01320                 stops.append(line_pos - len(linesep))
01321                 break
01322         self._toc = dict(enumerate(zip(starts, stops)))
01323         self._labels = dict(enumerate(label_lists))
01324         self._next_key = len(self._toc)
01325         self._file.seek(0, 2)
01326         self._file_length = self._file.tell()

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Babyl._install_message (   self,
  message 
) [private]
Write message contents and return (start, stop).

Definition at line 1345 of file mailbox.py.

01345 
01346     def _install_message(self, message):
01347         """Write message contents and return (start, stop)."""
01348         start = self._file.tell()
01349         if isinstance(message, BabylMessage):
01350             special_labels = []
01351             labels = []
01352             for label in message.get_labels():
01353                 if label in self._special_labels:
01354                     special_labels.append(label)
01355                 else:
01356                     labels.append(label)
01357             self._file.write(b'1')
01358             for label in special_labels:
01359                 self._file.write(b', ' + label.encode())
01360             self._file.write(b',,')
01361             for label in labels:
01362                 self._file.write(b' ' + label.encode() + b',')
01363             self._file.write(linesep)
01364         else:
01365             self._file.write(b'1,,' + linesep)
01366         if isinstance(message, email.message.Message):
01367             orig_buffer = io.BytesIO()
01368             orig_generator = email.generator.BytesGenerator(orig_buffer, False, 0)
01369             orig_generator.flatten(message)
01370             orig_buffer.seek(0)
01371             while True:
01372                 line = orig_buffer.readline()
01373                 self._file.write(line.replace(b'\n', linesep))
01374                 if line == b'\n' or not line:
01375                     break
01376             self._file.write(b'*** EOOH ***' + linesep)
01377             if isinstance(message, BabylMessage):
01378                 vis_buffer = io.BytesIO()
01379                 vis_generator = email.generator.BytesGenerator(vis_buffer, False, 0)
01380                 vis_generator.flatten(message.get_visible())
01381                 while True:
01382                     line = vis_buffer.readline()
01383                     self._file.write(line.replace(b'\n', linesep))
01384                     if line == b'\n' or not line:
01385                         break
01386             else:
01387                 orig_buffer.seek(0)
01388                 while True:
01389                     line = orig_buffer.readline()
01390                     self._file.write(line.replace(b'\n', linesep))
01391                     if line == b'\n' or not line:
01392                         break
01393             while True:
01394                 buffer = orig_buffer.read(4096) # Buffer size is arbitrary.
01395                 if not buffer:
01396                     break
01397                 self._file.write(buffer.replace(b'\n', linesep))
01398         elif isinstance(message, (bytes, str, io.StringIO)):
01399             if isinstance(message, io.StringIO):
01400                 warnings.warn("Use of StringIO input is deprecated, "
01401                     "use BytesIO instead", DeprecationWarning, 3)
01402                 message = message.getvalue()
01403             if isinstance(message, str):
01404                 message = self._string_to_bytes(message)
01405             body_start = message.find(b'\n\n') + 2
01406             if body_start - 2 != -1:
01407                 self._file.write(message[:body_start].replace(b'\n', linesep))
01408                 self._file.write(b'*** EOOH ***' + linesep)
01409                 self._file.write(message[:body_start].replace(b'\n', linesep))
01410                 self._file.write(message[body_start:].replace(b'\n', linesep))
01411             else:
01412                 self._file.write(b'*** EOOH ***' + linesep + linesep)
01413                 self._file.write(message.replace(b'\n', linesep))
01414         elif hasattr(message, 'readline'):
01415             if hasattr(message, 'buffer'):
01416                 warnings.warn("Use of text mode files is deprecated, "
01417                     "use a binary mode file instead", DeprecationWarning, 3)
01418                 message = message.buffer
01419             original_pos = message.tell()
01420             first_pass = True
01421             while True:
01422                 line = message.readline()
01423                 # Universal newline support.
01424                 if line.endswith(b'\r\n'):
01425                     line = line[:-2] + b'\n'
01426                 elif line.endswith(b'\r'):
01427                     line = line[:-1] + b'\n'
01428                 self._file.write(line.replace(b'\n', linesep))
01429                 if line == b'\n' or not line:
01430                     self._file.write(b'*** EOOH ***' + linesep)
01431                     if first_pass:
01432                         first_pass = False
01433                         message.seek(original_pos)
01434                     else:
01435                         break
01436             while True:
01437                 buffer = message.read(4096)     # Buffer size is arbitrary.
01438                 if not buffer:
01439                     break
01440                 self._file.write(buffer.replace(b'\n', linesep))
01441         else:
01442             raise TypeError('Invalid message type: %s' % type(message))
01443         stop = self._file.tell()
01444         return (start, stop)
01445 

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Babyl._post_message_hook (   self,
  f 
) [private]
Called after writing each message to file f.

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1341 of file mailbox.py.

01341 
01342     def _post_message_hook(self, f):
01343         """Called after writing each message to file f."""
01344         f.write(linesep + b'\037')

def mailbox.Babyl._pre_mailbox_hook (   self,
  f 
) [private]
Called before writing the mailbox to file f.

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1327 of file mailbox.py.

01327 
01328     def _pre_mailbox_hook(self, f):
01329         """Called before writing the mailbox to file f."""
01330         babyl = b'BABYL OPTIONS:' + linesep
01331         babyl += b'Version: 5' + linesep
01332         labels = self.get_labels()
01333         labels = (label.encode() for label in labels)
01334         babyl += b'Labels:' + b','.join(labels) + linesep
01335         babyl += b'\037'
01336         f.write(babyl)

Here is the call graph for this function:

def mailbox.Babyl._pre_message_hook (   self,
  f 
) [private]
Called before writing each message to file f.

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1337 of file mailbox.py.

01337 
01338     def _pre_message_hook(self, f):
01339         """Called before writing each message to file f."""
01340         f.write(b'\014' + linesep)

def mailbox.Babyl.add (   self,
  message 
)
Add message and return assigned key.

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1215 of file mailbox.py.

01215 
01216     def add(self, message):
01217         """Add message and return assigned key."""
01218         key = _singlefileMailbox.add(self, message)
01219         if isinstance(message, BabylMessage):
01220             self._labels[key] = message.get_labels()
01221         return key

Here is the caller graph for this function:

def mailbox.Mailbox.clear (   self) [inherited]
Delete all messages.

Definition at line 147 of file mailbox.py.

00147 
00148     def clear(self):
00149         """Delete all messages."""
00150         for key in self.keys():
00151             self.discard(key)

Here is the call graph for this function:

def mailbox._singlefileMailbox.close (   self) [inherited]
Flush and close the mailbox.

Reimplemented from mailbox.Mailbox.

Definition at line 714 of file mailbox.py.

00714 
00715     def close(self):
00716         """Flush and close the mailbox."""
00717         self.flush()
00718         if self._locked:
00719             self.unlock()
00720         self._file.close()  # Sync has been done by self.flush() above.

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Mailbox.discard (   self,
  key 
) [inherited]
If the keyed message exists, remove it.

Reimplemented in mailbox.Maildir.

Definition at line 57 of file mailbox.py.

00057 
00058     def discard(self, key):
00059         """If the keyed message exists, remove it."""
00060         try:
00061             self.remove(key)
00062         except KeyError:
00063             pass

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox._singlefileMailbox.flush (   self) [inherited]
Write any pending changes to disk.

Reimplemented from mailbox.Mailbox.

Definition at line 644 of file mailbox.py.

00644 
00645     def flush(self):
00646         """Write any pending changes to disk."""
00647         if not self._pending:
00648             return
00649 
00650         # In order to be writing anything out at all, self._toc must
00651         # already have been generated (and presumably has been modified
00652         # by adding or deleting an item).
00653         assert self._toc is not None
00654 
00655         # Check length of self._file; if it's changed, some other process
00656         # has modified the mailbox since we scanned it.
00657         self._file.seek(0, 2)
00658         cur_len = self._file.tell()
00659         if cur_len != self._file_length:
00660             raise ExternalClashError('Size of mailbox file changed '
00661                                      '(expected %i, found %i)' %
00662                                      (self._file_length, cur_len))
00663 
00664         new_file = _create_temporary(self._path)
00665         try:
00666             new_toc = {}
00667             self._pre_mailbox_hook(new_file)
00668             for key in sorted(self._toc.keys()):
00669                 start, stop = self._toc[key]
00670                 self._file.seek(start)
00671                 self._pre_message_hook(new_file)
00672                 new_start = new_file.tell()
00673                 while True:
00674                     buffer = self._file.read(min(4096,
00675                                                  stop - self._file.tell()))
00676                     if not buffer:
00677                         break
00678                     new_file.write(buffer)
00679                 new_toc[key] = (new_start, new_file.tell())
00680                 self._post_message_hook(new_file)
00681         except:
00682             new_file.close()
00683             os.remove(new_file.name)
00684             raise
00685         _sync_close(new_file)
00686         # self._file is about to get replaced, so no need to sync.
00687         self._file.close()
00688         try:
00689             os.rename(new_file.name, self._path)
00690         except OSError as e:
00691             if e.errno == errno.EEXIST or \
00692               (os.name == 'os2' and e.errno == errno.EACCES):
00693                 os.remove(self._path)
00694                 os.rename(new_file.name, self._path)
00695             else:
00696                 raise
00697         self._file = open(self._path, 'rb+')
00698         self._toc = new_toc
00699         self._pending = False
00700         if self._locked:
00701             _lock_file(self._file, dotlock=False)

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Mailbox.get (   self,
  key,
  default = None 
) [inherited]
Return the keyed message, or default if it doesn't exist.

Definition at line 68 of file mailbox.py.

00068 
00069     def get(self, key, default=None):
00070         """Return the keyed message, or default if it doesn't exist."""
00071         try:
00072             return self.__getitem__(key)
00073         except KeyError:
00074             return default

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Babyl.get_bytes (   self,
  key 
)
Return a string representation or raise a KeyError.

Reimplemented from mailbox.Mailbox.

Definition at line 1262 of file mailbox.py.

01262 
01263     def get_bytes(self, key):
01264         """Return a string representation or raise a KeyError."""
01265         start, stop = self._lookup(key)
01266         self._file.seek(start)
01267         self._file.readline()   # Skip b'1,' line specifying labels.
01268         original_headers = io.BytesIO()
01269         while True:
01270             line = self._file.readline()
01271             if line == b'*** EOOH ***' + linesep or not line:
01272                 break
01273             original_headers.write(line.replace(linesep, b'\n'))
01274         while True:
01275             line = self._file.readline()
01276             if line == linesep or not line:
01277                 break
01278         headers = original_headers.getvalue()
01279         n = stop - self._file.tell()
01280         assert n >= 0
01281         data = self._file.read(n)
01282         data = data.replace(linesep, b'\n')
01283         return headers + data

Here is the call graph for this function:

def mailbox.Babyl.get_file (   self,
  key 
)
Return a file-like representation or raise a KeyError.

Reimplemented from mailbox.Mailbox.

Definition at line 1284 of file mailbox.py.

01284 
01285     def get_file(self, key):
01286         """Return a file-like representation or raise a KeyError."""
01287         return io.BytesIO(self.get_bytes(key).replace(b'\n', linesep))

Here is the call graph for this function:

def mailbox.Babyl.get_labels (   self)
Return a list of user-defined labels in the mailbox.

Definition at line 1288 of file mailbox.py.

01288 
01289     def get_labels(self):
01290         """Return a list of user-defined labels in the mailbox."""
01291         self._lookup()
01292         labels = set()
01293         for label_list in self._labels.values():
01294             labels.update(label_list)
01295         labels.difference_update(self._special_labels)
01296         return list(labels)

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Babyl.get_message (   self,
  key 
)
Return a Message representation or raise a KeyError.

Reimplemented from mailbox.Mailbox.

Definition at line 1234 of file mailbox.py.

01234 
01235     def get_message(self, key):
01236         """Return a Message representation or raise a KeyError."""
01237         start, stop = self._lookup(key)
01238         self._file.seek(start)
01239         self._file.readline()   # Skip b'1,' line specifying labels.
01240         original_headers = io.BytesIO()
01241         while True:
01242             line = self._file.readline()
01243             if line == b'*** EOOH ***' + linesep or not line:
01244                 break
01245             original_headers.write(line.replace(linesep, b'\n'))
01246         visible_headers = io.BytesIO()
01247         while True:
01248             line = self._file.readline()
01249             if line == linesep or not line:
01250                 break
01251             visible_headers.write(line.replace(linesep, b'\n'))
01252         # Read up to the stop, or to the end
01253         n = stop - self._file.tell()
01254         assert n >= 0
01255         body = self._file.read(n)
01256         body = body.replace(linesep, b'\n')
01257         msg = BabylMessage(original_headers.getvalue() + body)
01258         msg.set_visible(visible_headers.getvalue())
01259         if key in self._labels:
01260             msg.set_labels(self._labels[key])
01261         return msg

Here is the call graph for this function:

def mailbox.Mailbox.get_string (   self,
  key 
) [inherited]
Return a string representation or raise a KeyError.

Uses email.message.Message to create a 7bit clean string
representation of the message.

Definition at line 87 of file mailbox.py.

00087 
00088     def get_string(self, key):
00089         """Return a string representation or raise a KeyError.
00090 
00091         Uses email.message.Message to create a 7bit clean string
00092         representation of the message."""
00093         return email.message_from_bytes(self.get_bytes(key)).as_string()

Here is the call graph for this function:

def mailbox.Mailbox.items (   self) [inherited]
Return a list of (key, message) tuples. Memory intensive.

Definition at line 135 of file mailbox.py.

00135 
00136     def items(self):
00137         """Return a list of (key, message) tuples. Memory intensive."""
00138         return list(self.iteritems())

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Mailbox.iteritems (   self) [inherited]
Return an iterator over (key, message) tuples.

Definition at line 126 of file mailbox.py.

00126 
00127     def iteritems(self):
00128         """Return an iterator over (key, message) tuples."""
00129         for key in self.keys():
00130             try:
00131                 value = self[key]
00132             except KeyError:
00133                 continue
00134             yield (key, value)

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox._singlefileMailbox.iterkeys (   self) [inherited]
Return an iterator over keys.

Reimplemented from mailbox.Mailbox.

Definition at line 616 of file mailbox.py.

00616 
00617     def iterkeys(self):
00618         """Return an iterator over keys."""
00619         self._lookup()
00620         for key in self._toc.keys():
00621             yield key

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Mailbox.itervalues (   self) [inherited]
Return an iterator over all messages.

Definition at line 110 of file mailbox.py.

00110 
00111     def itervalues(self):
00112         """Return an iterator over all messages."""
00113         for key in self.keys():
00114             try:
00115                 value = self[key]
00116             except KeyError:
00117                 continue
00118             yield value

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Mailbox.keys (   self) [inherited]
Return a list of keys.

Definition at line 106 of file mailbox.py.

00106 
00107     def keys(self):
00108         """Return a list of keys."""
00109         return list(self.iterkeys())

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox._singlefileMailbox.lock (   self) [inherited]
Lock the mailbox.

Reimplemented from mailbox.Mailbox.

Definition at line 632 of file mailbox.py.

00632 
00633     def lock(self):
00634         """Lock the mailbox."""
00635         if not self._locked:
00636             _lock_file(self._file)
00637             self._locked = True

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Mailbox.pop (   self,
  key,
  default = None 
) [inherited]
Delete the keyed message and return it, or default.

Definition at line 152 of file mailbox.py.

00152 
00153     def pop(self, key, default=None):
00154         """Delete the keyed message and return it, or default."""
00155         try:
00156             result = self[key]
00157         except KeyError:
00158             return default
00159         self.discard(key)
00160         return result

Here is the call graph for this function:

Here is the caller graph for this function:

def mailbox.Mailbox.popitem (   self) [inherited]
Delete an arbitrary (key, message) pair and return it.

Definition at line 161 of file mailbox.py.

00161 
00162     def popitem(self):
00163         """Delete an arbitrary (key, message) pair and return it."""
00164         for key in self.keys():
00165             return (key, self.pop(key))     # This is only run once.
00166         else:
00167             raise KeyError('No messages in mailbox')

Here is the call graph for this function:

def mailbox.Babyl.remove (   self,
  key 
)
Remove the keyed message; raise KeyError if it doesn't exist.

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1222 of file mailbox.py.

01222 
01223     def remove(self, key):
01224         """Remove the keyed message; raise KeyError if it doesn't exist."""
01225         _singlefileMailbox.remove(self, key)
01226         if key in self._labels:
01227             del self._labels[key]

Here is the caller graph for this function:

def mailbox._singlefileMailbox.unlock (   self) [inherited]
Unlock the mailbox if it is locked.

Reimplemented from mailbox.Mailbox.

Definition at line 638 of file mailbox.py.

00638 
00639     def unlock(self):
00640         """Unlock the mailbox if it is locked."""
00641         if self._locked:
00642             _unlock_file(self._file)
00643             self._locked = False

Here is the call graph for this function:

def mailbox.Mailbox.update (   self,
  arg = None 
) [inherited]
Change the messages that correspond to certain keys.

Definition at line 168 of file mailbox.py.

00168 
00169     def update(self, arg=None):
00170         """Change the messages that correspond to certain keys."""
00171         if hasattr(arg, 'iteritems'):
00172             source = arg.items()
00173         elif hasattr(arg, 'items'):
00174             source = arg.items()
00175         else:
00176             source = arg
00177         bad_key = False
00178         for key, message in source:
00179             try:
00180                 self[key] = message
00181             except KeyError:
00182                 bad_key = True
00183         if bad_key:
00184             raise KeyError('No message with key(s)')

Here is the caller graph for this function:

def mailbox.Mailbox.values (   self) [inherited]
Return a list of messages. Memory intensive.

Definition at line 122 of file mailbox.py.

00122 
00123     def values(self):
00124         """Return a list of messages. Memory intensive."""
00125         return list(self.itervalues())

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1325 of file mailbox.py.

Definition at line 1213 of file mailbox.py.

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1323 of file mailbox.py.

tuple mailbox.Babyl._special_labels [static, private]
Initial value:
frozenset(('unseen', 'deleted', 'filed', 'answered',
                                 'forwarded', 'edited', 'resent'))

Definition at line 1207 of file mailbox.py.

mailbox.Babyl._toc [private]

Reimplemented from mailbox._singlefileMailbox.

Definition at line 1321 of file mailbox.py.


The documentation for this class was generated from the following file: