o
    p̦i3                    @   s>  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Zddl
ZddlZddlZddlmZ zddlZW n eyI   dZY nw g dZejdZG dd dZG dd	 d	eZG d
d deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd dejjZG dd deZG dd deZG dd deZ G dd deZ!G d d! d!eZ"G d"d# d#eZ#G d$d% d%Z$G d&d' d'e$Z%d?d)d*Z&d+d, Z'd-d. Z(d/d0 Z)d1d2 Z*d3d4 Z+G d5d6 d6e,Z-G d7d8 d8e-Z.G d9d: d:e-Z/G d;d< d<e-Z0G d=d> d>e-Z1dS )@zDRead/write support for Maildir, mbox, MH, Babyl, and MMDF mailboxes.    N)GenericAlias)MailboxMaildirmboxMHBabylMMDFMessageMaildirMessagemboxMessage	MHMessageBabylMessageMMDFMessageErrorNoSuchMailboxErrorNotEmptyErrorExternalClashErrorFormatErrorasciic                   @   s  e Zd ZdZdCddZdd Zdd	 Zd
d Zdd Zdd Z	dDddZ
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ ZdDd0d1Zd2d3 ZdDd4d5Zd6d7 Zd8d9 Zd:d; Zd<d= Z d>d? Z!d@Z"dEdAdBZ#e$e%Z&dS )Fr   z*A group of messages in a particular place.NTc                 C   s    t jt j|| _|| _dS )zInitialize a Mailbox instance.N)ospathabspath
expanduser_path_factoryselfr   factorycreate r   /usr/lib/python3.10/mailbox.py__init__%   s   
zMailbox.__init__c                 C      t d)$Add message and return assigned key.&Method must be implemented by subclassNotImplementedErrorr   messager   r   r    add*      zMailbox.addc                 C   r"   )=Remove the keyed message; raise KeyError if it doesn't exist.r$   r%   r   keyr   r   r    remove.   r*   zMailbox.removec                 C   s   |  | d S N)r.   r,   r   r   r    __delitem__2   s   zMailbox.__delitem__c                 C   s&   z|  | W dS  ty   Y dS w z'If the keyed message exists, remove it.N)r.   KeyErrorr,   r   r   r    discard5   s
   zMailbox.discardc                 C   r"   )>Replace the keyed message; raise KeyError if it doesn't exist.r$   r%   r   r-   r(   r   r   r    __setitem__<   r*   zMailbox.__setitem__c                 C   s$   z|  |W S  ty   | Y S w )z9Return the keyed message, or default if it doesn't exist.)__getitem__r2   )r   r-   defaultr   r   r    get@   s
   zMailbox.getc                 C   sN   | j s| |S t| |}|  |W  d   S 1 s w   Y  dS )z=Return the keyed message; raise KeyError if it doesn't exist.N)r   get_message
contextlibclosingget_file)r   r-   filer   r   r    r7   G   s
   
$zMailbox.__getitem__c                 C   r"   )4Return a Message representation or raise a KeyError.r$   r%   r,   r   r   r    r:   O   r*   zMailbox.get_messagec                 C   s   t | | S )zReturn a string representation or raise a KeyError.

        Uses email.message.Message to create a 7bit clean string
        representation of the message.emailmessage_from_bytes	get_bytes	as_stringr,   r   r   r    
get_stringS   s   zMailbox.get_stringc                 C   r"   )z8Return a byte string representation or raise a KeyError.r$   r%   r,   r   r   r    rC   Z   r*   zMailbox.get_bytesc                 C   r"   )6Return a file-like representation or raise a KeyError.r$   r%   r,   r   r   r    r=   ^   r*   zMailbox.get_filec                 C   r"   )Return an iterator over keys.r$   r%   r   r   r   r    iterkeysb   r*   zMailbox.iterkeysc                 C      t |  S )zReturn a list of keys.)listrI   rH   r   r   r    keysf      zMailbox.keysc              	   c   s:    |   D ]}z| | }W n	 ty   Y qw |V  qdS )z%Return an iterator over all messages.NrI   r2   r   r-   valuer   r   r    
itervaluesj   s   zMailbox.itervaluesc                 C   s   |   S r/   )rQ   rH   r   r   r    __iter__s   s   zMailbox.__iter__c                 C   rJ   )z,Return a list of messages. Memory intensive.)rK   rQ   rH   r   r   r    valuesv   rM   zMailbox.valuesc              	   c   s>    |   D ]}z| | }W n	 ty   Y qw ||fV  qdS )z.Return an iterator over (key, message) tuples.NrN   rO   r   r   r    	iteritemsz   s   zMailbox.iteritemsc                 C   rJ   )z9Return a list of (key, message) tuples. Memory intensive.)rK   rT   rH   r   r   r    items   rM   zMailbox.itemsc                 C   r"   )9Return True if the keyed message exists, False otherwise.r$   r%   r,   r   r   r    __contains__   r*   zMailbox.__contains__c                 C   r"   )*Return a count of messages in the mailbox.r$   r%   rH   r   r   r    __len__   r*   zMailbox.__len__c                 C   s   |   D ]}| | qdS )zDelete all messages.N)rL   r3   r,   r   r   r    clear   s   zMailbox.clearc                 C   s2   z| | }W n t y   | Y S w | | |S )z3Delete the keyed message and return it, or default.)r2   r3   )r   r-   r8   resultr   r   r    pop   s   
zMailbox.popc                 C   s&   |   D ]
}|| |f  S td)z6Delete an arbitrary (key, message) pair and return it.zNo messages in mailbox)rI   r\   r2   r,   r   r   r    popitem   s   zMailbox.popitemc              	   C   sp   t |dr
| }nt |dr| }n|}d}|D ]\}}z|| |< W q ty/   d}Y qw |r6tddS )z4Change the messages that correspond to certain keys.rT   rU   FTzNo message with key(s)N)hasattrrT   rU   r2   )r   argsourcebad_keyr-   r(   r   r   r    update   s   



zMailbox.updatec                 C   r"   )&Write any pending changes to the disk.r$   r%   rH   r   r   r    flush   r*   zMailbox.flushc                 C   r"   )Lock the mailbox.r$   r%   rH   r   r   r    lock   r*   zMailbox.lockc                 C   r"   )#Unlock the mailbox if it is locked.r$   r%   rH   r   r   r    unlock   r*   zMailbox.unlockc                 C   r"   )Flush and close the mailbox.r$   r%   rH   r   r   r    close   r*   zMailbox.closec                 C   s$   z| dW S  ty   tdw )Nr   z?String input must be ASCII-only; use bytes or a Message instead)encodeUnicodeError
ValueErrorr'   r   r   r    _string_to_bytes   s
   zMailbox._string_to_bytesFc           	      C   s  t |tjjr?t }tj||d}|| |	d |
 }|dt}|| | jr;|ts=|t d
S d
S d
S t |tttjfrt |tjrYtdtd | }t |trc| |}|rk|dd}|dt}|| | jr|ts|t d
S d
S d
S t|drt|drtd	td |j}d
}	 | }|dr|d
d d }n|dr|d
d d }|sn|r|drd|dd
  }|dt}|| |}q| jr|r|ts|t d
