U
    ØccÃL  ã                   @   sX   d dl mZmZmZmZmZ d dlmZmZm	Z	m
Z
mZ d dlmZ G dd„ deƒZdS )é    )Úlinefeed_byte_valueÚcrlfÚcr_byteÚlinefeed_byteÚcr_byte_value)ÚBytesIOÚPY2ÚuÚbytes_typesÚ	text_type)ÚClosingContextManagerc                   @   s   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZd	Zd
Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zerndd„ Zndd„ Zdd„ Zdd„ Zdd„ Zdd „ ZdBd"d#„ZdCd$d%„ZdDd&d'„ZdEd(d)„Zd*d+„ Zd,d-„ Z d.d/„ Z!d0d1„ Z"e#d2d3„ ƒZ$d4d5„ Z%d6d7„ Z&d8d9„ Z'dFd<d=„Z(d>d?„ Z)d@dA„ Z*d!S )GÚBufferedFilezc
    Reusable base class to implement Python-style file buffering around a
    simpler stream.
    i    r   é   é   é   é   é    é@   é€   c                 C   sF   d | _ d| _| j| _tƒ | _tƒ | _d| _d| _	d | _
| _d| _d S )Nr   F)ÚnewlinesÚ_flagsÚ_DEFAULT_BUFSIZEÚ_bufsizer   Ú_wbufferÚbytesÚ_rbufferÚ_at_trailing_crÚ_closedÚ_posÚ_realposÚ_size©Úself© r#   ú1/tmp/pip-unpacked-wheel-rglolp_m/paramiko/file.pyÚ__init__2   s    zBufferedFile.__init__c                 C   s   |   ¡  d S ©N)Úcloser!   r#   r#   r$   Ú__del__A   s    zBufferedFile.__del__c                 C   s   | j rtdƒ‚| S )zý
        Returns an iterator that can be used to iterate over the lines in this
        file.  This iterator happens to return the file itself, since a file is
        its own iterator.

        :raises: ``ValueError`` -- if the file is closed.
        zI/O operation on closed file)r   Ú
ValueErrorr!   r#   r#   r$   Ú__iter__D   s    zBufferedFile.__iter__c                 C   s   |   ¡  d| _dS )zN
        Close the file.  Future read and write operations will fail.
        TN)Úflushr   r!   r#   r#   r$   r'   P   s    zBufferedFile.closec                 C   s   |   | j ¡ ¡ tƒ | _dS )z{
        Write out any data in the write buffer.  This may do nothing if write
        buffering is not turned on.
        N)Ú
_write_allr   Úgetvaluer   r!   r#   r#   r$   r+   W   s    zBufferedFile.flushc                 C   s   |   ¡ }|st‚|S )a\  
            Returns the next line from the input, or raises
            ``StopIteration`` when EOF is hit.  Unlike Python file
            objects, it's okay to mix calls to `next` and `readline`.

            :raises: ``StopIteration`` -- when the end of the file is reached.

            :returns: a line (`str`) read from the file.
            ©ÚreadlineÚStopIteration©r"   Úliner#   r#   r$   Únextb   s    
zBufferedFile.nextc                 C   s   |   ¡ }|st‚|S )a^  
            Returns the next line from the input, or raises ``StopIteration``
            when EOF is hit.  Unlike python file objects, it's okay to mix
            calls to `.next` and `.readline`.

            :raises: ``StopIteration`` -- when the end of the file is reached.

            :returns: a line (`str`) read from the file.
            r.   r1   r#   r#   r$   Ú__next__s   s    
zBufferedFile.__next__c                 C   s   | j | j@ | jkS )z±
        Check if the file can be read from.

        :returns:
            `True` if the file can be read from. If `False`, `read` will raise
            an exception.
        )r   Ú	FLAG_READr!   r#   r#   r$   Úreadable‚   s    zBufferedFile.readablec                 C   s   | j | j@ | jkS )z´
        Check if the file can be written to.

        :returns:
            `True` if the file can be written to. If `False`, `write` will
            raise an exception.
        )r   Ú
