B
    <[$e                 @   s  d Z ddlm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
mZ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mZm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$ ddl%m&Z&m'Z'm(Z( ddl)m*Z* ddl+Z+d, Z-d, Z.e/e	dsdge	_0dZ1ej23ddZ4e45 dkr>dZ6n e45 dkrRdZ6ne7de4 edd Z8G dd de9Z:G dd dej;Z<G dd deZ=d$d d!Z>d"d# Z?dS )%z,A base class for a configurable application.    )print_function)deepcopyN)defaultdictOrderedDict)	decorator)ConfigurableSingletonConfigurable)KVArgParseConfigLoaderPyFileConfigLoaderConfigArgumentErrorConfigFileNotFoundJSONFileConfigLoader)
BoolUnicodeListEnumDictInstance
TraitErrorobserveobserve_compatdefault)import_item)indentwrap_paragraphsdedent)	py3compatz
Arguments that take values are actually convenience aliases to full
Configurables, whose aliases are listed on the help line. For more information
on full configurables, see '--help-all'.
z
Parameters are set from command-line arguments of the form:
`--Class.trait=value`.
This line is evaluated in Python, so simple expressions are allowed, e.g.::
`--C.a='range(3)'` For setting C.a=[0,1,2].
argv zp
Subcommands are launched as `{app} cmd [args]`. For information on using
subcommand 'cmd', do: `{app} cmd -h`.
-TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR>   true1T>   falser   0FzUnsupported value for environment variable: 'TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR' is set to '%s' which is none of  {'0', '1', 'false', 'true', ''}.c          
   O   sz   y| |f||S  t tfk
rt } zB|  |jd |jt| |jd|j |d W dd}~X Y nX dS )a  Method decorator for catching invalid config (Trait/ArgumentErrors) during init.

    On a TraitError (generally caused by bad config), this will print the trait's
    message, and exit the app.

    For use on init methods, to prevent invoking excepthook on invalid input.
    z-Bad config encountered during initialization:zConfig at the time: %s   N)	r   r   
