o
    .&ßaÈ>  ã                   @   sÄ   d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZ d dl	m
Z
mZ d dl	mZmZmZmZ d dlmZ d dlmZ eZd	d
„ Zdd„ ZG dd„ deƒZG dd„ deƒZG dd„ deƒZdS )é    N)Úparse)Útzlocal)ÚClientError)Úfind_bucket_keyÚget_file_stat)ÚBucketListerÚcreate_warningÚfind_dest_path_comp_keyÚ
EPOCH_TIME)Úsix)Úqueuec                 C   sH   t  | ¡j}t |¡rdS t |¡rdS t |¡rdS t |¡r"dS dS )z�
    This function checks to see if a special file.  It checks if the
    file is a character special device, block special device, FIFO, or
    socket.
    TF)ÚosÚstatÚst_modeÚS_ISCHRÚS_ISBLKÚS_ISFIFOÚS_ISSOCK)ÚpathÚmode© r   úH/usr/lib/python3/dist-packages/awscli/customizations/s3/filegenerator.pyÚis_special_file   s   



r   c              	   C   s„   t j | ¡rzt  | ¡ W dS  ttfy   Y dS w zt| dƒ�
}W d  ƒ W dS 1 s.w   Y  W dS  ttfyA   Y dS w )zµ
    This function checks to see if a file or a directory can be read.
    This is tested by performing an operation that requires read access
    on the file or the directory.
    FÚrNT)r   r   ÚisdirÚlistdirÚOSErrorÚIOErrorÚ_open)r   Úfdr   r   r   Úis_readable4   s"   	øÿÿüþÿr    c                       s,   e Zd ZdZde ¡  Z‡ fdd„Z‡  ZS )ÚFileDecodingErrorz1Raised when there was an issue decoding the file.z€Please check your locale settings.  The filename was decoded as: %s
On posix platforms, check the LC_CTYPE environment variable.c                    s<   || _ || _dt| jƒ| j | jf | _tt| ƒ | j¡ d S )NzJThere was an error trying to decode the the file %s in directory "%s". 
%s)Ú	directoryÚ	file_nameÚreprÚADVICEÚerror_messageÚsuperr!   Ú__init__)Úselfr"   Úfilename©Ú	__class__r   r   r(   S   s   þÿÿzFileDecodingError.__init__)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚsysÚgetfilesystemencodingr%   r(   Ú__classcell__r   r   r+   r   r!   J   s    þÿr!   c                   @   s   e Zd Z			ddd„ZdS )ÚFileStatNc
           
      C   s:   || _ || _|| _|| _|| _|| _|| _|| _|	| _d S ©N)	ÚsrcÚdestÚcompare_keyÚsizeÚlast_updateÚsrc_typeÚ	dest_typeÚoperation_nameÚresponse_data)