FLAG_WRITEr!   r#   r#   r$   ÚwritableŒ   s    zBufferedFile.writablec                 C   s   dS )z½
        Check if the file supports random access.

        :returns:
            `True` if the file supports random access. If `False`, `seek` will
            raise an exception.
        Fr#   r!   r#   r#   r$   Úseekable–   s    zBufferedFile.seekablec                 C   s&   |   t|ƒ¡}||dt|ƒ…< t|ƒS )z°
        Read up to ``len(buff)`` bytes into ``bytearray`` *buff* and return the
        number of bytes read.

        :returns:
            The number of bytes read.
        N)ÚreadÚlen)r"   ZbuffÚdatar#   r#   r$   Úreadinto    s    zBufferedFile.readintoNc                 C   sè  | j rtdƒ‚| j| j@ s"tdƒ‚|dks2|dk rÎt| jƒ}tƒ | _|  jt|ƒ7  _z|  	| j
¡}W n tk
r~   d}Y nX |dksÆt|ƒdkr–qÆ| |¡ |  jt|ƒ7  _|  jt|ƒ7  _qVt|ƒS |t| jƒkr| jd|… }| j|d… | _|  jt|ƒ7  _|S t| jƒ|k r´|t| jƒ }| j| j@ rJt| j|ƒ}z|  	|¡}W n tk
rr   d}Y nX |dks´t|ƒdkrq´|  j|7  _|  jt|ƒ7  _q| jd|… }| j|d… | _|  jt|ƒ7  _|S )a™  
        Read at most ``size`` bytes from the file (less if we hit the end of
        the file first).  If the ``size`` argument is negative or omitted,
        read all the remaining data in the file.

        .. note::
            ``'b'`` mode flag is ignored (``self.FLAG_BINARY`` in
            ``self._flags``), because SSH treats all files as binary, since we
            have no idea what encoding the file is in, or even if the file is
            text data.

        :param int size: maximum number of bytes to read
        :returns:
            data read from the file (as bytes), or an empty string if EOF was
            encountered immediately
        úFile is closedzFile is not open for readingNr   )r   ÚIOErrorr   r5   Ú	bytearrayr   r   r   r;   Ú_readr   ÚEOFErrorÚextendr   ÚFLAG_BUFFEREDÚmaxr   )r"   ÚsizeÚresultÚnew_dataÚ	read_sizer#   r#   r$   r:   ¬   sN    



zBufferedFile.readc           
      C   sÔ  | j rtdƒ‚| j| j@ s"tdƒ‚| j}d}| jr~| j| j@ r~t|ƒdkr~|d tkrn|dd… }|  	t
¡ n
|  	t¡ d| _|dk	rÊ|dkrÊt|ƒ|kr¼||d… | _|d|… }d}q‚|t|ƒ }n| j}t|ksì| j| j@ rðt|krðq‚z|  |¡}W n tk
r   d}Y nX |dks2t|ƒdkrftƒ | _|  jt|ƒ7  _| j| j@ r^|S t|ƒS ||7 }|  jt|ƒ7  _q,| t¡}| j| j@ rÆ| t¡}|dkrÆ||k sÂ|dk rÆ|}|dkrü|  jt|ƒ7  _| j| j@ rô|S t|ƒS |d }|| tkr6|t|ƒk r6|| tkr6|d7 }|rR||d… | j | _n||d… | _|||… }	|d|… t }t| jƒdkrž|	tkržd| _n
|  	|	¡ |  jt|ƒ7  _| j| j@ rÌ|S t|ƒS )	aÍ  
        Read one entire line from the file.  A trailing newline character is
        kept in the string (but may be absent when a file ends with an
        incomplete line).  If the size argument is present and non-negative, it
        is a maximum byte count (including the trailing newline) and an
        incomplete line may be returned.  An empty string is returned only when
        EOF is encountered immediately.

        .. note::
            Unlike stdio's ``fgets``, the returned string contains null
            characters (``'\0'``) if they occurred in the input.

        :param int size: maximum length of returned string.
        :returns:
            next line of the file, or an empty string if the end of the
            file has been reached.

            If the file was opened in binary (``'b'``) mode: bytes are returned
            Else: the encoding of the file is assumed to be UTF-8 and character
            strings (`str`) are returned
        r>   zFile not open for readingFr   r   NTéÿÿÿÿ)r   r?   r   r5   r   r   ÚFLAG_UNIVERSAL_NEWLINEr;   r   Ú_record_newliner   r   r   r   rA   rB   r   r   ÚFLAG_BINARYr	   r   Úfindr   )