print_helplogZfatalstrdebugconfigexit)methodappargskwargse r1   ;lib/python3.7/site-packages/traitlets/config/application.pycatch_config_errorM   s    	r3   c               @   s   e Zd ZdS )ApplicationErrorN)__name__
__module____qualname__r1   r1   r1   r2   r4   `   s   r4   c                   s*   e Zd ZdZejZdZ fddZ  Z	S )LevelFormattera  Formatter with additional `highlevel` record

    This field is empty if log level is less than highlevel_limit,
    otherwise it is formatted with self.highlevel_format.

    Useful for adding 'WARNING' to warning messages,
    without adding 'INFO' to info, etc.
    z %(levelname)s |c                s2   |j | jkr| j|j |_nd|_tt| |S )Nr   )Zlevelnohighlevel_limithighlevel_format__dict__Z	highlevelsuperr8   format)selfrecord)	__class__r1   r2   r=   p   s    zLevelFormatter.format)
r5   r6   r7   __doc__loggingWARNr9   r:   r=   __classcell__r1   r1   )r@   r2   r8   d   s   r8   c                   s$  e Zd ZdZedZedZeeZeeZee	Z	e
ZeZe Zg Zdd ZedZe ZeeZedejdd	jd
dZededd ZeZ edddjd
dZ!edddjd
dZ"eddedd Z#e$ddd Z%e&ddiZ'e& Z(ededd Z)e& Z*e+d d
d!Z,ee Z-e+e.d"i d#dZ/d$d% Z0ed&e fd'd(Z1e2dTd*d+Z3d,d- Z4d.d/ Z5d0d1 Z6d2d3 Z7d4d5 Z8dUd7d8Z9d9d: Z:d;d< Z;d=d> Z<d?d@ Z=e2dVdAdBZ>dCdD Z?e2dWdEdFZ@eAdXdGdHZBe2dYdIdJZCdKdL ZDdMdN ZEdZdPdQZFeAd[dRdSZG  ZHS )\Applicationz8A singleton application with full configuration support.ZapplicationzThis is an application.c             c   sR   t  }xF| jD ]<}x6t| D ]&}t|tr ||kr || |V  q W qW dS )zIterate through configurable classes, including configurable parents

        Children should always be after parents, and each class should only be
        yielded once.
        N)setclassesreversedmro
issubclassr   add)r>   seencparentr1   r1   r2   _classes_inc_parents   s    
z Application._classes_inc_parentsz0.0)r   
         (   2   DEBUGINFOrC   ZERRORZCRITICALz#Set the log level by value or name.)Zdefault_valuehelpT)r*   	log_levelc             C   s2   |j }t|tjr"tt|}|| _| j| dS )z+Adjust the log level when log_level is set.N)	new
isinstancesixstring_typesgetattrrB   rX   r'   setLevel)r>   changerY   r1   r1   r2   _log_level_changed   s
    
zApplication._log_level_changedz%Y-%m-%d %H:%M:%Sz:The date format used by logging formatters for %(asctime)s)rW   z#[%(name)s]%(highlevel)s %(message)szThe Logging format templatelog_datefmt
log_formatc             C   s,   | j jd }| j| j| jd}|| dS )z0Change the log formatter when log_format is set.r   )fmtdatefmtN)r'   handlers_log_formatter_clsrb   ra   setFormatter)r>   r_   _log_handler_log_formatterr1   r1   r2   _log_format_changed   s    zApplication._log_format_changedr'   c             C   s   t | jj}|| j d|_|}x"|rF|jr4|S |js>P q&|j}q&W t	j
rnt	j
drnt ttjd}nt  }| j| j| jd}|| || |S )a
  Start logging for this application.

        The default is to log to stderr using a StreamHandler, if no default
        handler already exists.  The log level starts at logging.WARN, but this
        can be adjusted by setting the ``log_level`` attribute.
        Fzpythonw.exew)rc   rd   )rB   Z	getLoggerr@   r5   r^   rX   Z	propagatere   rN   sys
executableendswithZStreamHandleropenosdevnullrf   rb   ra   rg   Z
addHandler)r>   r'   Z_logrh   ri   r1   r1   r2   _log_default   s"    


zApplication._log_defaultz	log-levelzApplication.log_levelflagsc             C   s~   |j }xr| D ]f\}}t|dks4td||f t|d ttfsVtd||f t|d tjstd||f qW dS )zensure flags dict is valid   zBad flag: %r:%sr   r%   N)	rY   itemslenAssertionErrorrZ   dictr   r[   r\   )r>   r_   rY   keyvaluer1   r1   r2   _flags_changed   s
    "zApplication._flags_changedz(traitlets.config.application.Application)Z
allow_noner1   zThe subset of our configuration that came from the command-line

        We re-load this configuration after loading config files,
        to ensure that it maintains highest priority.
        c             K   sN   t j| f| | j}|| jkrJ| j|jkr:|g| j |_n| jd| j d S )Nr   )r   __init__r@   rG   insert)r>   r/   clsr1   r1   r2   r|     s    
zApplication.__init__r*   c                s2   t t| | | jd | jt|j d S )NzConfig changed:)r<   rE   _config_changedr'   r)   reprrY   )r>   r_   )r@   r1   r2   r     s    zApplication._config_changedNc             C   s   |  | dS )zMDo the basic steps to configure me.

        Override in subclasses.
        N)parse_command_line)r>   r   r1   r1   r2   
initialize"  s    zApplication.initializec             C   s   | j dk	r| j  S dS )zAStart the app mainloop.

        Override in subclasses.
        N)subappstart)r>   r1   r1   r2   r   +  s    
zApplication.startc             C   s   | j s
dS g }i }x2| jD ](}x"| dd D ]}|||j< q0W qW x| j  D ]\}}|dd\}}|| }|jdd| }	||	 }
|
d 	||d|  |
d< t
|dkr|
d 	d	| d
| |
d< ||
 qRW ttj| dS )z!Print the alias part of the help.N.r%   T)r*   r   z (%s)z--%s=z-%s )aliasesrG   rI   r5   ru   splitZclass_traitsZclass_get_trait_help
splitlinesreplacerv   extendprintrp   linesepjoin)r>   lines	classdictr~   rM   aliasZlongnameZ	classnameZ	traitnametraitrW   r1   r1   r2   print_alias_help3  s"    zApplication.print_alias_helpc             C   sv   | j s
dS g }xR| j  D ]D\}\}}t|dkr6dnd}|||  |tt|  qW ttj	
| dS )z Print the flag part of the help.Nr%   z---)rs   ru   rv   appendr   r   stripr   rp   r   r   )r>   r   mZcfgrW   prefixr1   r1   r2   print_flag_helpM  s    zApplication.print_flag_helpc             C   s   | j s| jsd S dg}|dt|d   |d x&t| jD ]}|| |d qBW ttj	| | 
  |   t  d S )NZOptionsr   r   r   )rs   r   r   rv   r   option_descriptionr   rp   r   r   r   r   )r>   r   pr1   r1   r2   print_optionsZ  s    

zApplication.print_optionsc             C   s   | j s
dS dg}|dt|d   |d x0t| jj| jdD ]}|| |d qFW x>| j  D ]0\}\}}|| |rn|tt	|
  qnW |d ttj| dS )z&Print the subcommand part of the help.NZSubcommandsr   r   r   )r-   )subcommandsr   rv   r   subcommand_descriptionr=   nameru   r   r   r   r   rp   r   r   )r>   r   r   subcr~   rW   r1   r1   r2   print_subcommandsh  s    




zApplication.print_subcommandsFc             C   s   |    |   |   |r|| j}|r^td td t  x t| jD ]}t| t  qHW x*|D ]}|  t  qdW ntd t  |   dS )zPrint the help for each Configurable class in self.classes.

        If classes=False (the default), only flags and aliases are printed.
        zClass parametersz----------------z4To see all available configurables, use `--help-all`N)	print_descriptionr   r   rG   r   r   keyvalue_descriptionZclass_print_helpprint_examples)r>   rG   Zhelp_classesr   r~   r1   r1   r2   r&   {  s$    

zApplication.print_helpc             C   s   d dd |  D S )zwGenerate rST format documentation for the config options this application

        Returns a multiline string.
        
c             s   s   | ]}|  V  qd S )N)Zclass_config_rst_doc).0rM   r1   r1   r2   	<genexpr>  s   z6Application.document_config_options.<locals>.<genexpr>)r   rO   )r>   r1   r1   r2   document_config_options  s    
z#Application.document_config_optionsc             C   s&   x t | jD ]}t| t  qW dS )z"Print the application description.N)r   descriptionr   )r>   r   r1   r1   r2   r     s    zApplication.print_descriptionc             C   s<   | j r8td td t  ttt| j   t  dS )zPrint usage and examples.

        This usage string goes at the end of the command line help string
        and should contain examples of the application's usage.
        ZExamplesz--------N)examplesr   r   r   r   )r>   r1   r1   r2   r     s    zApplication.print_examplesc             C   s   t | j dS )zPrint the version string.N)r   version)r>   r1   r1   r2   print_version  s    zApplication.print_versionc             C   sL   | j |\}}t|tjr$t|}| j  |j| d| _	| j	
| dS )z"Initialize a subcommand with argv.)rN   N)r   getrZ   r[   r\   r   r@   Zclear_instanceinstancer   r   )r>   r   r   r   rW   r1   r1   r2   initialize_subcommand  s    
z!Application.initialize_subcommandc             C   s  t t}x>| jD ]4}|j}x(| dd D ]}||j | q,W qW i }xT| j D ]F\}}|dd\}}|| }	t	|	dkr|	d }d
||g||< qXW i }
xd| j D ]V\}\}}i }x8| D ],\}}|| }	t	|	dkr|	d }|||< qW ||f|
|< qW |
|fS )a~  flatten flags and aliases, so cl-args override as expected.

        This prevents issues such as an alias pointing to InteractiveShell,
        but a config file setting the same trait in TerminalInteraciveShell
        getting inappropriate priority over the command-line arg.

        Only aliases with exactly one descendent in the class list
        will be promoted.

        r%   r   r   r   )r   listrG   r5   rI   r   r   ru   r   rv   r   rs   )r>   Zmro_treer~   ZclsnamerN   r   r   Z	cls_traitr   Zchildrenrs   ry   ZflagdictrW   ZnewflagZsubdictr1   r1   r2   flatten_flags  s,    zApplication.flatten_flagsc                s^  |dkrt jdd n|}dd |D | _|rL|d dkrL|dd dg }| jrt|dkr|d |dd  }}td|r|| jkr| ||S y|d|d	  W n tk
r   | Y nX t	 fd
ddD r| 
d k | d d ksd kr|   | d |  \}}t|||| jd}t| | _| | j |j| _dS )z!Parse the command line arguments.Nr%   c             S   s   g | ]}t |qS r1   )r   Zcast_unicode)r   argr1   r1   r2   
<listcomp>  s    z2Application.parse_command_line.<locals>.<listcomp>r   rW   z-hz^\w(\-?\w)*$z--c             3   s   | ]}| kV  qd S )Nr1   )r   x)interpreted_argvr1   r2   r     s    z1Application.parse_command_line.<locals>.<genexpr>)z-hz
--help-allz--helpz
--help-allz	--versionz-V)r   r   rs   r'   )rl   r   r   rv   rematchr   index
ValueErroranyr&   r+   r   r   r	   r'   r   load_config
cli_configupdate_config
extra_args)r>   r   r   Zsubargvrs   r   loaderr1   )r   r2   r     s0    


zApplication.parse_command_linec             c   sj  t |ts|g}xR|ddd D ]>}| j|d ||d}|rV|d||pRt  | j|d ||d}d}g }g }	x||gD ]}
y|
 }W nJ tk
r   Y nJ t	k
r   |
j
p|}|r |r|jd|dd	 Y nX |r|d
|
j
 |rxNt|	|D ]@\}}||}| r| r|d||
j
tj|dd  qW |V  || |	|
j
 qW q"W dS )zeLoad config files (py,json) by filename and path.

        yield each config object in turn.
        Nz.py)pathr'   zLooking for %s in %sz.jsonz&Exception while loading config file %sT)exc_infozLoaded config file: %szMCollisions detected in {0} and {1} config files. {1} has higher priority: {2}rt   )r   )rZ   r   python_config_loader_classr)   rp   getcwdjson_config_loader_classr   r   	ExceptionZfull_filenameerrorzip
collisionsZwarningr=   jsondumpsr   )r~   Zbasefilenamer   r'   raise_config_file_errorsZpyloaderZ
jsonloaderr*   Zloaded	filenamesr   filenameZearlier_configr   r1   r1   r2   _load_config_files  sB    



zApplication._load_config_filesc             C   sZ   t j|\}}t }x(| j||| j| jdD ]}|| q.W || j | 	| dS )z'Load config files by filename and path.)r   r'   r   N)
rp   r   splitextr   r   r'   r   merger   r   )r>   r   r   ZextZ
new_configr*   r1   r1   r2   load_config_fileP  s    zApplication.load_config_filec             #   sx   t dd |  D   fddx0  }t fdd  D   |kr$P q$W x  D ]\}}|r^|V  q^W dS )a[  
        Yields only classes with own traits, and their subclasses.

        Thus, produced sample config-file will contain all classes
        on which a trait-value may be overridden:

        - either on the class owning the trait,
        - or on its subclasses, even if those subclasses do not define
          any traits themselves.
        c             s   s"   | ]}|t |jd dfV  qdS )T)r*   N)boolZclass_own_traits)r   r~   r1   r1   r2   r   i  s   z8Application._classes_in_config_sample.<locals>.<genexpr>c                s   t  fdd| jD S )Nc             3   s   | ]}| ko | V  qd S )Nr1   )r   b)cls_to_configr1   r2   r   n  s    zXApplication._classes_in_config_sample.<locals>.is_any_parent_included.<locals>.<genexpr>)r   	__bases__)r~   )r   r1   r2   is_any_parent_includedm  s    zEApplication._classes_in_config_sample.<locals>.is_any_parent_includedc             3   s"   | ]\}}||p |fV  qd S )Nr1   )r   r~   inc_yes)r   r1   r2   r   u  s   N)r   rO   copyru   )r>   Zto_incl_origZclr   r1   )r   r   r2   _classes_in_config_sample^  s    z%Application._classes_in_config_samplec             C   s@   d| j  g}|d x|  D ]}||  q W d|S )z/generate default config file from Configurablesz# Configuration file for %s.r   r   )r   r   r   Zclass_config_sectionr   )r>   r   r~   r1   r1   r2   generate_config_file~  s
    
z Application.generate_config_filer   c             C   s    | j d| j  t| d S )NzExiting application: %s)r'   r)   r   rl   r+   )r>   Zexit_statusr1   r1   r2   r+     s    zApplication.exitc             K   s"   | j f |}|| |  dS )zLaunch a global instance of this Application

        If a global instance already exists, this reinitializes and starts it
        N)r   r   r   )r~   r   r/   r-   r1   r1   r2   launch_instance  s    
zApplication.launch_instance)N)F)N)N)NNF)N)r   )N)Ir5   r6   r7   rA   r   r   r   r   r   r   r
   r   r   r   r   rG   rO   r   r   r   r   r    r   r   rB   rC   tagrX   r   r   r`   r8   rf   ra   rb   rj   r   rr   r   r   rs   r{   r   r   r   r   r   r   r|   r   r3   r   r   r   r   r   r   r&   r   r   r   r   r   r   r   classmethodr   r   r   r   r+   r   rD   r1   r1   )r@   r2   rE   x   s   	

	-*1 
