U
    ")3ga                     @  s  d Z ddlm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 ddlmZ ddlmZ ddlmZ ddlmZmZmZ dd	lmZ erdd
lmZ ejejd dZdZG dd deZdZe
eedZ e j!dded e j"ddZ#i Z$dd Z%g e#g fddZ&ej'fddZ(dddZ)dd  Z*dd"d#Z+d$d% Z,d&d' Z-e&e%d(d)d*d+e%d,d-d.ej'd/d0e%d1d2d3d4e.d5d6e%d7d8d9d:d;e%d<d8d=d>e%d?d8d@d>e%dAd8dBd>e%dCd8dDd>e%dEd8dFd>g	dgdGdHdI Z/e&e%dJd)dKd+e%d,d-d.ej'd/d0e%dLddMd0e%dNdOdPd8dQdRgdSgdGdTdU Z0e&e%dVd)d-dWdXe%dYdZd[d\d)d]d^e%d_d`dadbdcddd^e%dedfdgd8dhdRe%did7djd8dkdRe%d1d2d3d4e.dld6e%dmd8dnd>e%d<d8d=d>e%d?d8d@d>e%dAd8dBd>e%dCd8dDd>e%dEd8dFd>gdodp Z1e&e%dVd)d-dqdXe%drdsdddtd^e%dYdZd[d\d)d]d^e%d_d`dadbdcddd^e%dedfdgdud8dhdve%did7djd8dkdRe%d1d2d3d4e.dld6e%dwdxdyd8dzdRe%d{d|d}d8d~dRe%d<d8d=d>g
dd Z2e&e%ddde%ddd)dde%dddVdddde%dYdZd[d\d)d]d^e%d_d`dadbdcddd^e%dedfdgdud8dhdve%did7djd8dkdRe%d1d2d3d4e.dld6e%ddddd^e%d<d8d=d>e%ddde.dd6e%ddde.dd6e%ddd9dddvgdd Z3G dd de4Z5dd Z6dd Z7e8dkre9e7  dS )u   :module: watchdog.watchmedo
:author: yesudeep@google.com (Yesudeep Mangalapilly)
:author: contact@tiger-222.fr (Mickaël Schoentgen)
:synopsis: ``watchmedo`` shell script utility.
    )annotationsN)ArgumentParserRawDescriptionHelpFormatter)StringIO)dedent)TYPE_CHECKING)WatchdogShutdown
load_classplatform)VERSION_STRING)BaseObserverSubclassCallable)leveltrickszpython-pathc                      s.   e Zd ZdZdd fdd
Zdd Z  ZS )HelpFormattera#  A nicer help formatter.

    Help for arguments can be indented and contain new lines.
    It will be de-dented and arguments in the help
    will be separated by a blank line for better readability.

    Source: https://github.com/httpie/httpie/blob/2423f89/httpie/cli/argparser.py#L31
       )max_help_positionc                  s   ||d< t  j|| d S )Nr   )super__init__)selfr   argskwargs	__class__ 6/tmp/pip-unpacked-wheel-cstuilrs/watchdog/watchmedo.pyr   :   s    zHelpFormatter.__init__c                 C  s   t | d }| S )Nz

)r   strip
splitlines)r   textwidthr   r   r   _split_lines?   s    zHelpFormatter._split_lines)__name__
__module____qualname____doc__r   r   __classcell__r   r   r   r   r   0   s   	r   zCopyright 2011 Yesudeep Mangalapilly <yesudeep@gmail.com>.
Copyright 2012 Google, Inc & contributors.

Licensed under the terms of the Apache license, version 2.0. Please see
LICENSE in the source code for more information.)epilogformatter_classz	--versionversion)actionr'   top_command)destc                  O  s   t | |fS )z\Convenience function to properly format arguments to pass to the
    command decorator.
    )list)Zname_or_flagsr   r   r   r   argumentQ   s    r,   c                   s    fdd}|S )a
  Decorator to define a new command in a sanity-preserving way.
    The function will be stored in the ``func`` variable when the parser
    parses arguments so that it can be called directly like so::

      >>> args = cli.parse_args()
      >>> args.func(args)

    c                   s   | j dd}t| j}j||td}|t|< | }|jdddddd	 |jd
ddddd	  D ]$}|j|d |d  |j	| d qf| S )N_-)descriptionaliasesr&   z-qz--quiet	verbosityappend_const)r*   r(   constz-vz	--verbose   r   )func)
r    replacer   r#   
add_parserr   command_parsersadd_mutually_exclusive_groupadd_argumentset_defaults)r6   namedescparserZverbosity_groupargr   cmd_aliasesparentr   r   	decoratorb   s    
zcommand.<locals>.decoratorr   )r   rC   rB   rD   r   rA   r   commandX   s    
rE   c                 C  s   t | |S )zSplits a pathname specification separated by an OS-dependent separator.

    :param pathname_spec:
        The pathname specification.
    :param separator:
        (OS Dependent) `:` on Unix and `;` on Windows or user-specified.
    )r+   split)Zpathname_spec	separatorr   r   r   
path_splitr   s    rH   c                 C  s&   | ddd D ]}t j|| qdS )zAdds specified paths at specified index into the sys.path list.

    :param paths:
        A list of paths to add to the sys.path
    :param index:
        (Default 0) The index in the sys.path list where the paths will be
        added.
    Nr3   )syspathinsert)	pathnamesindexpathnamer   r   r   add_to_sys_path}   s    	rO   c              
   C  s8   ddl }t| d}|| W  5 Q R  S Q R X dS )zLoads the YAML configuration from the specified file.

    :param tricks_file_path:
        The path to the tricks configuration file.
    :returns:
        A dictionary of configuration information.
    r   Nrb)yamlopenZ	safe_loadread)Ztricks_file_pathnamerQ   fr   r   r   load_config   s    rU   ;c                 C  s*   |  |}| |}|dgkr"g }||fS )z^Parses pattern argument specs and returns a two-tuple of
    (patterns, ignore_patterns).
     )rF   )Zpatterns_specZignore_patterns_specrG   patternsignore_patternsr   r   r   parse_patterns   s
    


rZ   c                 C  s^   t |D ]}| ||| q|   ztd q&W n tk
rP   |   Y nX |   dS )ag  Single observer thread with a scheduled path and event handler.

    :param observer:
        The observer thread.
    :param event_handler:
        Event handler which will be called in response to file system events.
    :param pathnames:
        A list of pathnames to monitor.
    :param recursive:
        ``True`` if recursive; ``False`` otherwise.
    r5   N)setschedulestarttimesleepr   stopjoin)observerZevent_handlerrL   	recursiverN   r   r   r   observe_with   s    rd   c           
      C  sT   |D ]J}t | D ]8\}}t|}|f |}t|ddp<|}	| ||	| qqdS )aj  Schedules tricks with the specified observer and for the given watch
    path.

    :param observer:
        The observer thread into which to schedule the trick and watch.
    :param tricks:
        A list of tricks.
    :param pathname:
        A path name which should be watched.
    :param recursive:
        ``True`` if recursive; ``False`` otherwise.
    source_directoryN)r+   itemsr	   getattrr\   )
rb   r   rN   rc   Ztrickr=   value
TrickClasshandlerZtrick_pathnamer   r   r   schedule_tricks   s    
rk   files*zperform tricks from given file)nargshelpz--python-path.zPaths separated by z to add to the Python path.)defaultro   z
--intervalz	--timeouttimeoutg      ?z?Use this as the polling interval/blocking timeout (in seconds).)r*   rq   typero   z--recursive
store_trueTz-Recursively monitor paths (defaults to True).)r(   rq   ro   z--debug-force-pollingz[debug] Forces polling.)r(   ro   z--debug-force-kqueuez[debug] Forces BSD kqueue(2).z--debug-force-winapiz[debug] Forces Windows API.z--debug-force-fseventsz[debug] Forces macOS FSEvents.z--debug-force-inotifyz [debug] Forces Linux inotify(7).)rB   c           
      C  s  | j rddlm} nl| jr(ddlm} nXts2| js>trLt	 rLddl
m} n4| jr`ddlm} n | jrtddlm} nddlm} tt| j g }| jD ]}|| jd}tj|sttjttj|t |}z|t! }W n< t"k
r } zt"d	t!d
|d|W 5 d}~X Y nX t#|kr2t|t#  tj$|pNtj%t& }t'|||| j( |)  |*| qzt+,d qvW n2 t-k
r   |D ]}	|	.  |	/  qY nX |D ]}	|	0  qdS )z;Command to execute tricks from a tricks configuration file.r   PollingObserverKqueueObserverWindowsApiObserverInotifyObserverFSEventsObserverObserverrr   zNo z key specified in rp   Nr5   )1debug_force_pollingwatchdog.observers.pollingrv   debug_force_kqueuewatchdog.observers.kqueuerx   r   debug_force_winapir
   