r)   r6   r7   r8   r9   r:   r;   r<   r=   r>   r   r   r   r(   `   s   
zFileStat.__init__)NNNNNNNN)r-   r.   r/   r(   r   r   r   r   r4   _   s
    þr4   c                   @   sv   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S )ÚFileGeneratora}  
    This is a class the creates a generator to yield files based on information
    returned from the ``FileFormat`` class.  It is universal in the sense that
    it will handle s3 files, local files, local directories, and s3 objects
    under the same common prefix.  The generator yields corresponding
    ``FileInfo`` objects to send to a ``Comparator`` or ``S3Handler``.
    TNc                 C   sH   || _ || _|| _|| _|| _|st ¡ | _i | _|d ur"|| _d S d S r5   )Ú_clientr=   Úfollow_symlinksÚ	page_sizeÚresult_queuer   ÚQueueÚrequest_parameters)r)   Úclientr=   rA   rB   rC   rE   r   r   r   r(   v   s   

ÿzFileGenerator.__init__c                 c   s–   � | j | jdœ}|d d }|d d }|d d }|| ||d ƒ}|D ]#\}}t||ƒ\}	}
||	|
||| jdœ}|  ||¡ td	i |¤ŽV  q%dS )
zì
        This is the generalized function to yield the ``FileInfo`` objects.
        ``dir_op`` and ``use_src_name`` flags affect which files are used and
        ensure the proper destination paths and compare keys are formed.
        )Ús3Úlocalr6   r   Útyper7   Údir_op)r6   r7   r8   r;   r<   r=   Nr   )Úlist_objectsÚ
list_filesr	   r=   Ú_inject_extra_informationr4   )r)   ÚfilesÚfunction_tableÚsourcer;   r<   Úfile_iteratorÚsrc_pathÚextra_informationÚ	dest_pathr8   Úfile_stat_kwargsr   r   r   Úcallƒ   s   €ýøzFileGenerator.callc                 C   s8   |d }|d |d< |d |d< |dkr||d< d S d S )Nr;   ÚSizer9   ÚLastModifiedr:   rG   r>   r   )r)   rU   rS   r;   r   r   r   rM   ˜   s   ÿz'FileGenerator._inject_extra_informationc                 c   s  � t jjt jjt jj}}}t jt j}}|  |¡s}|s+|  |¡}|r)|V  dS dS ||ƒ}	g }
|	D ]}|  	||¡sO|||ƒ}||ƒrJ|t jj
 }|
 |¡ q3|  |
t j
d¡ |
D ]$}|||ƒ}||ƒrr|  ||¡D ]}|V  qkqZ|  |¡}|r||V  qZdS dS )a{  
        This function yields the appropriate local file or local files
        under a directory depending on if the operation is on a directory.
        For directories a depth first search is implemented in order to
        follow the same sorted pattern as a s3 list objects operation
        outputs.  It yields the file's source path, size, and last
        update
        ú/N)r   r   Újoinr   ÚisfileÚerrorr   Úshould_ignore_fileÚ_safely_get_file_statsÚ)should_ignore_file_with_decoding_warningsÚsepÚappendÚnormalize_sortrL   )r)   r   rJ   rZ   r   r[   r\   r   ÚstatsÚlistdir_namesÚnamesÚnameÚ	file_pathÚxr   r   r   rL   ¢   sB   €	


ÿÿ

€
ÿ
€ÙzFileGenerator.list_filesc              	   C   sN   zt |ƒ\}}W n ttfy   |  |¡ Y d S w |  ||¡}|||dœfS )N©rW   rX   )r   r   Ú
ValueErrorÚtriggers_warningÚ_validate_update_time)r)   rg   r9   r:   r   r   r   r^   Ö   s   ÿz$FileGenerator._safely_get_file_statsc                 C   s*   |d u rt |ddd�}| j |¡ tS |S )Nz?File has an invalid timestamp. Passing epoch time as timestamp.F)r   r&   Ú	skip_file)r   rC   Úputr
   )r)   Úupdate_timer   Úwarningr   r   r   rl   ß   s   üz#FileGenerator._validate_update_timec                    s   |j ‡ ‡fdd„d� dS )a  
        The purpose of this function is to ensure that the same path seperator
        is used when sorting.  In windows, the path operator is a backslash as
        opposed to a forward slash which can lead to differences in sorting
        between s3 and a windows machine.
        c                    s   |   ˆˆ ¡S r5   )Úreplace)Úitem©Ú	characterÚos_sepr   r   Ú<lambda>ò   s    z.FileGenerator.normalize_sort.<locals>.<lambda>)ÚkeyN)Úsort)r)   re   ru   rt   r   rs   r   rb   ë   s   zFileGenerator.normalize_sortc                 C   sN   t |tjƒst||ƒ}tt|ƒ|jƒ}| j |¡ dS t	j
 ||¡}|  |¡S )a�  
        We can get a UnicodeDecodeError if we try to listdir(<unicode>) and
        can't decode the contents with sys.getfilesystemencoding().  In this
        case listdir() returns the bytestring, which means that
        join(<unicode>, <str>) could raise a UnicodeDecodeError.  When this
        happens we warn using a FileDecodingError that provides more
        information into what's going on.
        T)Ú
isinstancer   Ú	text_typer!   r   r$   r&   rC   rn   r   r   rZ   r]   )r)   Údirnamer*   Údecoding_errorrp   r   r   r   r   r_   ô   s   	
ÿ
z7FileGenerator.should_ignore_file_with_decoding_warningsc                 C   sP   | j stj |¡r| tj¡r|dd… }tj |¡rdS |  |¡}|r&dS dS )zÍ
        This function checks whether a file should be ignored in the
        file generation process.  This includes symlinks that are not to be
        followed and files that generate warnings.
        NéÿÿÿÿTF)rA   r   r   r   Úendswithr`   Úislinkrk   )r)   r   Úwarning_triggeredr   r   r   r]     s   