S d
S d
S d
S tdt| )z%Dump message contents to target file.r      
8Use of StringIO input is deprecated, use BytesIO instead   s   
From s   
>From readbufferDUse of text mode files is deprecated, use a binary mode file insteadNT   
      From s   >From    Invalid message type: %s)
isinstancerA   r(   r	   ioBytesIO	generatorBytesGeneratorflattenseekrr   replacelinesepwrite_append_newlineendswithstrbytesStringIOwarningswarnDeprecationWarninggetvaluern   r^   rs   readline
startswith	TypeErrortype)	r   r(   targetmangle_from_rs   gendatalastlineliner   r   r    _dump_message   sf   










zMailbox._dump_messageNTr/   F)'__name__
__module____qualname____doc__r!   r)   r.   r0   r3   r6   r9   r7   r:   rE   rC   r=   rI   rL   rQ   rR   rS   rT   rU   rW   rY   rZ   r\   r]   rb   rd   rf   rh   rj   rn   r   r   classmethodr   __class_getitem__r   r   r   r    r   "   sF    

		
	

6r   c                   @   s   e Zd ZdZdZd6ddZdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-Zd.d/ Zd0d1 Zd2d3 Zd4d5 ZdS )7r   zA qmail-style Maildir mailbox.:NTc                 C   s   t | ||| tj| jdtj| jdtj| jdd| _tj| jsE|r@t| jd | j	 D ]}t|d q6nt
| ji | _ddd| _d| _d| _d	S )
zInitialize a Maildir instance.tmpnewcur)r   r   r     r   )r   r   g?N)r   r!   r   r   joinr   _pathsexistsmkdirrS   r   _toc_toc_mtimes
_last_read_skewfactor)r   dirnamer   r   r   r   r   r    r!     s    

zMaildir.__init__c              
   C   sf  |   }z| || W n ty   |  t|j  w t| t|t	r;|
 }| j|  }|| jkr:d}nd}d}tj|j| jd }tj| j||| }t|t	rlt|jtj|j| f z'z	t|j| W n ttfy   t|j| Y W |S w t|j W |S  ty } zt|j |jtjkrtd|  d}~ww )r#    r   r   z$Name clash with existing message: %sN)_create_tmpr   BaseExceptionrj   r   r.   name_sync_closer|   r
   
get_subdircolonget_infor   basenamesplitr   r   utimegetatimeget_datelinkAttributeErrorPermissionErrorrenameOSErrorerrnoEEXISTr   )r   r(   tmp_filesubdirsuffixuniqdester   r   r    r)   $  sR   



zMaildir.addc                 C   s    t t j| j| | dS r+   N)r   r.   r   r   r   _lookupr,   r   r   r    r.   N  s    zMaildir.removec              	   C   s*   z|  | W dS  ttfy   Y dS w r1   )r.   r2   FileNotFoundErrorr,   r   r   r    r3   R  s
   zMaildir.discardc                 C   s   |  |}| |}|  |}t|tr|}n|}tj|}| j|v r0| j|| jd  }nd}| 	| tj
| j|}	tj
| j||| }
t|tr]t|	tj|	| f t|	|
 dS )r4   rx   r   N)r   r)   r|   r
   r   r   r   r   r   r3   r   r   r   r   r   r   )r   r-   r(   old_subpathtemp_keytemp_subpathdominant_subpathr   r   tmp_pathnew_pathr   r   r    r6   Z  s$   






zMaildir.__setitem__c                 C   s   |  |}ttj| j|d}| jr| |}nt|}W d   n1 s(w   Y  tj|\}}|	| | j
|v rJ||| j
d  |tjtj| j| |S )r?   rbNrx   )r   openr   r   r   r   r   r
   r   
set_subdirr   set_infoset_dategetmtime)r   r-   subpathfmsgr   r   r   r   r    r:   u  s   


zMaildir.get_messagec                 C   sP   t tj| j| |d}| tdW  d   S 1 s!w   Y  dS )2Return a bytes representation or raise a KeyError.r   ro   N)	r   r   r   r   r   r   rr   r   r   r   r-   r   r   r   r    rC     s   $zMaildir.get_bytesc                 C   s$   t tj| j| |d}t|S )rF   r   )r   r   r   r   r   r   
_ProxyFiler   r   r   r    r=     s   zMaildir.get_filec              	   c   sB    |    | jD ]}z| | W n	 ty   Y qw |V  qdS rG   N)_refreshr   r   r2   r,   r   r   r    rI     s   
zMaildir.iterkeysc                 C      |    || jv S rV   )r   r   r,   r   r   r    rW        
zMaildir.__contains__c                 C      |    t| jS rX   )r   lenr   rH   r   r   r    rY     r   zMaildir.__len__c                 C      dS )"Write any pending changes to disk.Nr   rH   r   r   r    rd     s   zMaildir.flushc                 C   r   )re   Nr   rH   r   r   r    rf        zMaildir.lockc                 C   r   )rg   Nr   rH   r   r   r    rh     r   zMaildir.unlockc                 C   r   ri   Nr   rH   r   r   r    rj     r   zMaildir.closec                 C   s\   g }t | jD ]#}t|dkr+|d dkr+t jt j| j|r+||dd  q|S )Return a list of folder names.   r   .N)r   listdirr   r   r   isdirr   appendr   r[   entryr   r   r    list_folders  s   zMaildir.list_foldersc                 C   s    t tj| jd| | jddS )z/Return a Maildir instance for the named folder.r   Fr   r   )r   r   r   r   r   r   r   folderr   r   r    
get_folder  s   zMaildir.get_folderc                 C   s\   t j| jd| }t|| jd}t j|d}t j|s,t t |t j	t j
B d |S )z>Create a folder and return a Maildir instance representing it.r   r   maildirfolder  )r   r   r   r   r   r   r   rj   r   O_CREATO_WRONLY)r   r   r   r[   maildirfolder_pathr   r   r    
add_folder  s   zMaildir.add_folderc                 C   s  t j| jd| }t t j|dt t j|d D ]}t|dk s,|d dkr2td| qt |D ]!}|dkrY|dkrY|dkrYt jt j||rYtd||f q8t j|d	d
D ]#\}}}|D ]}t 	t j|| qh|D ]}t 
t j|| qwqat 
| dS )-Delete the named folder, which must be empty.r   r   r   r   r   zFolder contains message(s): %sr   z%Folder contains subdirectory '%s': %sF)topdownN)r   r   r   r   r   r   r   r   walkr.   rmdir)r   r   r   r   rootdirsfilesr   r   r    remove_folder  s,   zMaildir.remove_folderc                 C   sX   t   }ttj| jdD ]}tj| jd|}|tj| dkr)t| qdS )zDelete old files in "tmp".r   i@ N)timer   r   r   r   r   r   r.   )r   nowr   r   r   r   r    clean  s   
zMaildir.cleanr   c                 C   s   t   }t }d|v r|dd}d|v r|dd}dt|t|d d t tj|f }tj	
| jd|}zt| W n! tya   t jd7  _zt|W  Y S  ty^   Y nw Y nw td	| )
z=Create a file in the tmp subdirectory and open and return it./z\057r   z\072z%s.M%sP%sQ%s.%sr   g    .Ar   z&Name clash prevented file creation: %s)r  socketgethostnamer   intr   getpidr   _countr   r   r   statr   _create_carefullyFileExistsErrorr   )r   r  hostnamer   r   r   r   r    r     s0   zMaildir._create_tmpc                 C   s   t   | j d| j kr/d}| jD ]}tj| j| }|| j| kr%d}|| j|< q|s/dS i | _| jD ]/}| j| }t	|D ]"}tj
||}tj|rQqA|| jd }tj
||| j|< qAq5t   | _dS )z!Update table of contents mapping.   FTNr   )r  r   r   r   r   r   r   r   r   r   r   r   r   r   )r   refreshr   mtimer   r   pr   r   r   r    r     s(   


zMaildir._refreshc                 C   st   zt jt j| j| j| r| j| W S W n	 ty    Y nw |   z| j| W S  ty9   td| dw )z=Use TOC to return subpath for given key, or raise a KeyError.No message with key: %sN)r   r   r   r   r   r   r2   r   r,   r   r   r    r   &  s   zMaildir._lookupc                 C   sL   t | ds
|  | _	 z| t| j W S  ty   Y dS  ty%   Y q
w )z0Return the next message in a one-time iteration._onetime_keysTN)r^   rI   r  nextStopIterationr2   rH   r   r   r    r  4  s   