r"   rF   r2   Z	truncatedÚnrH   ÚposÚrposZxposÚlfr#   r#   r$   r/   ç   s†    ÿ
þ
ý

ÿÿ




ÿ
þ
ý
zBufferedFile.readlinec                 C   sL   g }d}|   ¡ }t|ƒdkrqH| |¡ |t|ƒ7 }|dk	r||krqHq|S )a®  
        Read all remaining lines using `readline` and return them as a list.
        If the optional ``sizehint`` argument is present, instead of reading up
        to EOF, whole lines totalling approximately sizehint bytes (possibly
        after rounding up to an internal buffer size) are read.

        :param int sizehint: desired maximum number of bytes to read.
        :returns: list of lines read from the file.
        r   N)r/   r;   Úappend)r"   ÚsizehintÚlinesZ
byte_countr2   r#   r#   r$   Ú	readlinesP  s    

zBufferedFile.readlinesc                 C   s   t dƒ‚dS )a¬  
        Set the file's current position, like stdio's ``fseek``.  Not all file
        objects support seeking.

        .. note::
            If a file is opened in append mode (``'a'`` or ``'a+'``), any seek
            operations will be undone at the next write (as the file position
            will move back to the end of the file).

        :param int offset:
            position to move to within the file, relative to ``whence``.
        :param int whence:
            type of movement: 0 = absolute; 1 = relative to the current
            position; 2 = relative to the end of the file.

        :raises: ``IOError`` -- if the file doesn't support random access.
        zFile does not support seeking.N©r?   )r"   ÚoffsetÚwhencer#   r#   r$   Úseekf  s    zBufferedFile.seekc                 C   s   | j S )zù
        Return the file's current position.  This may not be accurate or
        useful if the underlying file doesn't support random access, or was
        opened in append mode.

        :returns: file position (`number <int>` of bytes).
        )r   r!   r#   r#   r$   Útellz  s    zBufferedFile.tellc                 C   sî   t |tƒr| d¡}| jr"tdƒ‚| j| j@ s6tdƒ‚| j| j@ sP|  |¡ dS | j	 
|¡ | j| j@ rÒ| t¡}|dkrÎ| j	 ¡ }|t|ƒt|ƒ 7 }|  |d|d … ¡ tƒ | _	| j	 
||d d… ¡ dS | j	 ¡ | jkrê|  ¡  dS )a8  
        Write data to the file.  If write buffering is on (``bufsize`` was
        specified and non-zero), some or all of the data may not actually be
        written yet.  (Use `flush` or `close` to force buffered data to be
        written out.)

        :param data: ``str``/``bytes`` data to write
        zutf-8r>   zFile not open for writingNr   r   )Ú
isinstancer   Úencoder   r?   r   r7   rD   r,   r   ÚwriteÚFLAG_LINE_BUFFEREDÚrfindr   r-   r;   r   r[   r   r+   )r"   r<   Zlast_newline_posZwbufr#   r#   r$   r^   „  s,    	