z FileGenerator.should_ignore_filec                 C   sn   t j |¡st|dƒ}| j |¡ dS t|ƒr$t|dƒ}| j |¡ dS t|ƒs5t|dƒ}| j |¡ dS dS )aÖ  
        This function checks the specific types and properties of a file.
        If the file would cause trouble, the function adds a
        warning to the result queue to be printed out and returns a boolean
        value notify whether the file caused a warning to be generated.
        Files that generate warnings are skipped.  Currently, this function
        checks for files that do not exist and files that the user does
        not have read access.
        zFile does not exist.TzHFile is character special device, block special device, FIFO, or socket.zFile/Directory is not readable.F)r   r   Úexistsr   rC   rn   r   r    )r)   r   rp   r   r   r   rk     s   

ÿ
zFileGenerator.triggers_warningc           
      c   s¨   � t |ƒ\}}|s|r|  |¡V  dS t| jƒ}| j di ¡}|j||| j|d�D ](}|\}}	|	d dkrE| d¡rE| j	dkrD||	fV  q)|sL||krLq)||	fV  q)dS )zð
        This function yields the appropriate object or objects under a
        common prefix depending if the operation is on objects under a
        common prefix.  It yields the file's source path, size, and last
        update.
        ÚListObjectsV2)ÚbucketÚprefixrB   Ú
extra_argsrW   r   rY   ÚdeleteN)
r   Ú_list_single_objectr   r@   rE   ÚgetrK   rB   r~   r=   )
r)   Ús3_pathrJ   rƒ   r„   Úlisterr…   rw   Úsource_pathr>   r   r   r   rK   2  s&   €


þ

€ðzFileGenerator.list_objectsc              
   C   sà   | j dkr|d d dœfS t|ƒ\}}z||dœ}| | j di ¡¡ | jjdi |¤Ž}W n( tyT } z|jd d dks>‚ |j 	¡ }d| |d d	< t|dƒ‚d }~ww t
| d
¡ƒ|d< t|d ƒ}| tƒ ¡|d< ||fS )Nr†   ri   )ÚBucketÚKeyÚ
HeadObjectÚErrorÚCodeÚ404zKey "%s" does not existÚMessageÚContentLengthrW   rX   r   )r=   r   ÚupdaterE   rˆ   r@   Úhead_objectr   ÚresponseÚcopyÚintÚpopr   Ú
astimezoner   )r)   r‰   rƒ   rw   Úparamsr–   Úer:   r   r   r   r‡   T  s&   



€öz!FileGenerator._list_single_object)TNNN)r-   r.   r/   r0   r(   rV   rM   rL   r^   rl   rb   r_   r]   rk   rK   r‡   r   r   r   r   r?   n   s     
ÿ
4		"r?   )r   r1   r   Údateutil.parserr   Údateutil.tzr   Úbotocore.exceptionsr   Úawscli.customizations.s3.utilsr   r   r   r   r	   r
   Úawscli.compatr   r   Úopenr   r   r    Ú	Exceptionr!   Úobjectr4   r?   r   r   r   r   Ú<module>   s    