zMaildir.nextr   )r   r   r   r   r   r!   r)   r.   r3   r6   r:   rC   r=   rI   rW   rY   rd   rf   rh   rj   r   r   r   r  r	  r  r   r   r   r  r   r   r   r    r     s8    
*
	
$r   c                   @   s   e Zd ZdZd$ddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd%d d!Zd"d# ZdS )&_singlefileMailboxzA single-file mailbox.NTc              
   C   s   t | ||| zt| jd}W n7 tyG } z+|jtjkr,|r't| jd}nt| j|jtjtj	fv r<t| jd}n W Y d}~nd}~ww || _
d| _d| _d| _d| _d| _d| _dS )z!Initialize a single-file mailbox.rb+zwb+r   Nr   F)r   r!   r   r   r   r   ENOENTr   EACCESEROFS_filer   	_next_key_pending_pending_sync_locked_file_length)r   r   r   r   r   r   r   r   r    r!   D  s(   


z_singlefileMailbox.__init__c                 C   s8   |    | || j| j< |  jd7  _d| _| jd S )r#   r   T)r   _append_messager   r"  r$  r'   r   r   r    r)   [  s
   
z_singlefileMailbox.addc                 C   s   |  | | j|= d| _dS )r+   TN)r   r   r#  r,   r   r   r    r.   e  s   

z_singlefileMailbox.removec                 C   s$   |  | | || j|< d| _dS )r4   TN)r   r'  r   r#  r5   r   r   r    r6   k  s   

z_singlefileMailbox.__setitem__c                 c   s    |    | j E dH  dS r   )r   r   rL   rH   r   r   r    rI   q  s   z_singlefileMailbox.iterkeysc                 C   r   r   )r   r   r,   r   r   r    rW   v  r   z_singlefileMailbox.__contains__c                 C   r   r   )r   r   r   rH   r   r   r    rY   {  r   z_singlefileMailbox.__len__c                 C   s   | j st| j d| _ dS dS )re   TN)r%  
_lock_filer!  rH   r   r   r    rf        

z_singlefileMailbox.lockc                 C   s   | j rt| j d| _ dS dS rg   FN)r%  _unlock_filer!  rH   r   r   r    rh     r)  z_singlefileMailbox.unlockc           
      C   s  | j s| jrt| j d| _dS | jdusJ | jdd | j }|| jkr1td| j|f t	| j
}zSi }| | t| j D ]=}| j| \}}| j| | | | }	 | jtd|| j  }|son|| q^|| f||< | | qE| | _W n   |  t|j  t| | j  t| j
j}	t|j|	 z
t|j| j
 W n ty   t| j
 t|j| j
 Y nw t| j
d| _|| _d| _ d| _| jrt| jdd	 dS dS )
r   FNr   r  z4Size of mailbox file changed (expected %i, found %i)T   r  )dotlock) r#  r$  _sync_flushr!  r   r   tellr&  r   _create_temporaryr   _pre_mailbox_hooksortedrL   _pre_message_hookrr   minr   _post_message_hookrj   r   r.   r   r   r  st_modechmodr   r  r   r%  r(  )
r   cur_lennew_filenew_tocr-   startstop	new_startrs   moder   r   r    rd     sj   








z_singlefileMailbox.flushc                 C   r   ),Called before writing the mailbox to file f.Nr   r   r   r   r   r    r1    r   z$_singlefileMailbox._pre_mailbox_hookc                 C   r   )-Called before writing each message to file f.Nr   r@  r   r   r    r3    r   z$_singlefileMailbox._pre_message_hookc                 C   r   ,Called after writing each message to file f.Nr   r@  r   r   r    r5    r   z%_singlefileMailbox._post_message_hookc                 C   s   z#|    W z| jr|   W | j  dS W | j  dS | j  w z| jr3|   W | j  w W | j  w | j  w r   )rd   r%  rh   r!  rj   rH   r   r   r    rj     s   


z_singlefileMailbox.closec                 C   sH   | j du r	|   |dur"z| j | W S  ty!   td| dw dS )z'Return (start, stop) or raise KeyError.Nr  )r   _generate_tocr2   r,   r   r   r    r     s   
z_singlefileMailbox._lookupc                 C   s   | j dd | j  }t| jdkr| js| | j  z| | j  | |}| 	| j  W n t
y=   | j |  w | j   | j  | _|S )z;Append message to mailbox and return (start, stop) offsets.r   r  )r!  r   r/  r   r   r#  r1  r3  _install_messager5  r   truncaterd   r&  )r   r(   beforeoffsetsr   r   r    r'    s   


z"_singlefileMailbox._append_messager   r/   )r   r   r   r   r!   r)   r.   r6   rI   rW   rY   rf   rh   rd   r1  r3  r5  rj   r   r'  r   r   r   r    r  A  s$    

@

r  c                   @   sB   e Zd ZdZdZdd ZdddZddd	Zdd
dZdd Z	dS )	_mboxMMDFzAn mbox or MMDF mailbox.Tc                 C   sp   |  |\}}| j| | j td}| j|| j  }| |td}|	|dd 
d |S )r?       ro   rz   Nr   )r   r!  r   r   r   r   rr   r/  _message_factoryset_fromdecode)r   r-   r;  r<  	from_linestringr   r   r   r    r:   	  s   z_mboxMMDF.get_messageFc                 C   s   t | ||j|dS )3Return a string representation or raise a KeyError.)unixfromr@   )r   r-   from_r   r   r    rE     s
   
