U
    ꥡc5                     @   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m	Z	m
Z
mZmZmZmZmZmZmZmZ ddlmZmZmZmZ ddlmZ edZG dd deZG d	d
 d
eZdS )u   
:module: watchdog.observers.fsevents
:synopsis: FSEvents based emitter implementation.
:author: yesudeep@google.com (Yesudeep Mangalapilly)
:author: contact@tiger-222.fr (Mickaël Schoentgen)
:platforms: macOS
    N)
FileDeletedEventFileModifiedEventFileCreatedEventFileMovedEventDirDeletedEventDirModifiedEventDirCreatedEventDirMovedEventgenerate_sub_created_eventsgenerate_sub_moved_events)BaseObserverEventEmitterDEFAULT_EMITTER_TIMEOUTDEFAULT_OBSERVER_TIMEOUT)DirectorySnapshotZfseventsc                       s   e Zd ZdZedf f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dd Zdd Zdd Zdd Zdd  Z  ZS )!FSEventsEmittera5  
    macOS FSEvents Emitter class.

    :param event_queue:
        The event queue to fill with events.
    :param watch:
        A watch object representing the directory to monitor.
    :type watch:
        :class:`watchdog.observers.api.ObservedWatch`
    :param timeout:
        Read events blocking timeout (in seconds).
    :param suppress_history:
        The FSEvents API may emit historic events up to 30 sec before the watch was
        started. When ``suppress_history`` is ``True``, those events will be suppressed
        by creating a directory snapshot of the watched path before starting the stream
        as a reference to suppress old events. Warning: This may result in significant
        memory usage in case of a large number of items in the watched path.
    :type timeout:
        ``float``
    Fc                    sZ   t  ||| t | _|| _d| _d | _t | _	t
jt
jt
j| jj| _d S )Ng        )super__init__set_fs_viewsuppress_history_start_time_starting_state	threadingLock_lockospathrealpathabspath
expanduserwatch_absolute_watch_path)selfZevent_queuer!   timeoutr   	__class__ ?/tmp/pip-unpacked-wheel-thtqfo2i/watchdog/observers/fsevents.pyr   P   s    
zFSEventsEmitter.__init__c                 C   s   t | j t |  d S N)	_fseventsZremove_watchr!   stopr#   r'   r'   r(   on_thread_stopY   s    zFSEventsEmitter.on_thread_stopc                 C   sV   | j jr"td| t| | n0| |sFtd| t| | ntd| d S )Nzqueue_event %szdrop event %s)Z_watchZis_recursiveloggerdebugr   queue_event_is_recursive_event)r#   eventr'   r'   r(   r0   ]   s    
zFSEventsEmitter.queue_eventc                 C   sV   |j r|jntj|j}|| jkr(dS t|ttfrRtj|j	}|| jkrRdS dS )NFT)
is_directorysrc_pathr   r   dirnamer"   
isinstancer   r	   	dest_path)r#   r2   r4   r7   r'   r'   r(   r1   j   s    

z#FSEventsEmitter._is_recursive_eventc                 C   s.   |j r
tnt}| || | t| d S r)   )r3   r   r   r0   r   r#   r2   r4   r5   clsr'   r'   r(   _queue_created_eventx   s    z$FSEventsEmitter._queue_created_eventc                 C   s.   |j r
tnt}| || | t| d S r)   )r3   r   r   r0   r   r8   r'   r'   r(   _queue_deleted_event}   s    z$FSEventsEmitter._queue_deleted_eventc                 C   s    |j r
tnt}| || d S r)   )r3   r   r   r0   r8   r'   r'   r(   _queue_modified_event   s    z%FSEventsEmitter._queue_modified_eventc                 C   sH   |j r
tnt}| |}| ||| | t| | t| d S r)   )r3   r	   r   _encode_pathr0   r   )r#   Z	src_eventr4   dst_pathsrc_dirnamedst_dirnamer9   r'   r'   r(   _queue_renamed_event   s
    