is_windows)watchdog.observers.read_directory_changesrz   debug_force_inotifywatchdog.observers.inotifyr|   debug_force_fseventswatchdog.observers.fseventsr~   watchdog.observersr   rO   rH   python_pathrl   rr   osrJ   existsOSErrorerrnoENOENTstrerrorrU   CONFIG_KEY_TRICKSKeyErrorCONFIG_KEY_PYTHON_PATHdirnamerelpathgetcwdrk   rc   r]   appendr^   r_   r   Zunschedule_allr`   ra   )
r   r   Z	observersZtricks_filerb   configr   eZdir_pathor   r   r   tricks_from   sH    1
*
r   trick_pathsz5Dotted paths for all the tricks you want to generate.z--append-to-filez
                   Appends the generated tricks YAML to a file.
                   If not specified, prints to standard output.z-az--append-onlyappend_onlyz
                   If --append-to-file is not specified, produces output for
                   appending instead of a complete tricks YAML file.)r*   r(   ro   zgenerate-tricks-yamlc           	   	   C  s   ddl }t| j}t| t }| jD ]}t|}||  q&|	 }|
  |t|i}|t d7 }| jdkr| js|| }tj| n<tj| js|| }t| jddd}|| W 5 Q R X dS )zLCommand to generate Yaml configuration for tricks named on the command line.r   Nz:
azutf-8)encoding)rQ   rH   r   rO   r   r   r	   writeZgenerate_yamlgetvalueclosedumpr   r   Zappend_to_filer   rI   stdoutr   rJ   r   rR   )	r   rQ   Zpython_pathsoutputZ
trick_pathri   contentheaderfiler   r   r   tricks_generate_yaml1  s&    !


r   directoriesz%Directories to watch. (default: '.').)rn   rq   ro   z-pz	--patternz
--patternsrX   z9Matches event paths with these patterns (separated by ;).)r*   rq   ro   z-iz--ignore-patternz--ignore-patternsrY   rW   z9Ignores event paths with these patterns (separated by ;).z-Dz--ignore-directoriesignore_directorieszIgnores events for directories.z-Rrc   z%Monitors the directories recursively.z2Use this as the polling interval/blocking timeout.z--tracez!Dumps complete dispatching trace.c                   s  ddl m} ddlm} | jr@t|j |j| fddd t	| j
| j\}}|||| jd}| jrvddlm} nl| jrdd	lm} nXts| jstrt rdd
lm} n4| jrddlm} n | jrddlm} nddlm } || j!d}t"||| j#| j$ dS )z1Command to log file system events to the console.r   )LoggerTrick)echoc                   s
     | S N)info)msgZclass_module_loggerr   r   <lambda>      zlog.<locals>.<lambda>)r   )rX   rY   r   ru   rw   ry   r{   r}   r   r   N)%watchdog.tricksr   watchdog.utilsr   tracelogging	getLoggerr!   Z
echo_classrZ   rX   rY   r   r   r   rv   r   r   rx   r   r   r
   r   r   rz   r   r   r|   r   r   r~   r   r   rr   rd   r   rc   )r   r   r   rX   rY   rj   r   rb   r   r   r   logm  s0    Hr   zDirectories to watch.z-cz	--commandam  
    Shell command executed in response to matching events.
    These interpolation variables are available to your command string:

        ${watch_src_path}   - event source path
        ${watch_dest_path}  - event destination path (for moved events)
        ${watch_event_type} - event type
        ${watch_object}     - 'file' or 'directory'

    Note:
        Please ensure you do not use double quotes (") to quote
        your command string. That will force your shell to
        interpolate before the command is processed by this
        command.

    Example:

        --command='echo "${watch_src_path}"'
    F)r*   rq   r(   ro   z-wz--waitwait_for_processzDWait for process to finish to avoid multiple simultaneous instances.z-Wz--dropdrop_during_processzhIgnore events that occur while command is still being executed to avoid multiple simultaneous instances.c                 C  s   ddl m} | jsd| _| jr,ddlm} nddlm} t| j	| j
\}}|| j||| j| j| jd}|| jd}t||| j| j dS )zDCommand to execute shell commands in response to file system events.r   )ShellCommandTrickNru   r   )shell_commandrX   rY   r   r   r   r   )r   r   rE   r   r   rv   r   r   rZ   rX   rY   r   r   r   rr   rd   r   rc   )r   r   r   rX   rY   rj   rb   r   r   r   r     s"    Wr   z,Long-running command to run in a subprocess.)ro   command_argsr@   z
    Command arguments.

    Note: Use -- before the command arguments, otherwise watchmedo will
    try to interpret them.
    )metavarrn   ro   z-dz--directoryZ	DIRECTORYr   zLDirectory to watch. Use another -d or --directory option for each directory.)r*   r   r(   ro   z--signalsignalSIGINTz6Stop the subprocess with this signal (default SIGINT).z--kill-after
kill_afterg      $@zYWhen stopping, kill the subprocess after the specified timeout in seconds (default 10.0).z--debounce-intervaldebounce_intervalg        zwAfter a file change, Wait until the specified interval (in seconds) passes with no file changes, and only then restart.z--no-restart-on-command-exitrestart_on_command_exitstore_falsez.Don't auto-restart the command after it exits.c              
     sF  | j rddlm} nddlm} ddl ddlm} | jsBdg| _| j	drZt
 | jnt| j} j jht dr j  fd	d
}D ]} || qt| j| j\}}| jg}|| j ||||| j|| j| j| jd}	|	  || jd}
z2zt|
|	| j| j W n t k
r2   Y nX W 5 |	  X dS )zLCommand to start a long-running subprocess and restart it on matched events.r   ru   r   N)AutoRestartTrickrp   ZSIGSIGHUPc                   s    D ]}  | j qtd S r   )r   SIG_IGNr   )Z_signumZ_framesignumr   Ztermination_signalsr   r   handler_termination_signal  s    z0auto_restart.<locals>.handler_termination_signal)rE   rX   rY   r   stop_signalr   Zdebounce_interval_secondsr   r   )!r   r   rv   r   r   r   r   r   r   
startswithrg   intSIGTERMr   hasattraddr   rZ   rX   rY   rE   extendr   r   r   r   r   r]   rr   r`   rd   rc   r   )r   r   r   r   r   r   rX   rY   rE   rj   rb   r   r   r   auto_restartE  sD    _"