z_mboxMMDF.get_stringc                 C   sJ   |  |\}}| j| |s| j  | j|| j  }|tdS )rP  ro   )r   r!  r   r   rr   r/  r   r   )r   r-   rR  r;  r<  rO  r   r   r    rC     s   
z_mboxMMDF.get_bytesc                 C   s<   |  |\}}| j| |s| j  t| j| j |S )rF   )r   r!  r   r   _PartialFiler/  )r   r-   rR  r;  r<  r   r   r    r=   !  s
   
z_mboxMMDF.get_filec                 C   s  d}t |tr| |}t |tr3|dr3|d}|dkr.|d| }||d d }n*|}d}n%t |trD| d}d| }nt |t	j
jrX| }|durX|d}|du rgdtt   }| j }| j|t  | || j| j | j }||fS )	z1Format a message and blindly write to self._file.Nry   ro   rx   r   rJ  r   s   From MAILER-DAEMON )r|   r   rn   r   r   find_mboxMMDFMessageget_fromrk   rA   r(   r	   get_unixfromr  asctimegmtimer!  r/  r   r   r   _mangle_from_)r   r(   rN  newlineauthorr;  r<  r   r   r    rE  )  s0   







z_mboxMMDF._install_messageNr   )
r   r   r   r   rZ  r:   rE   rC   r=   rE  r   r   r   r    rI    s    



	rI  c                   @   s2   e Zd ZdZdZdZd
ddZdd Zdd	 ZdS )r   zA classic mbox mailbox.TNc                 C      t | _t| ||| dS )zInitialize an mbox mailbox.N)r   rK  rI  r!   r   r   r   r    r!   O     zmbox.__init__c                 C   s   | t dS rB  r   r   r@  r   r   r    r5  T     zmbox._post_message_hookc                 C   s   g g }}d}| j d 	 | j  }| j  }|dr>t|t|k r6|r1||tt  n|| || d}n|sR|rL||tt  n|| n
|tkrYd}nd}qtt	t
||| _t| j| _| j  | _dS )0Generate key-to-(start, stop) table of contents.Fr   Try   N)r!  r   r/  r   r   r   r   r   dict	enumeratezipr   r"  r&  )r   startsstopslast_was_emptyline_posr   r   r   r    rD  X  s2   






zmbox._generate_tocr   )	r   r   r   r   rZ  r   r!   r5  rD  r   r   r   r    r   F  s    
r   c                   @   s2   e Zd ZdZdddZdd Zdd	 Zd
d ZdS )r   zAn MMDF mailbox.NTc                 C   r]  )zInitialize an MMDF mailbox.N)r   rK  rI  r!   r   r   r   r    r!   }  r^  zMMDF.__init__c                 C      | dt  dS )rA     Nr_  r@  r   r   r    r3       zMMDF._pre_message_hookc                 C   s   | td t  dS )rC  rj  Nr_  r@  r   r   r    r5    s   zMMDF._post_message_hookc                 C   s   g g }}| j d d}	 |}| j  }| j  }|dt rM|| 	 |}| j  }| j  }|dt krC||tt  n	|sK|| nq'n|sPnqtt	t
||| _t| j| _| j dd | j  | _dS )ra  r   Trj  r  N)r!  r   r   r/  r   r   r   r   rb  rc  rd  r   r"  r&  )r   re  rf  next_posrh  r   r   r   r    rD    s8   







zMMDF._generate_tocr   )r   r   r   r   r!   r3  r5  rD  r   r   r   r    r   z  s    
r   c                   @   s   e Zd ZdZd0ddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ ZdS )1r   zAn MH mailbox.NTc                 C   st   t | ||| tj| js5|r0t| jd tttj	| jdtj
tjB tjB d nt| jd| _dS )zInitialize an MH instance.r   .mh_sequencesi  FN)r   r!   r   r   r   r   r   rj   r   r   r   O_EXCLr   r   r%  r   r   r   r    r!     s   

zMH.__init__c                 C   s   |   }t|dkrd}nt|d }tj| jt|}t|}d}zQ| j	r+t
| z7z| || W n tyN   | j	rBt| t| d}t|  w t|trZ| || W | j	rbt| n	| j	rkt| w w W |sst| |S |s|t| w w )r#   r   r   FT)rL   r   maxr   r   r   r   r   r  r%  r(  r   r   r+  r   r.   r|   r   _dump_sequences)r   r(   rL   new_keyr   r   closedr   r   r    r)     sJ   



zMH.addc              
   C   sl   t j| jt|}zt|d}W n ty* } z|jtjkr%t	d|  d}~ww |
  t | dS )r+   r  r  N)r   r   r   r   r   r   r   r   r  r2   rj   r.   )r   r-   r   r   r   r   r   r    r.     s   z	MH.removec              
   C   s   t j| jt|}zt|d}W n ty* } z|jtjkr%t	d|  d}~ww z?| j
r3t| z't t |t jt jB  | || t|trR| || W | j
rZt| n	| j
rct| w w W t| dS t| w )r4   r  r  N)r   r   r   r   r   r   r   r   r  r2   r%  r(  rj   r   O_TRUNCr   r|   r   rp  r+  r   )r   r-   r(   r   r   r   r   r   r    r6     s4   

zMH.__setitem__c              
   C   s   z | j rttj| jt|d}nttj| jt|d}W n ty9 } z|jtj	kr4t
d|  d}~ww |& | j rDt| zt|}W | j rQt| n	| j rZt| w w W d   n1 sew   Y  |   D ]\}}||v r}|| qp|S )r?   r  r   r  N)r%  r   r   r   r   r   r   r   r   r  r2   r(  r   r+  get_sequencesrU   add_sequence)r   r-   r   r   r   r   key_listr   r   r    r:     s:   


zMH.get_messagec              
   C   s   z | j rttj| jt|d}nttj| jt|d}W n ty9 } z|jtj	kr4t
d|  d}~ww |) | j rDt| z| tdW | j rTt| W  d   S | j rdt| w w 1 shw   Y  dS )r   r  r   r  Nro   )r%  r   r   r   r   r   r   r   r   r  r2   r(  rr   r   r   r+  r   r-   r   r   r   r   r    rC     s.   
zMH.get_bytesc              
   C   sX   zt tj| jt|d}W t