zBufferedFile.writec                 C   s   |D ]}|   |¡ qdS )a?  
        Write a sequence of strings to the file.  The sequence can be any
        iterable object producing strings, typically a list of strings.  (The
        name is intended to match `readlines`; `writelines` does not add line
        separators.)

        :param sequence: an iterable sequence of strings.
        N)r^   )r"   Úsequencer2   r#   r#   r$   Ú
writelines¨  s    	zBufferedFile.writelinesc                 C   s   | S )z
        Identical to ``iter(f)``.  This is a deprecated file interface that
        predates Python iterator support.
        r#   r!   r#   r#   r$   Ú
xreadlinesµ  s    zBufferedFile.xreadlinesc                 C   s   | j S r&   )r   r!   r#   r#   r$   Úclosed¼  s    zBufferedFile.closedc                 C   s
   t ƒ ‚dS )zˆ
        (subclass override)
        Read data from the stream.  Return ``None`` or raise ``EOFError`` to
        indicate EOF.
        N)rB   )r"   rF   r#   r#   r$   rA   Â  s    zBufferedFile._readc                 C   s   t dƒ‚dS )zI
        (subclass override)
        Write data into the stream.
        zwrite not implementedNrW   )r"   r<   r#   r#   r$   Ú_writeÊ  s    zBufferedFile._writec                 C   s   dS )ai  
        (subclass override)
        Return the size of the file.  This is called from within `_set_mode`
        if the file is opened in append mode, so the file position can be
        tracked and `seek` and `tell` will work correctly.  If the file is
        a stream that can't be randomly accessed, you don't need to override
        this method,
        r   r#   r!   r#   r#   r$   Ú	_get_sizeÑ  s    	zBufferedFile._get_sizeÚrrJ   c                 C   s:  | j | _|dk rd}|dkr4|  j| j| jB O  _nR|dkrf|| _|  j| jO  _|  j| j M  _n |dkr†|  j| j| jB  M  _d|ks–d|kr¦|  j| jO  _d|ks¶d|krÆ|  j| jO  _d|krü|  j| j| jB O  _|  ¡ | _	| j	 | _
| _d|kr|  j| jO  _d|kr6|  j| jO  _d	| _d	S )
zM
        Subclasses call this method to initialize the BufferedFile.
        r   r   rg   ú+ÚwÚaÚbÚUN)r   r   r   rD   r_   r5   r7   ÚFLAG_APPENDrf   r    r   r   rM   rK   r   )r"   ÚmodeÚbufsizer#   r#   r$   Ú	_set_modeÞ  s0    


zBufferedFile._set_modec                 C   sv   t |ƒ}t|ƒdkrr|  |¡}||d … }| j| j@ rT|  j|7  _| j | _| _q|  j|7  _|  j|7  _qd S )Nr   )Ú
memoryviewr;   re   r   rm   r    r   r   )r"   Úraw_datar<   Úcountr#   r#   r$   r,     s    
zBufferedFile._write_allc                 C   sd   | j | j@ sd S | jd kr"|| _n>| j|krFt| jtƒrF| j|f| _n|| jkr`|  j|f7  _d S r&   )r   rK   r   r\   r
   )r"   Únewliner#   r#   r$   rL     s    
 ÿ
zBufferedFile._record_newline)N)N)N)r   )rg   rJ   )+Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ÚSEEK_SETÚSEEK_CURÚSEEK_ENDr5   r7   rm   rM   rD   r_   rK   r%   r(   r*   r'   r+   r   r3   r4   r6   r8   r9   r=   r:   r/   rV   rZ   r[   r^   rb   rc   Úpropertyrd   rA   re   rf   rp   r,   rL   r#   r#   r#   r$   r      sP   	




;
i


$

(r   N)Zparamiko.commonr   r   r   r   r   Zparamiko.py3compatr   r   r	   r
   r   Zparamiko.utilr   r   r#   r#   r#   r$   Ú<module>   s   