home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_625 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  25.1 KB  |  1,104 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from warnings import warnpy3k
  5. warnpy3k('the mhlib module has been removed in Python 3.0; use the mailbox module instead', stacklevel = 2)
  6. del warnpy3k
  7. MH_PROFILE = '~/.mh_profile'
  8. PATH = '~/Mail'
  9. MH_SEQUENCES = '.mh_sequences'
  10. FOLDER_PROTECT = 448
  11. import os
  12. import sys
  13. import re
  14. import mimetools
  15. import multifile
  16. import shutil
  17. from bisect import bisect
  18. __all__ = [
  19.     'MH',
  20.     'Error',
  21.     'Folder',
  22.     'Message']
  23.  
  24. class Error(Exception):
  25.     pass
  26.  
  27.  
  28. class MH:
  29.     
  30.     def __init__(self, path = None, profile = None):
  31.         if profile is None:
  32.             profile = MH_PROFILE
  33.         
  34.         self.profile = os.path.expanduser(profile)
  35.         if path is None:
  36.             path = self.getprofile('Path')
  37.         
  38.         if not path:
  39.             path = PATH
  40.         
  41.         if not os.path.isabs(path) and path[0] != '~':
  42.             path = os.path.join('~', path)
  43.         
  44.         path = os.path.expanduser(path)
  45.         if not os.path.isdir(path):
  46.             raise Error, 'MH() path not found'
  47.         os.path.isdir(path)
  48.         self.path = path
  49.  
  50.     
  51.     def __repr__(self):
  52.         return 'MH(%r, %r)' % (self.path, self.profile)
  53.  
  54.     
  55.     def error(self, msg, *args):
  56.         sys.stderr.write('MH error: %s\n' % msg % args)
  57.  
  58.     
  59.     def getprofile(self, key):
  60.         return pickline(self.profile, key)
  61.  
  62.     
  63.     def getpath(self):
  64.         return self.path
  65.  
  66.     
  67.     def getcontext(self):
  68.         context = pickline(os.path.join(self.getpath(), 'context'), 'Current-Folder')
  69.         if not context:
  70.             context = 'inbox'
  71.         
  72.         return context
  73.  
  74.     
  75.     def setcontext(self, context):
  76.         fn = os.path.join(self.getpath(), 'context')
  77.         f = open(fn, 'w')
  78.         f.write('Current-Folder: %s\n' % context)
  79.         f.close()
  80.  
  81.     
  82.     def listfolders(self):
  83.         folders = []
  84.         path = self.getpath()
  85.         for name in os.listdir(path):
  86.             fullname = os.path.join(path, name)
  87.             if os.path.isdir(fullname):
  88.                 folders.append(name)
  89.                 continue
  90.         
  91.         folders.sort()
  92.         return folders
  93.  
  94.     
  95.     def listsubfolders(self, name):
  96.         fullname = os.path.join(self.path, name)
  97.         nlinks = os.stat(fullname).st_nlink
  98.         if nlinks <= 2:
  99.             return []
  100.         subfolders = []
  101.         subnames = os.listdir(fullname)
  102.         for subname in subnames:
  103.             fullsubname = os.path.join(fullname, subname)
  104.             if os.path.isdir(fullsubname):
  105.                 name_subname = os.path.join(name, subname)
  106.                 subfolders.append(name_subname)
  107.                 nlinks = nlinks - 1
  108.                 if nlinks <= 2:
  109.                     break
  110.                 
  111.             nlinks <= 2
  112.         
  113.         subfolders.sort()
  114.         return subfolders
  115.  
  116.     
  117.     def listallfolders(self):
  118.         return self.listallsubfolders('')
  119.  
  120.     
  121.     def listallsubfolders(self, name):
  122.         fullname = os.path.join(self.path, name)
  123.         nlinks = os.stat(fullname).st_nlink
  124.         if nlinks <= 2:
  125.             return []
  126.         subfolders = []
  127.         subnames = os.listdir(fullname)
  128.         for subname in subnames:
  129.             if subname[0] == ',' or isnumeric(subname):
  130.                 continue
  131.             
  132.             fullsubname = os.path.join(fullname, subname)
  133.             if os.path.isdir(fullsubname):
  134.                 name_subname = os.path.join(name, subname)
  135.                 subfolders.append(name_subname)
  136.                 if not os.path.islink(fullsubname):
  137.                     subsubfolders = self.listallsubfolders(name_subname)
  138.                     subfolders = subfolders + subsubfolders
  139.                 
  140.                 nlinks = nlinks - 1
  141.                 if nlinks <= 2:
  142.                     break
  143.                 
  144.             nlinks <= 2
  145.         
  146.         subfolders.sort()
  147.         return subfolders
  148.  
  149.     
  150.     def openfolder(self, name):
  151.         return Folder(self, name)
  152.  
  153.     
  154.     def makefolder(self, name):
  155.         protect = pickline(self.profile, 'Folder-Protect')
  156.         if protect and isnumeric(protect):
  157.             mode = int(protect, 8)
  158.         else:
  159.             mode = FOLDER_PROTECT
  160.         os.mkdir(os.path.join(self.getpath(), name), mode)
  161.  
  162.     
  163.     def deletefolder(self, name):
  164.         fullname = os.path.join(self.getpath(), name)
  165.         for subname in os.listdir(fullname):
  166.             fullsubname = os.path.join(fullname, subname)
  167.             
  168.             try:
  169.                 os.unlink(fullsubname)
  170.             continue
  171.             except os.error:
  172.                 self.error('%s not deleted, continuing...' % fullsubname)
  173.                 continue
  174.             
  175.  
  176.         
  177.         os.rmdir(fullname)
  178.  
  179.  
  180. numericprog = re.compile('^[1-9][0-9]*$')
  181.  
  182. def isnumeric(str):
  183.     return numericprog.match(str) is not None
  184.  
  185.  
  186. class Folder:
  187.     
  188.     def __init__(self, mh, name):
  189.         self.mh = mh
  190.         self.name = name
  191.         if not os.path.isdir(self.getfullname()):
  192.             raise Error, 'no folder %s' % name
  193.         os.path.isdir(self.getfullname())
  194.  
  195.     
  196.     def __repr__(self):
  197.         return 'Folder(%r, %r)' % (self.mh, self.name)
  198.  
  199.     
  200.     def error(self, *args):
  201.         self.mh.error(*args)
  202.  
  203.     
  204.     def getfullname(self):
  205.         return os.path.join(self.mh.path, self.name)
  206.  
  207.     
  208.     def getsequencesfilename(self):
  209.         return os.path.join(self.getfullname(), MH_SEQUENCES)
  210.  
  211.     
  212.     def getmessagefilename(self, n):
  213.         return os.path.join(self.getfullname(), str(n))
  214.  
  215.     
  216.     def listsubfolders(self):
  217.         return self.mh.listsubfolders(self.name)
  218.  
  219.     
  220.     def listallsubfolders(self):
  221.         return self.mh.listallsubfolders(self.name)
  222.  
  223.     
  224.     def listmessages(self):
  225.         messages = []
  226.         match = numericprog.match
  227.         append = messages.append
  228.         for name in os.listdir(self.getfullname()):
  229.             if match(name):
  230.                 append(name)
  231.                 continue
  232.         
  233.         messages = map(int, messages)
  234.         messages.sort()
  235.         if messages:
  236.             self.last = messages[-1]
  237.         else:
  238.             self.last = 0
  239.         return messages
  240.  
  241.     
  242.     def getsequences(self):
  243.         sequences = { }
  244.         fullname = self.getsequencesfilename()
  245.         
  246.         try:
  247.             f = open(fullname, 'r')
  248.         except IOError:
  249.             return sequences
  250.  
  251.         while None:
  252.             line = f.readline()
  253.             if not line:
  254.                 break
  255.             
  256.             fields = line.split(':')
  257.             if len(fields) != 2:
  258.                 self.error('bad sequence in %s: %s' % (fullname, line.strip()))
  259.             
  260.             key = fields[0].strip()
  261.             value = IntSet(fields[1].strip(), ' ').tolist()
  262.             sequences[key] = value
  263.             continue
  264.             return sequences
  265.  
  266.     
  267.     def putsequences(self, sequences):
  268.         fullname = self.getsequencesfilename()
  269.         f = None
  270.         for key, seq in sequences.iteritems():
  271.             s = IntSet('', ' ')
  272.             s.fromlist(seq)
  273.             if not f:
  274.                 f = open(fullname, 'w')
  275.             
  276.             f.write('%s: %s\n' % (key, s.tostring()))
  277.         
  278.         if not f:
  279.             
  280.             try:
  281.                 os.unlink(fullname)
  282.             except os.error:
  283.                 pass
  284.             except:
  285.                 None<EXCEPTION MATCH>os.error
  286.             
  287.  
  288.         None<EXCEPTION MATCH>os.error
  289.         f.close()
  290.  
  291.     
  292.     def getcurrent(self):
  293.         seqs = self.getsequences()
  294.         
  295.         try:
  296.             return max(seqs['cur'])
  297.         except (ValueError, KeyError):
  298.             raise Error, 'no cur message'
  299.  
  300.  
  301.     
  302.     def setcurrent(self, n):
  303.         updateline(self.getsequencesfilename(), 'cur', str(n), 0)
  304.  
  305.     
  306.     def parsesequence(self, seq):
  307.         all = self.listmessages()
  308.         if not all:
  309.             raise Error, 'no messages in %s' % self.name
  310.         all
  311.         if seq == 'all':
  312.             return all
  313.         i = seq.find(':')
  314.         if i >= 0:
  315.             head = seq[:i]
  316.             dir = ''
  317.             tail = seq[i + 1:]
  318.             if tail[:1] in '-+':
  319.                 dir = tail[:1]
  320.                 tail = tail[1:]
  321.             
  322.             if not isnumeric(tail):
  323.                 raise Error, 'bad message list %s' % seq
  324.             isnumeric(tail)
  325.             
  326.             try:
  327.                 count = int(tail)
  328.             except (ValueError, OverflowError):
  329.                 count = len(all)
  330.  
  331.             
  332.             try:
  333.                 anchor = self._parseindex(head, all)
  334.             except Error:
  335.                 msg = None
  336.                 seqs = self.getsequences()
  337.                 if head not in seqs:
  338.                     if not msg:
  339.                         msg = 'bad message list %s' % seq
  340.                     
  341.                     raise Error, msg, sys.exc_info()[2]
  342.                 head not in seqs
  343.                 msgs = seqs[head]
  344.                 if not msgs:
  345.                     raise Error, 'sequence %s empty' % head
  346.                 msgs
  347.                 if dir == '-':
  348.                     return msgs[-count:]
  349.                 return msgs[:count]
  350.  
  351.             if not dir:
  352.                 if head in ('prev', 'last'):
  353.                     dir = '-'
  354.                 
  355.             
  356.             if dir == '-':
  357.                 i = bisect(all, anchor)
  358.                 return all[max(0, i - count):i]
  359.             i = bisect(all, anchor - 1)
  360.             return all[i:i + count]
  361.         i >= 0
  362.         i = seq.find('-')
  363.         if i >= 0:
  364.             begin = self._parseindex(seq[:i], all)
  365.             end = self._parseindex(seq[i + 1:], all)
  366.             i = bisect(all, begin - 1)
  367.             j = bisect(all, end)
  368.             r = all[i:j]
  369.             if not r:
  370.                 raise Error, 'bad message list %s' % seq
  371.             r
  372.             return r
  373.         
  374.         try:
  375.             n = self._parseindex(seq, all)
  376.         except Error:
  377.             i >= 0
  378.             msg = i >= 0
  379.             seq == 'all'
  380.             seqs = self.getsequences()
  381.             if seq not in seqs:
  382.                 if not msg:
  383.                     msg = 'bad message list %s' % seq
  384.                 
  385.                 raise Error, msg
  386.             seq not in seqs
  387.             return seqs[seq]
  388.  
  389.         if n not in all:
  390.             if isnumeric(seq):
  391.                 raise Error, "message %d doesn't exist" % n
  392.             isnumeric(seq)
  393.             raise Error, 'no %s message' % seq
  394.         n not in all
  395.         return [
  396.             n]
  397.  
  398.     
  399.     def _parseindex(self, seq, all):
  400.         if isnumeric(seq):
  401.             
  402.             try:
  403.                 return int(seq)
  404.             except (OverflowError, ValueError):
  405.                 return sys.maxint
  406.             
  407.  
  408.         None<EXCEPTION MATCH>(OverflowError, ValueError)
  409.         if seq in ('cur', '.'):
  410.             return self.getcurrent()
  411.         if seq == 'first':
  412.             return all[0]
  413.         if seq == 'last':
  414.             return all[-1]
  415.         if seq == 'next':
  416.             n = self.getcurrent()
  417.             i = bisect(all, n)
  418.             
  419.             try:
  420.                 return all[i]
  421.             except IndexError:
  422.                 seq == 'last'
  423.                 seq == 'last'
  424.                 seq == 'first'
  425.                 raise Error, 'no next message'
  426.             except:
  427.                 seq == 'last'<EXCEPTION MATCH>IndexError
  428.             
  429.  
  430.         seq == 'last'
  431.         if seq == 'prev':
  432.             n = self.getcurrent()
  433.             i = bisect(all, n - 1)
  434.             if i == 0:
  435.                 raise Error, 'no prev message'
  436.             i == 0
  437.             
  438.             try:
  439.                 return all[i - 1]
  440.             except IndexError:
  441.                 seq == 'last'
  442.                 seq == 'last'
  443.                 seq == 'first'
  444.                 raise Error, 'no prev message'
  445.             except:
  446.                 seq == 'last'<EXCEPTION MATCH>IndexError
  447.             
  448.  
  449.         seq == 'last'
  450.         raise Error, None
  451.  
  452.     
  453.     def openmessage(self, n):
  454.         return Message(self, n)
  455.  
  456.     
  457.     def removemessages(self, list):
  458.         errors = []
  459.         deleted = []
  460.         for n in list:
  461.             path = self.getmessagefilename(n)
  462.             commapath = self.getmessagefilename(',' + str(n))
  463.             
  464.             try:
  465.                 os.unlink(commapath)
  466.             except os.error:
  467.                 pass
  468.  
  469.             
  470.             try:
  471.                 os.rename(path, commapath)
  472.             except os.error:
  473.                 msg = None
  474.                 errors.append(msg)
  475.                 continue
  476.  
  477.             deleted.append(n)
  478.         
  479.         if deleted:
  480.             self.removefromallsequences(deleted)
  481.         
  482.         if errors:
  483.             if len(errors) == 1:
  484.                 raise os.error, errors[0]
  485.             len(errors) == 1
  486.             raise os.error, ('multiple errors:', errors)
  487.         errors
  488.  
  489.     
  490.     def refilemessages(self, list, tofolder, keepsequences = 0):
  491.         errors = []
  492.         refiled = { }
  493.         for n in list:
  494.             ton = tofolder.getlast() + 1
  495.             path = self.getmessagefilename(n)
  496.             topath = tofolder.getmessagefilename(ton)
  497.             
  498.             try:
  499.                 os.rename(path, topath)
  500.             except os.error:
  501.                 
  502.                 try:
  503.                     shutil.copy2(path, topath)
  504.                     os.unlink(path)
  505.                 except (IOError, os.error):
  506.                     msg = None
  507.                     errors.append(msg)
  508.                     
  509.                     try:
  510.                         os.unlink(topath)
  511.                     continue
  512.                     except os.error:
  513.                         continue
  514.                     
  515.  
  516.                 except:
  517.                     None<EXCEPTION MATCH>(IOError, os.error)
  518.                 
  519.  
  520.                 None<EXCEPTION MATCH>(IOError, os.error)
  521.  
  522.             tofolder.setlast(ton)
  523.             refiled[n] = ton
  524.         
  525.         if refiled:
  526.             if keepsequences:
  527.                 tofolder._copysequences(self, refiled.items())
  528.             
  529.             self.removefromallsequences(refiled.keys())
  530.         
  531.         if errors:
  532.             if len(errors) == 1:
  533.                 raise os.error, errors[0]
  534.             len(errors) == 1
  535.             raise os.error, ('multiple errors:', errors)
  536.         errors
  537.  
  538.     
  539.     def _copysequences(self, fromfolder, refileditems):
  540.         fromsequences = fromfolder.getsequences()
  541.         tosequences = self.getsequences()
  542.         changed = 0
  543.         for name, seq in fromsequences.items():
  544.             
  545.             try:
  546.                 toseq = tosequences[name]
  547.                 new = 0
  548.             except KeyError:
  549.                 toseq = []
  550.                 new = 1
  551.  
  552.             for fromn, ton in refileditems:
  553.                 if fromn in seq:
  554.                     toseq.append(ton)
  555.                     changed = 1
  556.                     continue
  557.             
  558.             if new and toseq:
  559.                 tosequences[name] = toseq
  560.                 continue
  561.         
  562.         if changed:
  563.             self.putsequences(tosequences)
  564.         
  565.  
  566.     
  567.     def movemessage(self, n, tofolder, ton):
  568.         path = self.getmessagefilename(n)
  569.         f = open(path)
  570.         f.close()
  571.         del f
  572.         topath = tofolder.getmessagefilename(ton)
  573.         backuptopath = tofolder.getmessagefilename(',%d' % ton)
  574.         
  575.         try:
  576.             os.rename(topath, backuptopath)
  577.         except os.error:
  578.             pass
  579.  
  580.         
  581.         try:
  582.             os.rename(path, topath)
  583.         except os.error:
  584.             ok = 0
  585.             
  586.             try:
  587.                 tofolder.setlast(None)
  588.                 shutil.copy2(path, topath)
  589.                 ok = 1
  590.             finally:
  591.                 if not ok:
  592.                     
  593.                     try:
  594.                         os.unlink(topath)
  595.                     except os.error:
  596.                         pass
  597.                     except:
  598.                         None<EXCEPTION MATCH>os.error
  599.                     
  600.  
  601.  
  602.             os.unlink(path)
  603.  
  604.         self.removefromallsequences([
  605.             n])
  606.  
  607.     
  608.     def copymessage(self, n, tofolder, ton):
  609.         path = self.getmessagefilename(n)
  610.         f = open(path)
  611.         f.close()
  612.         del f
  613.         topath = tofolder.getmessagefilename(ton)
  614.         backuptopath = tofolder.getmessagefilename(',%d' % ton)
  615.         
  616.         try:
  617.             os.rename(topath, backuptopath)
  618.         except os.error:
  619.             pass
  620.  
  621.         ok = 0
  622.         
  623.         try:
  624.             tofolder.setlast(None)
  625.             shutil.copy2(path, topath)
  626.             ok = 1
  627.         finally:
  628.             if not ok:
  629.                 
  630.                 try:
  631.                     os.unlink(topath)
  632.                 except os.error:
  633.                     pass
  634.                 except:
  635.                     None<EXCEPTION MATCH>os.error
  636.                 
  637.  
  638.  
  639.  
  640.     
  641.     def createmessage(self, n, txt):
  642.         path = self.getmessagefilename(n)
  643.         backuppath = self.getmessagefilename(',%d' % n)
  644.         
  645.         try:
  646.             os.rename(path, backuppath)
  647.         except os.error:
  648.             pass
  649.  
  650.         ok = 0
  651.         BUFSIZE = 16384
  652.         
  653.         try:
  654.             f = open(path, 'w')
  655.             while None:
  656.                 buf = txt.read(BUFSIZE)
  657.                 if not buf:
  658.                     break
  659.                 
  660.                 continue
  661.                 f.close()
  662.                 ok = 1
  663.             if not ok:
  664.                 
  665.                 try:
  666.                     os.unlink(path)
  667.                 except os.error:
  668.                     pass
  669.                 except:
  670.                     None<EXCEPTION MATCH>os.error
  671.                 
  672.  
  673.             return None
  674.  
  675.  
  676.     
  677.     def removefromallsequences(self, list):
  678.         if hasattr(self, 'last') and self.last in list:
  679.             del self.last
  680.         
  681.         sequences = self.getsequences()
  682.         changed = 0
  683.         for name, seq in sequences.items():
  684.             if name == 'cur':
  685.                 continue
  686.             
  687.             for n in list:
  688.                 if n in seq:
  689.                     seq.remove(n)
  690.                     changed = 1
  691.                     if not seq:
  692.                         del sequences[name]
  693.                     
  694.                 seq
  695.             
  696.         
  697.         if changed:
  698.             self.putsequences(sequences)
  699.         
  700.  
  701.     
  702.     def getlast(self):
  703.         if not hasattr(self, 'last'):
  704.             self.listmessages()
  705.         
  706.         return self.last
  707.  
  708.     
  709.     def setlast(self, last):
  710.         if last is None:
  711.             if hasattr(self, 'last'):
  712.                 del self.last
  713.             
  714.         else:
  715.             self.last = last
  716.  
  717.  
  718.  
  719. class Message(mimetools.Message):
  720.     
  721.     def __init__(self, f, n, fp = None):
  722.         self.folder = f
  723.         self.number = n
  724.         if fp is None:
  725.             path = f.getmessagefilename(n)
  726.             fp = open(path, 'r')
  727.         
  728.         mimetools.Message.__init__(self, fp)
  729.  
  730.     
  731.     def __repr__(self):
  732.         return 'Message(%s, %s)' % (repr(self.folder), self.number)
  733.  
  734.     
  735.     def getheadertext(self, pred = None):
  736.         if pred is None:
  737.             return ''.join(self.headers)
  738.         headers = []
  739.         hit = 0
  740.         for line in self.headers:
  741.             if not line[0].isspace():
  742.                 i = line.find(':')
  743.                 if i > 0:
  744.                     hit = pred(line[:i].lower())
  745.                 
  746.             
  747.             if hit:
  748.                 headers.append(line)
  749.                 continue
  750.         
  751.         return ''.join(headers)
  752.  
  753.     
  754.     def getbodytext(self, decode = 1):
  755.         self.fp.seek(self.startofbody)
  756.         encoding = self.getencoding()
  757.         if not decode or encoding in ('', '7bit', '8bit', 'binary'):
  758.             return self.fp.read()
  759.         
  760.         try:
  761.             StringIO = StringIO
  762.             import cStringIO
  763.         except ImportError:
  764.             encoding in ('', '7bit', '8bit', 'binary')
  765.             encoding in ('', '7bit', '8bit', 'binary')
  766.             StringIO = StringIO
  767.             import StringIO
  768.         except:
  769.             encoding in ('', '7bit', '8bit', 'binary')
  770.  
  771.         output = StringIO()
  772.         mimetools.decode(self.fp, output, encoding)
  773.         return output.getvalue()
  774.  
  775.     
  776.     def getbodyparts(self):
  777.         if self.getmaintype() != 'multipart':
  778.             raise Error, 'Content-Type is not multipart/*'
  779.         self.getmaintype() != 'multipart'
  780.         bdry = self.getparam('boundary')
  781.         if not bdry:
  782.             raise Error, 'multipart/* without boundary param'
  783.         bdry
  784.         self.fp.seek(self.startofbody)
  785.         mf = multifile.MultiFile(self.fp)
  786.         mf.push(bdry)
  787.         parts = []
  788.         while mf.next():
  789.             n = '%s.%r' % (self.number, 1 + len(parts))
  790.             part = SubMessage(self.folder, n, mf)
  791.             parts.append(part)
  792.         mf.pop()
  793.         return parts
  794.  
  795.     
  796.     def getbody(self):
  797.         if self.getmaintype() == 'multipart':
  798.             return self.getbodyparts()
  799.         return self.getbodytext()
  800.  
  801.  
  802.  
  803. class SubMessage(Message):
  804.     
  805.     def __init__(self, f, n, fp):
  806.         Message.__init__(self, f, n, fp)
  807.         if self.getmaintype() == 'multipart':
  808.             self.body = Message.getbodyparts(self)
  809.         else:
  810.             self.body = Message.getbodytext(self)
  811.         self.bodyencoded = Message.getbodytext(self, decode = 0)
  812.  
  813.     
  814.     def __repr__(self):
  815.         f = self.folder
  816.         n = self.number
  817.         fp = self.fp
  818.         return 'SubMessage(%s, %s, %s)' % (f, n, fp)
  819.  
  820.     
  821.     def getbodytext(self, decode = 1):
  822.         if not decode:
  823.             return self.bodyencoded
  824.         if type(self.body) == type(''):
  825.             return self.body
  826.  
  827.     
  828.     def getbodyparts(self):
  829.         if type(self.body) == type([]):
  830.             return self.body
  831.  
  832.     
  833.     def getbody(self):
  834.         return self.body
  835.  
  836.  
  837.  
  838. class IntSet:
  839.     
  840.     def __init__(self, data = None, sep = ',', rng = '-'):
  841.         self.pairs = []
  842.         self.sep = sep
  843.         self.rng = rng
  844.         if data:
  845.             self.fromstring(data)
  846.         
  847.  
  848.     
  849.     def reset(self):
  850.         self.pairs = []
  851.  
  852.     
  853.     def __cmp__(self, other):
  854.         return cmp(self.pairs, other.pairs)
  855.  
  856.     
  857.     def __hash__(self):
  858.         return hash(self.pairs)
  859.  
  860.     
  861.     def __repr__(self):
  862.         return 'IntSet(%r, %r, %r)' % (self.tostring(), self.sep, self.rng)
  863.  
  864.     
  865.     def normalize(self):
  866.         self.pairs.sort()
  867.         i = 1
  868.         while i < len(self.pairs):
  869.             (alo, ahi) = self.pairs[i - 1]
  870.             (blo, bhi) = self.pairs[i]
  871.             if ahi >= blo - 1:
  872.                 self.pairs[i - 1:i + 1] = [
  873.                     (alo, max(ahi, bhi))]
  874.                 continue
  875.             i = i + 1
  876.  
  877.     
  878.     def tostring(self):
  879.         s = ''
  880.         for lo, hi in self.pairs:
  881.             if lo == hi:
  882.                 t = repr(lo)
  883.             else:
  884.                 t = repr(lo) + self.rng + repr(hi)
  885.             if s:
  886.                 s = s + self.sep + t
  887.                 continue
  888.             s = t
  889.         
  890.         return s
  891.  
  892.     
  893.     def tolist(self):
  894.         l = []
  895.         for lo, hi in self.pairs:
  896.             m = range(lo, hi + 1)
  897.             l = l + m
  898.         
  899.         return l
  900.  
  901.     
  902.     def fromlist(self, list):
  903.         for i in list:
  904.             self.append(i)
  905.         
  906.  
  907.     
  908.     def clone(self):
  909.         new = IntSet()
  910.         new.pairs = self.pairs[:]
  911.         return new
  912.  
  913.     
  914.     def min(self):
  915.         return self.pairs[0][0]
  916.  
  917.     
  918.     def max(self):
  919.         return self.pairs[-1][-1]
  920.  
  921.     
  922.     def contains(self, x):
  923.         for lo, hi in self.pairs:
  924.             if x <= x:
  925.                 pass
  926.             elif x <= hi:
  927.                 return True
  928.         
  929.         return False
  930.  
  931.     
  932.     def append(self, x):
  933.         for i in range(len(self.pairs)):
  934.             (lo, hi) = self.pairs[i]
  935.             if x < lo:
  936.                 if x + 1 == lo:
  937.                     self.pairs[i] = (x, hi)
  938.                 else:
  939.                     self.pairs.insert(i, (x, x))
  940.                 if i > 0 and x - 1 == self.pairs[i - 1][1]:
  941.                     self.pairs[i - 1:i + 1] = [
  942.                         (self.pairs[i - 1][0], self.pairs[i][1])]
  943.                 
  944.                 return None
  945.             if x <= hi:
  946.                 return None
  947.         
  948.         i = len(self.pairs) - 1
  949.         self.pairs.append((x, x))
  950.  
  951.     
  952.     def addpair(self, xlo, xhi):
  953.         if xlo > xhi:
  954.             return None
  955.         self.pairs.append((xlo, xhi))
  956.         self.normalize()
  957.  
  958.     
  959.     def fromstring(self, data):
  960.         new = []
  961.         for part in data.split(self.sep):
  962.             list = []
  963.             for subp in part.split(self.rng):
  964.                 s = subp.strip()
  965.                 list.append(int(s))
  966.             
  967.             if len(list) == 1:
  968.                 new.append((list[0], list[0]))
  969.                 continue
  970.             if len(list) == 2 and list[0] <= list[1]:
  971.                 new.append((list[0], list[1]))
  972.                 continue
  973.             raise ValueError, 'bad data passed to IntSet'
  974.         
  975.         self.pairs = self.pairs + new
  976.         self.normalize()
  977.  
  978.  
  979.  
  980. def pickline(file, key, casefold = 1):
  981.     
  982.     try:
  983.         f = open(file, 'r')
  984.     except IOError:
  985.         return None
  986.  
  987.     pat = re.escape(key) + ':'
  988.     if casefold:
  989.         pass
  990.     prog = re.compile(pat, re.IGNORECASE)
  991.     while None:
  992.         line = f.readline()
  993.         if not line:
  994.             break
  995.         
  996.         if prog.match(line):
  997.             text = line[len(key) + 1:]
  998.             while None:
  999.                 line = f.readline()
  1000.                 if not line or not line[0].isspace():
  1001.                     break
  1002.                 
  1003.                 text = text + line
  1004.                 continue
  1005.                 return text.strip()
  1006.                 continue
  1007.                 return None
  1008.  
  1009.  
  1010. def updateline(file, key, value, casefold = 1):
  1011.     
  1012.     try:
  1013.         f = open(file, 'r')
  1014.         lines = f.readlines()
  1015.         f.close()
  1016.     except IOError:
  1017.         lines = []
  1018.  
  1019.     pat = re.escape(key) + ':(.*)\n'
  1020.     if casefold:
  1021.         pass
  1022.     prog = re.compile(pat, re.IGNORECASE)
  1023.     if value is None:
  1024.         newline = None
  1025.     else:
  1026.         newline = '%s: %s\n' % (key, value)
  1027.     for i in range(len(lines)):
  1028.         line = lines[i]
  1029.         if prog.match(line):
  1030.             if newline is None:
  1031.                 del lines[i]
  1032.             else:
  1033.                 lines[i] = newline
  1034.             break
  1035.             continue
  1036.     elif newline is not None:
  1037.         lines.append(newline)
  1038.     
  1039.     tempfile = file + '~'
  1040.     f = open(tempfile, 'w')
  1041.     for line in lines:
  1042.         f.write(line)
  1043.     
  1044.     f.close()
  1045.     os.rename(tempfile, file)
  1046.  
  1047.  
  1048. def test():
  1049.     global mh, f, f
  1050.     os.system('rm -rf $HOME/Mail/@test')
  1051.     mh = MH()
  1052.     
  1053.     def do(s):
  1054.         print s
  1055.         print eval(s)
  1056.  
  1057.     do('mh.listfolders()')
  1058.     do('mh.listallfolders()')
  1059.     testfolders = [
  1060.         '@test',
  1061.         '@test/test1',
  1062.         '@test/test2',
  1063.         '@test/test1/test11',
  1064.         '@test/test1/test12',
  1065.         '@test/test1/test11/test111']
  1066.     for t in testfolders:
  1067.         do('mh.makefolder(%r)' % (t,))
  1068.     
  1069.     do("mh.listsubfolders('@test')")
  1070.     do("mh.listallsubfolders('@test')")
  1071.     f = mh.openfolder('@test')
  1072.     do('f.listsubfolders()')
  1073.     do('f.listallsubfolders()')
  1074.     do('f.getsequences()')
  1075.     seqs = f.getsequences()
  1076.     seqs['foo'] = IntSet('1-10 12-20', ' ').tolist()
  1077.     print seqs
  1078.     f.putsequences(seqs)
  1079.     do('f.getsequences()')
  1080.     for t in reversed(testfolders):
  1081.         do('mh.deletefolder(%r)' % (t,))
  1082.     
  1083.     do('mh.getcontext()')
  1084.     context = mh.getcontext()
  1085.     f = mh.openfolder(context)
  1086.     do('f.getcurrent()')
  1087.     for seq in ('first', 'last', 'cur', '.', 'prev', 'next', 'first:3', 'last:3', 'cur:3', 'cur:-3', 'prev:3', 'next:3', '1:3', '1:-3', '100:3', '100:-3', '10000:3', '10000:-3', 'all'):
  1088.         
  1089.         try:
  1090.             do('f.parsesequence(%r)' % (seq,))
  1091.         except Error:
  1092.             msg = None
  1093.             print 'Error:', msg
  1094.  
  1095.         stuff = os.popen('pick %r 2>/dev/null' % (seq,)).read()
  1096.         list = map(int, stuff.split())
  1097.         print list, '<-- pick'
  1098.     
  1099.     do('f.listmessages()')
  1100.  
  1101. if __name__ == '__main__':
  1102.     test()
  1103.  
  1104.