B
    <[?                 @   s   d Z ddlmZmZ ddlmZ ddlZddlmZm	Z	m
Z
 ddlmZmZmZmZmZ ddl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.    )print_functionabsolute_import)deepcopyN   )ConfigLazyConfigValue_is_section_key)	HasTraitsInstanceobserveobserve_compatdefault)indentdedentwrap_paragraphsc               @   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 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t| jf | |dk	rb|| _n| | j x | D ]\}}t	| || qxW 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config)
popgetr   r   superr   __init___load_configitemssetattr)selfkwargsr   r   keyvalue)	__class__r   r   r   &   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>f   s    z.Configurable.section_names.<locals>.<listcomp>)reversed__mro__)r*   r   )r*   r   section_namesc   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   r.   Z_has_sectionmerge)r"   cfgZcfgs	my_configr)   Zsnamer   r   r   r0   j   s    

zConfigurable._find_my_configNc          	   C   s@  |dkr| j dd}|dkr$|  }| |}|    x| D ]\}}||krt|trrt| |}||}t	| |t
| qDt|sDt|tsDddlm} t| tr| jj}	ndd }	|||}
dj|| jjd	}t|
d
k r|dj|
d d7 }n(t|
d
kr&|djdt|
d7 }|	| qDW 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>   s    z+Configurable._load_config.<locals>.<lambda>z5Config option `{option}` not recognized by `{klass}`.)Zoptionklassr   z  Did you mean `{matches}`?)matchesz#  Did you mean one of: `{matches}`?z, )traitsr.   r0   Zhold_trait_notificationsr    
isinstancer   getattrZ	get_valuer!   r   r   r   Zdifflibr4   LoggingConfigurablelogZwarningformatr&   r   lenjoinsorted)r"   r2   r.   r=   r3   nameZconfig_valueinitialr4   r8   r<   r9   r   r   r   r      s2    






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   )r=   r.   N)r=   r.   r   new)r"   Zchanger=   r.   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   r1   )r"   r   r   r   r   update_config   s    
zConfigurable.update_configc             C   s   |dkst || stg }|d| j  |t|d d  x6t| jdd D ]\}}| ||}|| qVW d	|S )zGet the help string for this class in ReST format.

        If `inst` is given, it's current trait values will be used in place of
        class defaults.
        Nz
%s optionsr   -T)r   
)
r>   AssertionErrorr/   r   rC   rE   class_traitsr    class_get_trait_helprD   )r*   instZ
final_helpkvhelpr   r   r   class_get_help   s    zConfigurable.class_get_helpc             C   s  |dkst || stg }d| j|j|jjf }|| |dk	r`|tdt||j d n^y| }W n t	k
r   d}Y nX |dk	rt
|dkr|dd d }|td| d d	|jjkr|td
|jf  |j}|dkrdt|d}|t|d d|S )zGet the help string for a single trait.

        If `inst` is given, it's current trait values will be used in place of
        the class default.
        Nz--%s.%s=<%s>zCurrent: %r   @   =   z...zDefault: %sEnumzChoices: %r rL   L   )r>   rM   r   rF   r&   r/   r   r?   default_value_repr	ExceptionrC   valuesrS   rD   r   )r*   traitrP   linesheaderdvrrS   r   r   r   rO      s*    


z!Configurable.class_get_trait_helpc             C   s   t | | dS )z4Get the help string for a single trait and print it.N)printrT   )r*   rP   r   r   r   class_print_help   s    zConfigurable.class_print_helpc       	      C   s   dd }d}d dd | jD }d| j|f }|||dg}|  d	}|rT|j}|sdt| d
d}|r||| |d xTt| j	dd
 D ]<\}}|||j |d| j|| f  |d qW d |S )z#Get the config class config sectionc             S   s    d t| d} d| dd S )z"return a commented, wrapped block.z

N   z## rL   z
#  )rD   r   replace)sr   r   r   r)     s    z,Configurable.class_config_section.<locals>.czO#------------------------------------------------------------------------------,c             s   s   | ]}|j V  qd S )N)r   )r(   pr   r   r   	<genexpr>  s    z4Configurable.class_config_section.<locals>.<genexpr>z# %s(%s) configurationrY   Zdescription__doc__T)r   z#c.%s.%s = %srL   )rD   	__bases__r   rN   r   Zdefault_valuer?   r/   rE   class_own_traitsr    rS   r[   )	r*   r)   ZbreakerZparent_classesrf   r_   ZdescrF   r^   r   r   r   class_config_section  s$    
z!Configurable.class_config_sectionc       	   	   C   s"  g }| j }x
t| jdd D ]\}}|jj }|d |j }d|krh|dddd |j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}|d|  |d |jpd}|tt|d |d q"W d|S )zwGenerate rST documentation for this class' config options.

        Excludes traits defined on parent classes.
        T)r   .rX   z : |c             s   s   | ]}t |V  qd S )N)repr)r(   xr   r   r   ri   0  s    z4Configurable.class_config_rst_doc.<locals>.<genexpr>NrV   rW   z...z\nz\\nz    Default: ``%s``rY   zNo descriptionrU   rL   )r   rE   rl   r    r&   rF   rD   r]   r/   r[   r\   rC   re   rS   r   r   )	r*   r_   Z	classnamerQ   r^   ZttypeZtermlinera   rS   r   r   r   class_config_rst_doc   s.      



z!Configurable.class_config_rst_doc)NN)N)N)N)r   r   r   r
   r   r   r   r   classmethodr.   r0   r   r   r   rI   rJ   rT   rO   rc   rm   rr   __classcell__r   r   )r&   r   r   !   s"   =
'r   c               @   s(   e Zd ZdZedZeddd ZdS )r@   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logging.LoggerrA   c             C   s   ddl m} | S )Nr   )rA   )Z	traitletsrA   Z
get_logger)r"   rA   r   r   r   _log_defaultT  s    z LoggingConfigurable._log_defaultN)r   r   r   rj   r
   rA   r   ru   r   r   r   r   r@   L  s   r@   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)mror'   rv   )r*   subclassr   r   r   	_walk_mrod  s
    

zSingletonConfigurable._walk_mroc             C   s4   |   sdS x"|  D ]}t|j| rd|_qW dS )z>unset _instance for this class and singleton parents.
        N)initializedry   r>   	_instance)r*   rx   r   r   r   clear_instanceq  s
    z$SingletonConfigurable.clear_instancec             O   sP   | j dkr,| ||}x|  D ]
}||_ qW t| j | r>| j S td| j 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
        NzAMultiple incompatible subclass instances of %s are being created.)r{   ry   r>   r   r   )r*   argsr#   rP   rx   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{   )r*   r   r   r   rz     s    z!SingletonConfigurable.initialized)
r   r   r   rj   r{   rs   ry   r|   r~   rz   r   r   r   r   rv   Z  s   -rv   )rj   Z
__future__r   r   copyr   r7   loaderr   r   r   Ztraitlets.traitletsr	   r
   r   r   r   Zipython_genutils.textr   r   r   r\   r   r   r   r@   rv   r   r   r   r   <module>   s     -