ยปCore Development>Code coverage>Lib/multifile.py

Python code coverage for Lib/multifile.py

#countcontent
1n/a"""A readline()-style interface to the parts of a multipart message.
2n/a
3n/aThe MultiFile class makes each part of a multipart message "feel" like
4n/aan ordinary file, as long as you use fp.readline(). Allows recursive
5n/ause, for nested multipart messages. Probably best used together
6n/awith module mimetools.
7n/a
8n/aSuggested use:
9n/a
10n/areal_fp = open(...)
11n/afp = MultiFile(real_fp)
12n/a
13n/a"read some lines from fp"
14n/afp.push(separator)
15n/awhile 1:
16n/a "read lines from fp until it returns an empty string" (A)
17n/a if not fp.next(): break
18n/afp.pop()
19n/a"read remaining lines from fp until it returns an empty string"
20n/a
21n/aThe latter sequence may be used recursively at (A).
22n/aIt is also allowed to use multiple push()...pop() sequences.
23n/a
24n/aIf seekable is given as 0, the class code will not do the bookkeeping
25n/ait normally attempts in order to make seeks relative to the beginning of the
26n/acurrent file part. This may be useful when using MultiFile with a non-
27n/aseekable stream object.
281"""
291from warnings import warn
301warn("the multifile module has been deprecated since Python 2.5",
311 DeprecationWarning, stacklevel=2)
321del warn
33n/a
341__all__ = ["MultiFile","Error"]
35n/a
362class Error(Exception):
371 pass
38n/a
392class MultiFile:
40n/a
411 seekable = 0
42n/a
431 def __init__(self, fp, seekable=1):
441 self.fp = fp
451 self.stack = []
461 self.level = 0
471 self.last = 0
481 if seekable:
491 self.seekable = 1
501 self.start = self.fp.tell()
511 self.posstack = []
52n/a
531 def tell(self):
5436 if self.level > 0:
550 return self.lastpos
5636 return self.fp.tell() - self.start
57n/a
581 def seek(self, pos, whence=0):
590 here = self.tell()
600 if whence:
610 if whence == 1:
620 pos = pos + here
630 elif whence == 2:
640 if self.level > 0:
650 pos = pos + self.lastpos
66n/a else:
670 raise Error, "can't use whence=2 yet"
680 if not 0 <= pos <= here or \
690 self.level > 0 and pos > self.lastpos:
700 raise Error, 'bad MultiFile.seek() call'
710 self.fp.seek(pos + self.start)
720 self.level = 0
730 self.last = 0
74n/a
751 def readline(self):
7634 if self.level > 0:
773 return ''
7831 line = self.fp.readline()
79n/a # Real EOF?
8031 if not line:
810 self.level = len(self.stack)
820 self.last = (self.level > 0)
830 if self.last:
840 raise Error, 'sudden EOF in MultiFile.readline()'
850 return ''
8631 assert self.level == 0
87n/a # Fast check to see if this is just data
8831 if self.is_data(line):
8925 return line
90n/a else:
91n/a # Ignore trailing whitespace on marker lines
926 marker = line.rstrip()
93n/a # No? OK, try to match a boundary.
94n/a # Return the line (unstripped) if we don't.
956 for i, sep in enumerate(reversed(self.stack)):
966 if marker == self.section_divider(sep):
974 self.last = 0
984 break
992 elif marker == self.end_marker(sep):
1002 self.last = 1
1012 break
102n/a else:
1030 return line
104n/a # We only get here if we see a section divider or EOM line
1056 if self.seekable:
1066 self.lastpos = self.tell() - len(line)
1076 self.level = i+1
1086 if self.level > 1:
1090 raise Error,'Missing endmarker in MultiFile.readline()'
1106 return ''
111n/a
1121 def readlines(self):
1133 list = []
1143 while 1:
11512 line = self.readline()
11612 if not line: break
1179 list.append(line)
1183 return list
119n/a
1201 def read(self): # Note: no size argument -- read until EOF only!
1210 return ''.join(self.readlines())
122n/a
1231 def next(self):
1247 while self.readline(): pass
1256 if self.level > 1 or self.last:
1262 return 0
1274 self.level = 0
1284 self.last = 0
1294 if self.seekable:
1304 self.start = self.fp.tell()
1314 return 1
132n/a
1331 def push(self, sep):
1342 if self.level > 0:
1350 raise Error, 'bad MultiFile.push() call'
1362 self.stack.append(sep)
1372 if self.seekable:
1382 self.posstack.append(self.start)
1392 self.start = self.fp.tell()
140n/a
1411 def pop(self):
1422 if self.stack == []:
1430 raise Error, 'bad MultiFile.pop() call'
1442 if self.level <= 1:
1452 self.last = 0
146n/a else:
1470 abslastpos = self.lastpos + self.start
1482 self.level = max(0, self.level - 1)
1492 self.stack.pop()
1502 if self.seekable:
1512 self.start = self.posstack.pop()
1522 if self.level > 0:
1530 self.lastpos = abslastpos - self.start
154n/a
1551 def is_data(self, line):
15631 return line[:2] != '--'
157n/a
1581 def section_divider(self, str):
1596 return "--" + str
160n/a
1611 def end_marker(self, str):
1622 return "--" + str + "--"