|S  ty+ } z|jtjkr&t	d|  d}~ww )rF   r   r  N)r   r   r   r   r   r   r   r   r  r2   r   rw  r   r   r    r=   ,  s   zMH.get_filec                 C   s   t tdd t| jD S )rG   c                 s   s     | ]}|  rt|V  qd S r/   )isdigitr  ).0r   r   r   r    	<genexpr>9  s    zMH.iterkeys.<locals>.<genexpr>)iterr2  r   r   r   rH   r   r   r    rI   7  s   zMH.iterkeysc                 C   s   t jt j| jt|S r   )r   r   r   r   r   r   r,   r   r   r    rW   <  s   zMH.__contains__c                 C   s   t t|  S r   )r   rK   rI   rH   r   r   r    rY   @     z
MH.__len__c                 C   s6   | j sttj| jdd| _t| j d| _ dS dS )re   rm  r  TN)r%  r   r   r   r   r   r!  r(  rH   r   r   r    rf   D  s
   

zMH.lockc                 C   s,   | j rt| j t| j | `d| _ dS dS r*  )r%  r+  r!  r   rH   r   r   r    rh   K  s   


z	MH.unlockc                 C   r   )rc   Nr   rH   r   r   r    rd   S  r   zMH.flushc                 C   s   | j r	|   dS dS r   )r%  rh   rH   r   r   r    rj   W  s   zMH.closec                 C   s<   g }t | jD ]}t jt j| j|r|| q|S )r   )r   r   r   r   r   r   r   r   r   r   r    r   \  s   
zMH.list_foldersc                 C   s   t tj| j|| jddS )z+Return an MH instance for the named folder.Fr   r   r   r   r   r   r   r   r   r   r    r   d  s   zMH.get_folderc                 C   s   t tj| j|| jdS )z:Create a folder and return an MH instance representing it.r   r}  r   r   r   r    r   i  s   zMH.add_folderc                 C   s`   t j| j|}t |}|dgkrt t j|d n|g kr"ntd| j t | dS )r   rm  zFolder not empty: %sN)r   r   r   r   r   r.   r   r  )r   r   r   entriesr   r   r    r  n  s   

zMH.remove_folderc           
   
      s  i }t tj| jddddp}t|   |D ]^}zM|d\}}t }| D ]$}| r7|	t
| q)dd |dD \}}	|t||	d	  q) fd
dt|D ||< t|| dkrf||= W q tyv   td|  w W d   |S 1 sw   Y  |S )z=Return a name-to-key-list dictionary to define each sequence.rm  rASCIIencodingr   c                 s   s    | ]}t |V  qd S r/   )r  )ry  xr   r   r    rz        z#MH.get_sequences.<locals>.<genexpr>-r   c                    s   g | ]}| v r|qS r   r   )ry  r-   all_keysr   r    
<listcomp>  s    z$MH.get_sequences.<locals>.<listcomp>r   z"Invalid sequence specification: %sN)r   r   r   r   r   setrL   r   rx  r)   r  rb   ranger2  r   rm   r   rstrip)
r   resultsr   r   r   contentsrL   specr;  r<  r   r  r    rt  z  s4   
zMH.get_sequencesc                 C   s  t tj| jdddd}zqtt |jtjtjB  |	 D ]W\}}t
|dkr+q ||d  d}d}tt|D ])}|d	 |krN|sMd
}|d n|r\d}|d||f  n|d|  |}q<|rr|t|d  q |d q W t| dS t| w )z:Set sequences using the given name-to-key-list dictionary.rm  zr+r  r  r   r   NFr   Tr  z%s %sz %s
)r   r   r   r   r   rj   r   r   rs  rU   r   r   r2  r  r   r   )r   	sequencesr   r   rL   prev
completingr-   r   r   r    set_sequences  s2   
zMH.set_sequencesc           	      C   s8  |   }d}g }|  D ]`}|d |krh|||d f zttj| jt|tj| jt|d  W n# t	t
fyZ   ttj| jt|tj| jt|d  Y nw ttj| jt| |d7 }q|d | _t|dkrzdS | D ]\}}|D ]\}}||v r||||< qq~| | dS )z?Re-name messages to eliminate numbering gaps. Invalidates keys.r   r   N)rt  rI   r   r   r   r   r   r   r   r   r   r   unlinkr"  r   rU   indexr  )	r   r  r  changesr-   r   rv  oldr   r   r   r    pack  s6   

zMH.packc                 C   st   |  }|   }| D ]\}}||v r|| q||v r$|||= q|D ]}||vr2|g||< q'| | dS )z;Inspect a new MHMessage and update sequences appropriately.N)rt  rU   r   r  r  )r   r(   r-   pending_sequencesall_sequencesr   rv  sequencer   r   r    rp    s   
zMH._dump_sequencesr   )r   r   r   r   r!   r)   r.   r6   r:   rC   r=   rI   rW   rY   rf   rh   rd   rj   r   r   r   r  rt  r  r  rp  r   r   r   r    r     s0    
"r   c                   @   s   e Zd ZdZeh dZdddZdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZdS ) r   zAn Rmail-style Babyl mailbox.>   filededitedresentunseendeletedanswered	forwardedNTc                 C   s   t | ||| i | _dS )zInitialize a Babyl mailbox.N)r  r!   _labelsr   r   r   r    r!     s   
zBabyl.__init__c                 C   s(   t | |}t|tr| | j|< |S )r#   )r  r)   r|   r   
get_labelsr  )r   r(   r-   r   r   r    r)     s   
z	Babyl.addc                 C   s&   t | | || jv r| j|= dS dS r   )r  r.   r  r,   r   r   r    r.     s   
zBabyl.removec                 C   s.   t | || t|tr| | j|< dS dS )r4   N)r  r6   r|   r   r  r  r5   r   r   r    r6     s   
zBabyl.__setitem__c           
      C   s  |  |\}}| j| | j  t }	 | j }|dt ks$|s%n
||td qt }	 | j }|tks?|s@n
||td q4|| j	  }|dksWJ | j
|}|td}t| | }	|	|  || jv r|	| j|  |	S )r?   T   *** EOOH ***ro   r   )r   r!  r   r   r}   r~   r   r   r   r/  rr   r   r   set_visibler  
set_labels)
r   r-   r;  r<  original_headersr   visible_headersnbodyr   r   r   r    r:     s4   



zBabyl.get_messagec           	      C   s   |  |\}}| j| | j  t }	 | j }|dt ks$|s%n
||td q	 | j }|tks;|s<nq0|	 }|| j
  }|dksNJ | j|}|td}|| S )rP  Tr  ro   r   )r   r!  r   r   r}   r~   r   r   r   r   r/  rr   )	r   r-   r;  r<  r  r   headersr  r   r   r   r    rC     s*   


zBabyl.get_bytesc                 C   s   t | |dtS )rF   ro   )r}   r~   rC   r   r   r,   r   r   r    r=   (     zBabyl.get_filec                 C   s<   |    t }| j D ]}|| q|| j t|S )z4Return a list of user-defined labels in the mailbox.)r   r  r  rS   rb   difference_update_special_labelsrK   )r   labels
label_listr   r   r    r  ,  s   zBabyl.get_labelsc                 C   s<  g g }}| j d d}g }	 |}| j  }| j  }|dt krOt|t|k r3||tt  || dd | j  dd dD }|| n(|d	ksY|d	t krkt|t|k rj||tt  n|sw||tt  nqtt	t
||| _tt	|| _t| j| _| j dd
 | j  | _dS )ra  r   Ts   c                 S   s   g | ]
}|  r|  qS r   )stripry  labelr   r   r    r  C  s    z'Babyl._generate_toc.<locals>.<listcomp>r   N   ,   r  )r!  r   r   r/  r   r   r   r   rb  rc  rd  r   r  r"  r&  )r   re  rf  rl  label_listsrh  r   r  r   r   r    rD  5  s:   



zBabyl._generate_tocc                 C   sV   dt  }|dt  7 }|  }dd |D }|dd| t  7 }|d7 }|| dS )	r?  s   BABYL OPTIONS:s
   Version: 5c                 s   s    | ]}|  V  qd S r/   )rk   r  r   r   r    rz  X  r  z*Babyl._pre_mailbox_hook.<locals>.<genexpr>s   Labels:r  r  N)r   r  r   r   )r   r   babylr  r   r   r    r1  S  s   zBabyl._pre_mailbox_hookc                 C   ri  )rA     Nr_  r@  r   r   r    r3  ]  rk  zBabyl._pre_message_hookc                 C   s   | td  dS )rC  r  Nr_  r@  r   r   r    r5  a  rk  zBabyl._post_message_hookc                 C   s`  | j  }t|trXg }g }| D ]}|| jv r|| q|| q| j d |D ]}| j d|   q-| j d |D ]}| j d|  d  qB| j t	 n| j dt	  t|t