r   c                   @  s   e Zd ZdS )LogLevelExceptionN)r    r!   r"   r   r   r   r   r     s   r   c                 C  sB   t | jp
g }|dk rtd|dkr.tdddddgd	|  S )
Nr3   z&-q/--quiet may be specified only once.   z,-v/--verbose may be specified up to 2 times.ERRORWARNINGINFODEBUGr5   )sumr1   r   )r   r1   r   r   r   _get_log_level_from_args  s    r   c               
   C  s   t  } | jdkrt   dS zt| }W nP tk
rz } z2td|jd  tj	d t
| j   W Y dS d}~X Y nX td| z| |  W n tk
r   Y dS X dS )zEntry-point function.Nr5   zError: r   )r   Zwatchdog   )cli
parse_argsr)   
print_helpr   r   printr   rI   stderrr9   r   r   setLevelr6   KeyboardInterrupt)r   Z	log_levelexcr   r   r   main  s     
r   __main__)r   )rV   ):r#   
__future__r   r   r   r   os.pathrI   r^   argparser   r   ior   textwrapr   typingr   r   r   r	   r
   Zwatchdog.versionr   Zwatchdog.observers.apir   basicConfigr   r   r   r   r%   r   r;   add_subparsersZ
subparsersr9   r,   rE   pathseprH   rO   rU   rZ   rd   rk   floatr   r   r   r   r   	Exceptionr   r   r   r    exitr   r   r   r   <module>   s  

+.
4
F
#U

\
9	