z$FSEventsEmitter._queue_renamed_eventc                 C   sZ   |j | jk}| jrNz | j |jd }||j k}W qR tk
rJ   d}Y qRX nd}|pX|S )Nr   F)inoder   r   r   KeyError)r#   r2   Z
in_historyZ	old_inodeZbefore_startr'   r'   r(   _is_historic_created_event   s    z*FSEventsEmitter._is_historic_created_eventc                 C   s   | j p| jp| jS )z9Returns True if the event indicates a change in metadata.)Zis_inode_meta_modZis_xattr_modZis_owner_changer2   r'   r'   r(   _is_meta_mod   s    zFSEventsEmitter._is_meta_modc                    s   t  tjkrH|D ]4 d fddt D }t   d|  qt | j	 dkr`d | _
|r|d |  j}tj|}zt|}W n tk
r   d }Y nX |o|j jk} jr8 jr8|  s|  || | j j  js
|  r|  || |  || | j j n jrZ|  sZ|  || | j j  js||  r|  ||  jrt t! fdd|D d }|rft d| | |j}	tj|	}
| " ||	||
 | j j t#||	D ]}| $| q|%| |js2| |r@| ||	|
 |jr| ||	|
 | j|j n\|r|  || | j j t&|D ]}| $| qn|  || | j j q` jr|  || | j j  j'r`| $t(| j)j t d	 | *  | j+  q`d S )
Nz, c                 3   s    | ]}t  |d kr|V  qdS )TN)getattr).0attrrE   r'   r(   	<genexpr>   s      z/FSEventsEmitter.queue_events.<locals>.<genexpr>z: <   r   c                 3   s$   | ]}|j r|j jkr|V  qd S r)   )
is_renamedrB   )rH   erE   r'   r(   rJ      s       z"Destination event for rename is %sz&Stopping because root path was changed),r.   getEffectiveLevelloggingDEBUGjoindirr/   time	monotonicr   r   popr=   r   r   r5   statOSErrorst_inorB   Z
is_createdZ
is_removedrD   r:   r   addZis_modifiedrF   r<   r;   discardrL   nextiterrA   r   r0   remover
   Zis_root_changedr   r!   r+   clear)r#   r$   eventsflagsr4   r?   rV   existsZ	dst_eventr>   r@   Z	sub_eventr'   rE   r(   queue_events   sx    




zFSEventsEmitter.queue_eventsc              	      sj   t j z@ fddt||||D }| j | | j| W 5 Q R X W n tk
rd   td Y nX dS )zhCallback passed to FSEventStreamCreate(), it will receive all
        FS events and queue them.
        c                    s"   g | ]\}}}} ||||qS r'   r'   )rH   r   rB   Zevent_flagsZevent_idr9   r'   r(   
<listcomp>,  s   
z3FSEventsEmitter.events_callback.<locals>.<listcomp>z(Unhandled exception in fsevents callbackN)	r*   ZNativeEventzipr   rb   r$   	Exceptionr.   	exception)r#   pathsinodesr`   idsr_   r'   rc   r(   events_callback&  s    
   zFSEventsEmitter.events_callbackc                 C   s^   | j jg| _t | _z$t| | j | j| j t	|  W n t
k
rX   td Y nX d S )Nz&Unhandled exception in FSEventsEmitter)r!   r   Z	pathnamesrS   rT   r   r*   Z	add_watchrk   read_eventsrf   r.   rg   r,   r'   r'   r(   run7  s    
zFSEventsEmitter.runc                 C   s:   | j r6t| jjtr$t| jj}n| jj}t|| _d S r)   )	r   r6   r!   r   bytesr   fsdecoder   r   )r#   Z
watch_pathr'   r'   r(   on_thread_start@  s
    zFSEventsEmitter.on_thread_startc                 C   s   t | jjtrt|S |S )z7Encode path only if bytes were passed to this emitter. )r6   r!   r   rn   r   fsencode)r#   r   r'   r'   r(   r=   J  s    
zFSEventsEmitter._encode_path)__name__
__module____qualname____doc__r   r   r-   r0   r1   r:   r;   r<   rA   rD   staticmethodrF   rb   rk   rm   rp   r=   __classcell__r'   r'   r%   r(   r   9   s$   	
 	
r   c                       s*   e Zd Zef fdd	ZdddZ  ZS )FSEventsObserverc                    s   t  jt|d d S )N)Zemitter_classr$   )r   r   r   )r#   r$   r%   r'   r(   r   S  s    zFSEventsObserver.__init__Fc                 C   s&   t |trtd|}t| |||S )NNFC)r6   strunicodedata	normalizer   schedule)r#   Zevent_handlerr   	recursiver'   r'   r(   r}   V  s    
zFSEventsObserver.schedule)F)rr   rs   rt   r   r   r}   rw   r'   r'   r%   r(   rx   Q  s   rx   )ru   rS   rO   r   r   r{   Z_watchdog_fseventsr*   Zwatchdog.eventsr   r   r   r   r   r   r   r	   r
   r   Zwatchdog.observers.apir   r   r   r   Zwatchdog.utils.dirsnapshotr   	getLoggerr.   r   rx   r'   r'   r'   r(   <module>   s   0
  