+++ /dev/null
-"""A readline()-style interface to the parts of a multipart message.\r
-\r
-The MultiFile class makes each part of a multipart message "feel" like\r
-an ordinary file, as long as you use fp.readline(). Allows recursive\r
-use, for nested multipart messages. Probably best used together\r
-with module mimetools.\r
-\r
-Suggested use:\r
-\r
-real_fp = open(...)\r
-fp = MultiFile(real_fp)\r
-\r
-"read some lines from fp"\r
-fp.push(separator)\r
-while 1:\r
- "read lines from fp until it returns an empty string" (A)\r
- if not fp.next(): break\r
-fp.pop()\r
-"read remaining lines from fp until it returns an empty string"\r
-\r
-The latter sequence may be used recursively at (A).\r
-It is also allowed to use multiple push()...pop() sequences.\r
-\r
-If seekable is given as 0, the class code will not do the bookkeeping\r
-it normally attempts in order to make seeks relative to the beginning of the\r
-current file part. This may be useful when using MultiFile with a non-\r
-seekable stream object.\r
-"""\r
-from warnings import warn\r
-warn("the multifile module has been deprecated since Python 2.5",\r
- DeprecationWarning, stacklevel=2)\r
-del warn\r
-\r
-__all__ = ["MultiFile","Error"]\r
-\r
-class Error(Exception):\r
- pass\r
-\r
-class MultiFile:\r
-\r
- seekable = 0\r
-\r
- def __init__(self, fp, seekable=1):\r
- self.fp = fp\r
- self.stack = []\r
- self.level = 0\r
- self.last = 0\r
- if seekable:\r
- self.seekable = 1\r
- self.start = self.fp.tell()\r
- self.posstack = []\r
-\r
- def tell(self):\r
- if self.level > 0:\r
- return self.lastpos\r
- return self.fp.tell() - self.start\r
-\r
- def seek(self, pos, whence=0):\r
- here = self.tell()\r
- if whence:\r
- if whence == 1:\r
- pos = pos + here\r
- elif whence == 2:\r
- if self.level > 0:\r
- pos = pos + self.lastpos\r
- else:\r
- raise Error, "can't use whence=2 yet"\r
- if not 0 <= pos <= here or \\r
- self.level > 0 and pos > self.lastpos:\r
- raise Error, 'bad MultiFile.seek() call'\r
- self.fp.seek(pos + self.start)\r
- self.level = 0\r
- self.last = 0\r
-\r
- def readline(self):\r
- if self.level > 0:\r
- return ''\r
- line = self.fp.readline()\r
- # Real EOF?\r
- if not line:\r
- self.level = len(self.stack)\r
- self.last = (self.level > 0)\r
- if self.last:\r
- raise Error, 'sudden EOF in MultiFile.readline()'\r
- return ''\r
- assert self.level == 0\r
- # Fast check to see if this is just data\r
- if self.is_data(line):\r
- return line\r
- else:\r
- # Ignore trailing whitespace on marker lines\r
- marker = line.rstrip()\r
- # No? OK, try to match a boundary.\r
- # Return the line (unstripped) if we don't.\r
- for i, sep in enumerate(reversed(self.stack)):\r
- if marker == self.section_divider(sep):\r
- self.last = 0\r
- break\r
- elif marker == self.end_marker(sep):\r
- self.last = 1\r
- break\r
- else:\r
- return line\r
- # We only get here if we see a section divider or EOM line\r
- if self.seekable:\r
- self.lastpos = self.tell() - len(line)\r
- self.level = i+1\r
- if self.level > 1:\r
- raise Error,'Missing endmarker in MultiFile.readline()'\r
- return ''\r
-\r
- def readlines(self):\r
- list = []\r
- while 1:\r
- line = self.readline()\r
- if not line: break\r
- list.append(line)\r
- return list\r
-\r
- def read(self): # Note: no size argument -- read until EOF only!\r
- return ''.join(self.readlines())\r
-\r
- def next(self):\r
- while self.readline(): pass\r
- if self.level > 1 or self.last:\r
- return 0\r
- self.level = 0\r
- self.last = 0\r
- if self.seekable:\r
- self.start = self.fp.tell()\r
- return 1\r
-\r
- def push(self, sep):\r
- if self.level > 0:\r
- raise Error, 'bad MultiFile.push() call'\r
- self.stack.append(sep)\r
- if self.seekable:\r
- self.posstack.append(self.start)\r
- self.start = self.fp.tell()\r
-\r
- def pop(self):\r
- if self.stack == []:\r
- raise Error, 'bad MultiFile.pop() call'\r
- if self.level <= 1:\r
- self.last = 0\r
- else:\r
- abslastpos = self.lastpos + self.start\r
- self.level = max(0, self.level - 1)\r
- self.stack.pop()\r
- if self.seekable:\r
- self.start = self.posstack.pop()\r
- if self.level > 0:\r
- self.lastpos = abslastpos - self.start\r
-\r
- def is_data(self, line):\r
- return line[:2] != '--'\r
-\r
- def section_divider(self, str):\r
- return "--" + str\r
-\r
- def end_marker(self, str):\r
- return "--" + str + "--"\r