rE   c             C   sV   |p
d| }|pd| }| d\}}||dii}||dii}| ||fd|  ||fiS )a  Helper for building basic --trait, --no-trait flags.

    Parameters
    ----------

    name : str
        The name of the flag.
    configurable : str
        The 'Class.trait' string of the trait to be set/unset with the flag
    set_help : unicode
        help string for --name flag
    unset_help : unicode
        help string for --no-name flag

    Returns
    -------

    cfg : dict
        A dict with two keys: 'name', and 'no-name', for setting and unsetting
        the trait, respectively.
    zset %s=Truezset %s=Falser   TFzno-)r   )r   ZconfigurableZset_helpZ
unset_helpr~   r   setterZunsetterr1   r1   r2   boolean_flag  s    r   c               C   s   t  rt  jS t S dS )z|Get the config object for the global Application instance, if there is one

    otherwise return an empty config object
    N)rE   Zinitializedr   r*   r   r1   r1   r1   r2   
get_config  s    
r   )r   r   )@rA   Z
__future__r   r   r   r   rB   rp   r   rl   collectionsr   r   r   Ztraitlets.config.configurabler   r   Ztraitlets.config.loaderr	   r
   r   r   r   r   Ztraitlets.traitletsr   r   r   r   r   r   r   r   r   r   Zipython_genutils.importstringr   Zipython_genutils.textr   r   r   Zipython_genutilsr   r[   r   r   r   hasattrr   r   environr   Z_envvarlowerr    r   r3   r   r4   Z	Formatterr8   rE   r   r   r1   r1   r1   r2   <module>   sJ    0	    $
!