B
    NcR                 @   s   d Z ddlZddlZddlmZ ddlmZ ddl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 ddlmZmZmZmZ G d	d
 d
eZG dd deZG dd deZG dd deZG dd deZdS )z/A base class for objects that are configurable.    N)deepcopy)dedent)	Any	ContainerDict	HasTraitsInstancedefaultobserveobserve_compatvalidate)indentwrap_paragraphs   )ConfigDeferredConfigLazyConfigValue_is_section_keyc               @   s   e Zd ZdS )ConfigurableErrorN)__name__
__module____qualname__ r   r   <lib/python3.7/site-packages/traitlets/config/configurable.pyr       s   r   c               @   s   e Zd ZdS )MultipleInstanceErrorN)r   r   r   r   r   r   r   r   $   s   r   c                   s   e Zd Zeedi ZedddZ fddZedd Z	d	d
 Z
dddZededd Zdd Zed ddZed!ddZed"ddZedd Zed#ddZedd Z  ZS )$Configurabler   z*traitlets.config.configurable.ConfigurableT)Z
allow_nonec                s    dd}|dk	r4dddkr.|jd< || _ dd}t jf  t   fdd}| | |dk	r||| _n| | j | 	| x D ]}t
| ||  qW dS )a  Create a configurable given a config config.

        Parameters
        ----------
        config : Config
            If this is empty, default values are used. If config is a
            :class:`Config` instance, it will be used to configure the
            instance.
        parent : Configurable instance, optional
            The parent Configurable instance of this object.

        Notes
        -----
        Subclasses of Configurable must call the :meth:`__init__` method of
        :class:`Configurable` *before* doing anything else and using
        :func:`super`::

            class MyConfigurable(Configurable):
                def __init__(self, config=None):
                    super(MyConfigurable, self).__init__(config=config)
                    # Then any other code you need to finish initialization.

        This ensures that instances will be configured properly.
        parentNconfigc                s   | j kr | j  dS )zRecord traits set by both config and kwargs.

            They will need to be overridden again after loading config.
            N)nameadd)change)config_override_nameskwargsr   r   notice_config_overrideZ   s    
z5Configurable.__init__.<locals>.notice_config_override)popgetr   r   super__init__setr
   _load_configZ	unobservesetattr)selfr"   r   r   r#   r   )	__class__)r!   r"   r   r'   2   s     