jjrt }t
j|dd}|| |d 	 | }| j |d
t	 |d
ks|snq~| j dt	  t|trt }	t
j|	dd}
|
|  	 |	 }| j |d
t	 |d
ks|snqn|d 	 | }| j |d
t	 |d
ks|snq	 |d}|sn| j |d
t	 qn)t|tttjfr{t|tjrtdtd | }t|tr%| |}|dd }|d dkrf| j |d| d
t	 | j dt	  | j |d| d
t	 | j ||d d
t	 n| j dt	 t	  | j |d
t	 nt |drt |drtdtd |j!}| }d	}	 | }|"dr|dd d
 }n|"dr|dd d
 }| j |d
t	 |d
ks|s|rd}| j dt	  || nnq	 | }|sn4|"dr|dd t	 }n|"dr|dd t	 }n|"d
r|dd t	 }| j | qnt#dt$| | j  }||fS )z0Write message contents and return (start, stop).   1s   , s   ,,    r  s   1,,Fr   Tro   r  r,  rp   rq   s   

r  rx   Nr   rs   rt   ru   rv   rw   r{   )%r!  r/  r|   r   r  r  r   r   rk   r   rA   r(   r	   r}   r~   r   r   r   r   r   r   get_visiblerr   r   r   r   r   r   r   r   rn   rT  r^   rs   r   r   r   )r   r(   r;  special_labelsr  r  orig_bufferorig_generatorr   
vis_buffervis_generatorrs   
body_startoriginal_pos
first_passr<  r   r   r    rE  e  s   










zBabyl._install_messager   )r   r   r   r   	frozensetr  r!   r)   r.   r6   r:   rC   r=   r  rD  r1  r3  r5  rE  r   r   r   r    r     s     
	
r   c                   @   s*   e Zd ZdZd	ddZdd Zdd ZdS )
r	   z0Message with mailbox-format-specific properties.Nc                 C   s   t |tjjr| t| t |tr||  dS dS t |tr,| t	| dS t |t
r;| t| dS t |tjrK| t| dS t|drZ| t| dS |du rgtjj|  dS tdt| )zInitialize a Message instance.rr   Nr{   )r|   rA   r(   r	   _become_messagecopydeepcopy_explain_tor   rB   r   message_from_stringr}   TextIOWrappermessage_from_filer^   message_from_binary_filer!   r   r   r'   r   r   r    r!     s    



zMessage.__init__c                 C   s4   t |dg }|jD ]}||vr|j| | j|< q	dS )z0Assume the non-format-specific state of message._type_specific_attributesN)getattr__dict__)r   r(   type_specificr   r   r   r    r    s   
zMessage._become_messagec                 C   s   t |trdS td)z:Copy format-specific state to message insofar as possible.Nz Cannot convert to specified type)r|   r	   r   r'   r   r   r    r    s   
zMessage._explain_tor/   )r   r   r   r   r!   r  r  r   r   r   r    r	     s
    
r	   c                   @   sz   e Zd ZdZg dZdddZdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd ZdS )r
   z)Message with Maildir-specific properties.)_subdir_info_dateNc                 C   s&   d| _ d| _t | _t| | dS )z%Initialize a MaildirMessage instance.r   r   N)r  r  r  r  r	   r!   r'   r   r   r    r!     s   
zMaildirMessage.__init__c                 C      | j S )zReturn 'new' or 'cur'.)r  rH   r   r   r    r        zMaildirMessage.get_subdirc                 C   s&   |dks|dkr|| _ dS td| )zSet subdir to 'new' or 'cur'.r   r   z!subdir must be 'new' or 'cur': %sN)r  rm   )r   r   r   r   r    r     s   
zMaildirMessage.set_subdirc                 C   s   | j dr| j dd S dS )*Return as a string the flags that are set.2,r  Nr   )r  r   rH   r   r   r    	get_flags  s   zMaildirMessage.get_flagsc                 C   s   dd t| | _dS ))Set the given flags and unset all others.r  r   N)r   r2  r  )r   flagsr   r   r    	set_flags  r  zMaildirMessage.set_flagsc                 C   $   |  dt|  t|B  dS z.Set the given flag(s) without changing others.r   Nr  r   r  r  r   flagr   r   r    add_flag     $zMaildirMessage.add_flagc                 C   s0   |   r| dt|   t|  dS dS )7Unset the given string flag(s) without changing others.r   N)r  r  r   r  r  r   r   r    remove_flag  s   $zMaildirMessage.remove_flagc                 C   r  )z<Return delivery date of message, in seconds since the epoch.)r  rH   r   r   r    r   !  r  zMaildirMessage.get_datec                 C   s.   zt || _W dS  ty   td| dw )z9Set delivery date of message, in seconds since the epoch.zcan't convert to float: %sN)floatr  rm   r   )r   dater   r   r    r   %  s
   zMaildirMessage.set_datec                 C   r  )z%Get the message's "info" as a string.)r  rH   r   r   r    r   ,  r  zMaildirMessage.get_infoc                 C   s$   t |tr
|| _dS tdt| )z Set the message's "info" string.zinfo must be a string: %sN)r|   r   r  r   r   )r   infor   r   r    r   0  s   

zMaildirMessage.set_infoc                 C   s  t |tr||   ||   ||   dS t |trct	|  }d|v r0|
d |  dkr;|
d d|v rD|
d d|v rM|
d d|v rV|
d |d	t|   dS t |trt	|  }d|vrw|d
 d|v r|d d|v r|d dS dS t |trt	|  }d|vr|d
 d|v r|d d|v r|d d|v r|d dS dS t |trdS tdt| )z;Copy Maildir-specific state to message insofar as possible.SRr   OTDFAMAILER-DAEMONr  repliedflaggedr  r  Pr  $Cannot convert to specified type: %sN)r|   r
   r  r  r   r   r   r   rU  r  r  rL  r  rY  r   ru  r   	add_labelr	   r   r   )r   r(   r  r   r   r    r  7  sT   














zMaildirMessage._explain_tor/   )r   r   r   r   r  r!   r   r   r  r  r  r  r   r   r   r   r  r   r   r   r    r
     s    
r
   c                   @   sZ   e Zd ZdZdgZdddZdd Zddd	Zd
