o
    !d>                     @   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   Jusr/lib/python3.10/site-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.zPlease 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)   Z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)   filesZfunction_tablesourcer;   r<   Zfile_iteratorZsrc_pathextra_informationZ	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:   rF   r>   r   )r)   rP   rO   r;   r   r   r   rL      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_sortrK   )r)   r   rI   rU   r   rV   rW   r   ZstatsZlistdir_namesnamesname	file_pathxr   r   r   rK      sB   	






zFileGenerator.list_filesc              	   C   sN   zt |\}}W n ttfy   | | Y d S w | ||}|||dfS )NrR   rS   )r   r   
ValueErrortriggers_warning_validate_update_time)r)   r`   r9   r:   r   r   r   rY      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&   Z	skip_file)r   rC   putr
   )r)   Zupdate_timer   warningr   r   r   re      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 separator
        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)   r^   rl   rk   r   rj   r   r]      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   Z	text_typer!   r   r$   r&   rC   rf   r   r   rU   rX   )r)   dirnamer*   Zdecoding_errorrg   r   r   r   r   rZ      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.
        NTF)rA   r   r   r   endswithr[   islinkrd   )r)   r   Zwarning_triggeredr   r   r   rX     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   rf   r   r    )r)   r   rg   r   r   r   rd     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.
        ZListObjectsV2)bucketprefixrB   
extra_argsrR   r   rT   deleteN)
r   _list_single_objectr   r@   rE   getrJ   rB   rs   r=   )
r)   s3_pathrI   rv   rw   Zlisterrx   rn   source_pathr>   r   r   r   rJ   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 )Nry   rb   )ZBucketKeyZ
HeadObjectErrorZCodeZ404zKey "%s" does not existMessageZContentLengthrR   rS   r   )r=   r   updaterE   r{   r@   Zhead_objectr   responsecopyintpopr   
astimezoner   )r)   r|   rv   rn   paramsr   er:   r   r   r   rz   T  s&   



z!FileGenerator._list_single_object)TNNN)r-   r.   r/   r0   r(   rQ   rL   rK   rY   re   r]   rZ   rX   rd   rJ   rz   r   r   r   r   r?   n   s     

4		"r?   )r   r1   r   Zdateutil.parserr   Zdateutil.tzr   Zbotocore.exceptionsr   Zawscli.customizations.s3.utilsr   r   r   r   r	   r
   Zawscli.compatr   r   openr   r   r    	Exceptionr!   objectr4   r?   r   r   r   r   <module>   s    