zConfigurable.__init__c                s    fddt  jD S )zreturn section names as a listc                s&   g | ]}t |trt  |r|jqS r   )
issubclassr   r   ).0c)clsr   r   
<listcomp>~   s   z.Configurable.section_names.<locals>.<listcomp>)reversed__mro__)r0   r   )r0   r   section_namesz   s    
zConfigurable.section_namesc             C   s`   |g}| j r|| j | t }x6|D ].}x(|  D ]}||r8|||  q8W q*W |S )a  extract my config from a global Config object

        will construct a Config object of only the config values that apply to me
        based on my mro(), as well as those of my parent(s) if they exist.

        If I am Bar and my parent is Foo, and their parent is Tim,
        this will return merge following config sections, in this order::

            [Bar, Foo.Bar, Tim.Foo.Bar]

        With the last item being the highest priority.
        )r   append_find_my_configr   r4   Z_has_sectionmerge)r+   cfgZcfgs	my_configr/   Zsnamer   r   r   r6      s    

zConfigurable._find_my_configNc          	   C   s^  |dkr| j dd}|dkr$|  }| |}|   x| D ]\}}||krt|trxt| |}||}nt|t	r||| }t
| |t| qFt|sFt|tsFddlm} t| tr| jj}	ndd }	|||}
dj|| jjd	}t|
d
kr|d|
d  d7 }n(t|
d
krD|djdt|
d7 }|	| qFW W dQ R X dS )z load traits from a Config objectNT)r   r   )get_close_matchesc             S   s   t j| ddS )N	   )
stacklevel)warningswarn)msgr   r   r   <lambda>       z+Configurable._load_config.<locals>.<lambda>z5Config option `{option}` not recognized by `{klass}`.)optionklassr   z  Did you mean `z`?z#  Did you mean one of: `{matches}`?z, )matches)traitsr4   r6   Zhold_trait_notificationsitems
isinstancer   getattrZ	get_valuer   r*   r   r   r   Zdifflibr:   LoggingConfigurablelogZwarningformatr,   r   lenjoinsorted)r+   r8   r4   rE   r9   r   Zconfig_valueinitialr:   r>   rD   r?   r   r   r   r)      s8    






zConfigurable._load_configr   c             C   s*   | j dd}|  }| j|j||d dS )zUpdate all the class traits having ``config=True`` in metadata.

        For any class trait with a ``config`` metadata attribute that is
        ``True``, we update the trait with the value of the corresponding
        config entry.
        T)r   )rE   r4   N)rE   r4   r)   new)r+   r    rE   r4   r   r   r   _config_changed   s    
zConfigurable._config_changedc             C   s&   t | j| _| | | j| dS )z%Update config and load the new valuesN)r   r   r)   r7   )r+   r   r   r   r   update_config   s    
zConfigurable.update_configc             C   s   |dkst || stg }ddd | jD }|| j d| d |t|d d  x6t| jd	d
	 D ]\}}| 
||}|| qtW d|S )zGet the help string for this class in ReST format.

        If `inst` is given, its current trait values will be used in place of
        class defaults.
        Nz, c             s   s   | ]}|j V  qd S )N)r   )r.   pr   r   r   	<genexpr>   s    z.Configurable.class_get_help.<locals>.<genexpr>(z	) optionsr   -T)r   
)rG   AssertionErrorrM   	__bases__r5   r   rL   rN   class_traitsrF   class_get_trait_help)r0   instZ
final_helpZbase_classes_vhelpr   r   r   class_get_help   s    zConfigurable.class_get_helpc       	      C   s  |dkst || stg }d| j d|j }t |ttfr|jdd}t |trZd}nd|jj	  }|dkr| d| d	}q| d
| d	}n| d|jj d}|
| |dkr|j}|dkrdt|d}|
t| d|jjkr|
td|   |dk	r4|
tdt||j nby| }W n tk
rZ   d}Y nX |dk	rt|dkr|dd d	 }|
td|  d|S )a  Get the helptext string for a single trait.

        :param inst:
            If given, its current trait values will be used in place of
            the class default.
        :param helptext:
            If not given, uses the `help` attribute of the current trait.
        Nz--.multiplicityr5   z<key-1>=<value-1>z<%s-item-1>=z... z=<> rW   L   EnumzChoices: %sz	Current: @   =   zDefault: %s)rG   rX   r   r   r   r   Zmetadatar%   r,   lowerr5   r_   rM   r   r   inforH   default_value_repr	ExceptionrL   )	r0   traitr\   Zhelptextlinesheaderrb   Zsample_valuedvrr   r   r   r[      s>    





z!Configurable.class_get_trait_helpc             C   s   t | | dS )z4Get the help string for a single trait and print it.N)printr`   )r0   r\   r   r   r   class_print_help1  s    zConfigurable.class_print_helpc             C   sJ   | }x@|   D ]4}t|tr||kr|jdd|jd|kr|}qW |S )a7  Get the class that defines a trait

        For reducing redundant help output in config files.
        Returns the current class if:
        - the trait is defined on this class, or
        - the class where it is defined would not be in the config file

        Parameters
        ----------
        trait : Trait
            The trait to look for
        classes : list
            The list of other classes to consider for redundancy.
            Will return `cls` even if it is not defined on `cls`
            if the defining class is not in `classes`.
        T)r   N)mror-   r   Zclass_own_traitsr%   r   )r0   ro   classesZdefining_clsr   r   r   r   _defining_class6  s    
zConfigurable._defining_classc          	   C   s  dd }d}d dd | jD }d| j d| d	}|||g}|  d
}|rX|j}|sht| dd}|r||| |d xt| jdd	 D ]\}}	|	
 }
|r| |	|}n| }|| kr|	jr|||	j dt|	jkr|d|	   |d|
  n<|	jr6|||	jddd  |d|j d|  |d| j d| d|
  |d qW d |S )zGet the config section for this class.

        Parameters
        ----------
        classes : list, optional
            The list of other classes in the config file.
            Used to reduce redundant information.
        c             S   s    d t| d} d| dd S )z"return a commented, wrapped block.z

N   z## rW   z
#  )rM   r   replace)sr   r   r   r/   ]  s    z,Configurable.class_config_section.<locals>.czO#------------------------------------------------------------------------------z, c             s   s   | ]}t |tr|jV  qd S )N)r-   r   r   )r.   rS   r   r   r   rT   e  s    z4Configurable.class_config_section.<locals>.<genexpr>z# rU   z) configurationdescription__doc__rf   T)r   rh   z#  Choices: %sz#  Default: %srW   r   r   z#  See also: ra   z# c.z = )rM   rY   r   rZ   r%   Zdefault_valuerH   r5   rN   rF   rm   rw   r_   typerl   split)r0   rv   r/   ZbreakerZparent_classesrz   rp   Zdescr   ro   Zdefault_reprZdefining_classr   r   r   class_config_sectionR  s<    