d Zdd Z	dd Z
dd Zdd ZdS )rU  z/Message with mbox- or MMDF-specific properties._fromNc                 C   sV   |  dd t|tjjr#| }|dur#|dr#|  |dd  t| | dS )z'Initialize an mboxMMDFMessage instance.r  TNzFrom rz   )rL  r|   rA   r(   r	   rW  r   r!   )r   r(   rQ  r   r   r    r!   h  s   z_mboxMMDFMessage.__init__c                 C   r  )z Return contents of "From " line.)r  rH   r   r   r    rV  q  r  z_mboxMMDFMessage.get_fromc                 C   s4   |dur|du rt  }|dt | 7 }|| _dS )z>Set "From " line, formatting and appending time_ if specified.NT )r  rY  rX  r  )r   rR  time_r   r   r    rL  u  s
   
z_mboxMMDFMessage.set_fromc                 C   s   |  dd|  dd S )r  Statusr   X-Status)r9   rH   r   r   r    r  }  r  z_mboxMMDFMessage.get_flagsc                 C   s   t |}d\}}dD ]}||v r||7 }|| q
dD ]}||v r+||7 }|| q|dt|7 }z| d| W n tyL   | d| Y nw z	| d| W dS  tyf   | d| Y dS w )r  )r   r   )r  r  )r  r  r  r   r  r  N)r  r.   r   r2  replace_headerr2   
add_header)r   r  status_flagsxstatus_flagsr  r   r   r    r    s.   

z_mboxMMDFMessage.set_flagsc                 C   r  r  r  r  r   r   r    r    r  z_mboxMMDFMessage.add_flagc                 C   s8   d| v sd| v r|  dt|  t|  dS dS )r  r  r  r   Nr  r  r   r   r    r    s   $z_mboxMMDFMessage.remove_flagc              	   C   s  t |trgt|  }d|v r|d d|v r|d d|v r&|d d|v r/|d d|v r8|d |d	= |d
= d|   dd }z|	t
t|d W dS  ttfyf   Y dS w t |tr|||   ||   dS t |trt|  }d|vr|d d|v r|d d|v r|d |d	= |d
= dS t |trt|  }d|vr|d d|v r|d d|v r|d |d	= |d
= dS t |trdS tdt| )zACopy mbox- or MMDF-specific state to message insofar as possible.r  r   r  r  r  r  r  r  statuszx-statusr  Nz%a %b %d %H:%M:%S %Yr  r  r  r  r  r  )r|   r
   r  r  r   r  r   rV  r   r   calendartimegmr  strptimerm   OverflowErrorrU  r  rL  r   ru  r   r  r	   r   r   )r   r(   r  
maybe_dater   r   r    r    sd   

















z_mboxMMDFMessage._explain_tor/   )r   r   r   r   r  r!   rV  rL  r  r  r  r  r  r   r   r   r    rU  c  s    
	
rU  c                   @      e Zd ZdZdS )r   z&Message with mbox-specific properties.Nr   r   r   r   r   r   r   r    r         r   c                   @   sH   e Zd ZdZdgZdddZdd Zdd	 Zd
d Zdd Z	dd Z
dS )r   z$Message with MH-specific properties.
_sequencesNc                 C   s   g | _ t| | dS )z!Initialize an MHMessage instance.N)r	  r	   r!   r'   r   r   r    r!     s   zMHMessage.__init__c                 C      | j dd S )z4Return a list of sequences that include the message.N)r	  rH   r   r   r    rt    r`  zMHMessage.get_sequencesc                 C      t || _dS )z3Set the list of sequences that include the message.N)rK   r	  )r   r  r   r   r    r    r`  zMHMessage.set_sequencesc                 C   8   t |tr|| jvr| j| dS dS tdt| )z8Add sequence to list of sequences including the message.zsequence type must be str: %sN)r|   r   r	  r   r   r   r   r  r   r   r    ru    
   

zMHMessage.add_sequencec                 C   (   z	| j | W dS  ty   Y dS w )zARemove sequence from the list of sequences including the message.N)r	  r.   rm   r  r   r   r    remove_sequence  
   zMHMessage.remove_sequencec                 C   sP  t |tr5t|  }d|v r|d n
|d |d d|v r(|d d|v r3|d dS dS t |tret|  }d|vrJ|d n|d	 d|v rX|d d|v rc|d
 dS dS t |trx|  D ]}|| qndS t |t	rt|  }d|v r|
d d|v r|
d dS dS t |trdS tdt| )z6Copy MH-specific state to message insofar as possible.r  r   r  r  r  r  r  ROr  r  r  r  N)r|   r
   r  rt  r   r  rU  r   ru  r   r  r	   r   r   )r   r(   r  r  r   r   r    r    sJ   










zMHMessage._explain_tor/   )r   r   r   r   r  r!   rt  r  ru  r  r  r   r   r   r    r     s    
r   c                   @   sb   e Zd ZdZddgZdddZdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd ZdS )r   z'Message with Babyl-specific properties.r  _visibleNc                 C   s   g | _ t | _t| | dS )z#Initialize a BabylMessage instance.N)r  r	   r  r!   r'   r   r   r    r!   %  s   zBabylMessage.__init__c                 C   r
  )z'Return a list of labels on the message.N)r  rH   r   r   r    r  +  r`  zBabylMessage.get_labelsc                 C   r  )z&Set the list of labels on the message.N)rK   r  )r   r  r   r   r    r  /  r`  zBabylMessage.set_labelsc                 C   r  )z+Add label to list of labels on the message.zlabel must be a string: %sN)r|   r   r  r   r   r   r   r  r   r   r    r  3  r  zBabylMessage.add_labelc                 C   r  )z4Remove label from the list of labels on the message.N)r  r.   rm   r  r   r   r    remove_label;  r  zBabylMessage.remove_labelc                 C   s
   t | jS )z3Return a Message representation of visible headers.r	   r  rH   r   r   r    r  B  s   
zBabylMessage.get_visiblec                 C   r  )z2Set the Message representation of visible headers.Nr  )r   visibler   r   r    r  F  r`  zBabylMessage.set_visiblec                 C   sb   | j  D ]}|| v r| j || |  q| j |= qdD ]}|| v r.|| j vr.| | | j |< qdS )z9Update and/or sensibly generate a set of visible headers.)DateFromzReply-ToToCCSubjectN)r  rL   r  )r   headerr   r   r    update_visibleJ  s   
zBabylMessage.update_visiblec                 C   sx  t |trBt|  }d|v r|d n
|d |d d|v s'd|v r,|d d|v r5|d d	|v r@|d
 dS dS t |trrt|  }d|vrW|d n|d d	|v re|d d|v rp|d dS dS t |trt|  }d|v r|d d|v r|d dS dS t |t	r|
|   |  D ]}|| qdS t |trdS tdt| )z9Copy Babyl-specific state to message insofar as possible.r  r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  N)r|   r
   r  r  r   r  rU  r   ru  r   r  r  r  r	   r   r   )r   r(   r  r  r   r   r    r  U  sP   











zBabylMessage._explain_tor/   )r   r   r   r   r  r!   r  r  r  r  r  r  r  r  r   r   r   r    r      s    
r   c                   @   r  )r   z&Message with MMDF-specific properties.Nr  r   r   r   r    r     r  r   c                   @   s   e Zd ZdZd&ddZd&ddZd&ddZd&d	d
Zd&ddZdd Z	dd Z
d'ddZdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zed$d% ZeeZdS )(r   zA read-only wrapper of a file.Nc                 C   s&   || _ |du r| | _dS || _dS )zInitialize a _ProxyFile.N)r!  r/  _pos)r   r   posr   r   r    r!     s   
z_ProxyFile.__init__c                 C      |  || jjS zRead bytes.)_readr!  rr   r   sizer   r   r    rr     r|  z_ProxyFile.readc                 C   r!  r"  )r#  r!  read1r$  r   r   r    r&    r|  z_ProxyFile.read1c                 C   r!  )zRead a line.)r#  r!  r   r$  r   r   r    r     r|  z_ProxyFile.readlinec                 C   s>   g }| D ]}| | |dur|t|8 }|dkr |S q|S )zRead multiple lines.Nr   )r   r   )r   sizehintr[   r   r   r   r    	readlines  s   
 z_ProxyFile.readlinesc                 c   s    	 |   }|s
dS |V  q)zIterate over lines.TN)r   )r   r   r   r   r    rR     s   z_ProxyFile.__iter__c                 C   r  )zReturn the position.)r  rH   r   r   r    r/    r  z_ProxyFile.tellr   c                 C   s4   |dkr| j | j | j || | j  | _dS )zChange position.r   Nr!  r   r  r/  r   offsetwhencer   r   r    r     s   z_ProxyFile.seekc                 C   s@   t | drzt | jdr| j  W | `dS W | `dS | `w dS )zClose the file.r!  rj   N)r^   r!  rj   rH   r   r   r    rj     s   
z_ProxyFile.closec                 C   s2   |du rd}| j | j ||}| j  | _|S )z"Read size bytes using read_method.Nrx   r)  )r   r%  read_methodr[   r   r   r    r#    s   z_ProxyFile._readc                 C   s   | S )z$Context management protocol support.r   rH   r   r   r    	__enter__  r   z_ProxyFile.__enter__c                 G   s   |    d S r/   )rj   )r   excr   r   r    __exit__  s   z_ProxyFile.__exit__c                 C   
   | j  S r/   )r!  readablerH   r   r   r    r2       
z_ProxyFile.readablec                 C   r1  r/   )r!  writablerH   r   r   r    r4    r3  z_ProxyFile.writablec                 C   r1  r/   )r!  seekablerH   r   r   r    r5    r3  z_ProxyFile.seekablec                 C   r1  r/   )r!  rd   rH   r   r   r    rd     r3  z_ProxyFile.flushc                 C   s&   t | dsdS t | jdsdS | jjS )Nr!  Trr  F)r^   r!  rr  rH   r   r   r    rr    s
   
z_ProxyFile.closedr/   r   )r   r   r   r   r!   rr   r&  r   r(  rR   r/  r   rj   r#  r.  r0  r2  r4  r5  rd   propertyrr  r   r   r   r   r   r   r    r     s*    





		
r   c                   @   s<   e Zd ZdZdddZdd Zddd	Zd
d Zdd ZdS )rS  z&A read-only wrapper of part of a file.Nc                 C   s   t | || || _|| _dS )zInitialize a _PartialFile.N)r   r!   _start_stop)r   r   r;  r<  r   r   r    r!     s   
z_PartialFile.__init__c                 C   s   t | | j S )z*Return the position with respect to start.)r   r/  r8  rH   r   r   r    r/    r|  z_PartialFile.tellr   c                 C   s<   |dkr| j | _d}n
|dkr| j| _d}t| || dS )z8Change position, possibly with respect to start or stop.r   r   r  N)r8  r  r9  r   r   r*  r   r   r    r     s   z_PartialFile.seekc                 C   sB   | j | j }|dkrdS |du s|dk s||kr|}t| ||S )z;Read size bytes using read_method, honoring start and stop.r   rJ  N)r9  r  r   r#  )r   r%  r-  	remainingr   r   r    r#    s   z_PartialFile._readc                 C   s   t | dr	| `d S d S )Nr!  )r^   r!  rH   r   r   r    rj     s   
z_PartialFile.close)NNr6  )	r   r   r   r   r!   r/  r   r#  rj   r   r   r   r    rS    s    


	rS  Tc              
   C   s  d}zt r1zt | t jt jB  W n ty0 } z|jtjtjtjfv r+t	d| j
  d}~ww |rzt| j
d }|  W n ty^ } z|jtjtjfv rYW Y d}~W dS  d}~ww z4zt|j
| j
d  d}W n ttfy   t|j
| j
d  d}Y nw t|j
 W W dS W W dS  ty   t|j
 t	d| j
 w W dS    t rt | t j |rt| j
d   )z(Lock file f using lockf and dot locking.Fzlockf: lock unavailable: %sN.lockTzdot lock unavailable: %s)fcntllockfLOCK_EXLOCK_NBr   r   EAGAINr  r   r   r   r0  rj   r   r   r   r   r   r  r  r.   LOCK_UN)r   r-  dotlock_doner   pre_lockr   r   r    r(    s\   r(  c                 C   s<   t r	t | t j tj| jd rt| jd  dS dS )z*Unlock file f using lockf and dot locking.r;  N)r<  r=  rA  r   r   r   r   r.   r   r   r   r    r+  9  s
   r+  c              	   C   s@   t | t jt jB t jB d}zt| dW t | S t | w )zCCreate a file if it doesn't exist and open for reading and writing.r   r  )r   r   r   rn  O_RDWRrj   )r   fdr   r   r    r  @  s   
r  c                 C   s$   t d| tt t t f S )zBCreate a temp file based on path and open for reading and writing.z%s.%s.%s.%s)r  r  r  r  r  r   r  )r   r   r   r    r0  H  s   r0  c                 C   s(   |    ttdrt|   dS dS )z0Ensure changes to file f are physically on disk.fsyncN)rd   r^   r   rG  filenorD  r   r   r    r.  N  s   
r.  c                 C   s   t |  |   dS )z:Close file f, ensuring all changes are physically on disk.N)r.  rj   rD  r   r   r    r   T  s   r   c                   @   r  )r   z"Raised for module-specific errors.Nr  r   r   r   r    r   Z  r  r   c                   @   r  )r   z:The specified mailbox does not exist and won't be created.Nr  r   r   r   r    r   ]  r  r   c                   @   r  )r   z>The specified mailbox is not empty and deletion was requested.Nr  r   r   r   r    r   `  r  r   c                   @   r  )r   z)Another process caused an action to fail.Nr  r   r   r   r    r   c  r  r   c                   @   r  )r   z)A file appears to have an invalid format.Nr  r   r   r   r    r   f  r  r   )T)2r   r   r  r  r  r   r  r   rA   email.messageemail.generatorr}   r;   typesr   r<  ImportError__all__r   rk   r   r   r  rI  r   r   r   r   r(   r	   r
   rU  r   r   r   r   r   rS  r(  r+  r  r0  r.  r   	Exceptionr   r   r   r   r   r   r   r   r    <module>   sp     j  8 DB4-  3 z%mqH_e
'*