z!Configurable.class_config_sectionc       	   	   C   s  g }| j }xt| jdd D ]\}}|jj }|d |j }d|krX|d|  7 }n|d| 7 }|| y| }W n t	k
r   d}Y nX |dk	rt
|dkr|dd d	 }|d
d}|td|  |d |jpd}|tt| |d q W d|S )zwGenerate rST documentation for this class' config options.

        Excludes traits defined on parent classes.
        T)r   ra   rh   z : Nri   rj   z...z\nz\\nzDefault: ``%s``rf   zNo descriptionrW   )r   rN   rZ   rF   r,   r   Zinfo_rstr5   rm   rn   rL   ry   r   r_   r   rM   )	r0   rp   Z	classnamer]   ro   ZttypeZtermlinerr   r_   r   r   r   class_config_rst_doc  s.    



z!Configurable.class_config_rst_doc)NN)N)NN)N)N)r   r   r   r   r   r   r   r'   classmethodr4   r6   r)   r
   r   rQ   rR   r`   r[   rt   rw   r   r   __classcell__r   r   )r,   r   r   -   s&   H	
.3;r   c               @   sB   e Zd ZdZeddZeddd Zeddd Z	d	d
 Z
dS )rI   zA parent class for Configurables that log.

    Subclasses have a log trait, and the default behavior
    is to get the logger from the currently running Application.
    z Logger or LoggerAdapter instance)r_   rJ   c             C   s6   t |jtjtjfs0t| jj d|j d |jS )Nz..log should be a Logger or LoggerAdapter, got ra   )	rG   valueloggingZLoggerLoggerAdapterr=   r>   r,   r   )r+   Zproposalr   r   r   _validate_log  s    z!LoggingConfigurable._validate_logc             C   s(   t | jtr| jjS ddlm} | S )Nr   )rJ   )rG   r   rI   rJ   Z	traitletsZ
get_logger)r+   rJ   r   r   r   _log_default  s    z LoggingConfigurable._log_defaultc             C   s2   | j }t|tjr|j}t|dds(dS |jd S )zReturn the default Handler

        Returns None if none can be found

        Deprecated, this now returns the first log handler which may or may
        not be the default one.
        handlersNr   )rJ   rG   r   r   loggerrH   r   )r+   r   r   r   r   _get_log_handler  s    z$LoggingConfigurable._get_log_handlerN)r   r   r   r|   r   rJ   r   r   r	   r   r   r   r   r   r   rI     s
   

rI   c               @   sD   e Zd ZdZdZedd Zedd Zedd Zed	d
 Z	dS )SingletonConfigurablezA configurable that only allows one instance.

    This class is for classes that should only have one instance of itself
    or *any* subclass. To create and retrieve such a class use the
    :meth:`SingletonConfigurable.instance` method.
    Nc             c   s8   x2|   D ]&}t| |r
t|tr
|tkr
|V  q
W dS )zfWalk the cls.mro() for parent classes that are also singletons

        For use in instance()
        N)ru   r-   r   )r0   subclassr   r   r   	_walk_mro  s
    

zSingletonConfigurable._walk_mroc             C   s4   |   sdS x"|  D ]}t|j| rd|_qW dS )z5unset _instance for this class and singleton parents.N)initializedr   rG   	_instance)r0   r   r   r   r   clear_instance  s
    z$SingletonConfigurable.clear_instancec             O   s\   | j dkr,| ||}x|  D ]
}||_ qW t| j | r>| j S td| jt| j jf dS )a  Returns a global instance of this class.

        This method create a new instance if none have previously been created
        and returns a previously created instance is one already exists.

        The arguments and keyword arguments passed to this method are passed
        on to the :meth:`__init__` method of the class upon instantiation.

        Examples
        --------
        Create a singleton class using instance, and retrieve it::

            >>> from traitlets.config.configurable import SingletonConfigurable
            >>> class Foo(SingletonConfigurable): pass
            >>> foo = Foo.instance()
            >>> foo == Foo.instance()
            True

        Create a subclass that is retrived using the base class instance::

            >>> class Bar(SingletonConfigurable): pass
            >>> class Bam(Bar): pass
            >>> bam = Bam.instance()
            >>> bam == Bar.instance()
            True
        NzHAn incompatible sibling of '%s' is already instanciated as singleton: %s)r   r   rG   r   r   r}   )r0   argsr"   r\   r   r   r   r   instance	  s    


zSingletonConfigurable.instancec             C   s   t | do| jdk	S )zHas an instance been created?r   N)hasattrr   )r0   r   r   r   r   5  s    z!SingletonConfigurable.initialized)
r   r   r   r|   r   r   r   r   r   r   r   r   r   r   r     s   ,r   )r|   r   r=   copyr   textwrapr   Ztraitlets.traitletsr   r   r   r   r   r	   r
   r   r   Ztraitlets.utils.textr   r   loaderr   r   r   r   rn   r   r   r   rI   r   r   r   r   r   <module>   s   ,	   ,