a
    7anQ                     @   s   d Z ddlmZ ddlZddlZddl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 ddlmZmZ ddl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.    )deepcopyN   )ConfigLazyConfigValueDeferredConfig_is_section_key)	Any	HasTraitsInstance	ContainerDictobserveobserve_compatdefaultvalidate)indentwrap_paragraphs)dedentc                   @   s   e Zd ZdS )ConfigurableErrorN__name__
__module____qualname__ r   r   <lib/python3.9/site-packages/traitlets/config/configurable.pyr   "   s   r   c                   @   s   e Zd ZdS )MultipleInstanceErrorNr   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ur4dddu r.|jd< || _ dd}tt| jf i  t   fdd}| | |dur|| _n| 	| j | 
|  D ]}t| ||  qd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 v 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Zconfig_override_nameskwargsr   r   notice_config_overrideY   s    
z5Configurable.__init__.<locals>.notice_config_override)popgetr   r   superr   __init__setr   _load_configZ	unobservesetattr)selfr#   r   r   r$   r   	__class__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__r3   r   r3   r   section_namesy   s    zConfigurable.section_namesc                 C   sX   |g}| j r|| j | t }|D ]*}|  D ]}||r4|||  q4q(|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   r8   Z_has_sectionmerge)r,   cfgZcfgs	my_configr2   Zsnamer   r   r   r:      s    
zConfigurable._find_my_configNc                 C   sn  |du r| j dd}|du r$|  }| |}|    | D ]\}}||v rt|trtt| |}||}nt|t	r||| }t
| |t| qBt|sBt|tsBd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 }|	| qBW d   n1 s`0    Y  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 `{matches}`?)matchesz#  Did you mean one of: `{matches}`?, )traitsr8   r:   Zhold_trait_notificationsitems
isinstancer   getattrZ	get_valuer   r+   r   r   r   Zdifflibr?   LoggingConfigurablelogZwarningformatr.   r   lenjoinsorted)r,   r<   r8   rK   r=   r   Zconfig_valueinitialr?   rC   rI   rD   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.
        Tr>   )rK   r8   N)rK   r8   r*   new)r,   r!   rK   r8   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*   r;   )r,   r   r   r   r   update_config   s    
zConfigurable.update_configc                 C   s   |du st || sJ g }ddd | jD }|d| j|f  |t|d d  t| jdd	 D ]\}}| 	||}|| qnd
|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.
        NrJ   c                 s   s   | ]}|j V  qd S N)r   r1   pr   r   r   	<genexpr>   rF   z.Configurable.class_get_help.<locals>.<genexpr>z%s(%s) optionsr   -Tr>   
)
rM   rS   	__bases__r9   r   rR   rT   class_traitsrL   class_get_trait_help)r4   instZ
final_helpZbase_classeskvhelpr   r   r   class_get_help   s    zConfigurable.class_get_helpc           	      C   s  |du st || sJ g }d| j|jf }t |ttfr|jdd}t |trVd}nd|jj  }|dkr|d||f }qd||f }nd	||jjf }|	| |du r|j
}|d
krdt|d}|	t| d|jjv r|	td|   |dur"|	tdt||jf  n`z| }W n tyF   d}Y n0 |durt|dkrp|dd d }|	td|  d|S )a  Get the helptext string for a single trait.

        :param inst:
            If given, it's 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--%s.%smultiplicityr9   z<key-1>=<value-1>z<%s-item-1>z%s=%s...z%s %s...z%s=<%s> r^   L   EnumzChoices: %szCurrent: %r@   =   ...zDefault: %s)rM   r   r   r   r   metadatar&   r.   lowerr9   re   rS   r   r   inforN   default_value_repr	ExceptionrR   )	r4   traitrb   Zhelptextlinesheaderrg   Zsample_valuedvrr   r   r   ra      s>    





z!Configurable.class_get_trait_helpc                 C   s   t | | dS )z4Get the help string for a single trait and print it.N)printrf   )r4   rb   r   r   r   class_print_help*  s    zConfigurable.class_print_helpc                 C   sF   | }|   D ]4}t|tr||v r|jdd|jd|u r|}q|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`.
        Tr>   N)mror0   r   Zclass_own_traitsr&   r   )r4   rs   classesZdefining_clsr   r   r   r   _defining_class/  s    
zConfigurable._defining_classc                 C   sl  dd }d}d dd | jD }d| j|f }|||g}|  d}|rR|j}|sbt| d	d
}|r~||| |d
 t| jdd	 D ]\}}	|	
 }
|r| |	|}n| }|| u r|	jr|||	j dt|	jv r|d|	   |d|
  n8|	jr,|||	jddd  |d|j|f  |d| j||
f  |d
 qd |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## r^   z
#  )rS   r   replace)sr   r   r   r2   S  s    z,Configurable.class_config_section.<locals>.czO#------------------------------------------------------------------------------rJ   c                 s   s   | ]}t |tr|jV  qd S rY   r/   rZ   r   r   r   r\   [  s   
z4Configurable.class_config_section.<locals>.<genexpr>z# %s(%s) configurationdescription__doc__rh   Tr>   rj   z#  Choices: %sz#  Default: %sr^   r   r   z#  See also: %s.%sz# c.%s.%s = %s)rS   r_   r   r`   r&   Zdefault_valuerN   r9   rT   rL   rq   r{   re   typerp   split)r4   rz   r2   ZbreakerZparent_classesr~   rt   Zdescr   rs   Zdefault_reprZdefining_classr   r   r   class_config_sectionI  s@    




z!Configurable.class_config_sectionc           	   	   C   s  g }| j }t| jdd D ]\}}|jj }|d |j }d|v rV|d|  7 }n|d| 7 }|| z| }W n t	y   d}Y n0 |durt
|dkr|dd d	 }|d
d}|td|  |d |jpd}|tt| |d qd|S )zwGenerate rST documentation for this class' config options.

        Excludes traits defined on parent classes.
        Tr>   .rj   z : Nrk   rl   rm   z\nz\\nzDefault: ``%s``rh   zNo descriptionr^   )r   rT   r`   rL   r.   r   Zinfo_rstr9   rq   rr   rR   r}   r   re   r   rS   )	r4   rt   Z	classnamerc   rs   ZttypeZtermlinerv   re   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(   classmethodr8   r:   r*   r   r   rW   rX   rf   ra   rx   r{   r   r   __classcell__r   r   r-   r   r   -   s.   G

*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 )rO   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)re   rP   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 r   )	rM   valueloggingZLoggerLoggerAdapterrB   rC   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   )rP   )rM   r   rO   rP   Z	traitletsZ
get_logger)r,   rP   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 )zNReturn the default Handler

        Returns None if none can be found
        handlersNr   )rP   rM   r   r   loggerrN   r   )r,   r   r   r   r   _get_log_handler  s    z$LoggingConfigurable._get_log_handlerN)r   r   r   r   r   rP   r   r   r   r   r   r   r   r   r   rO     s   

	
rO   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   s4   |   D ]&}t| |rt|tr|tkr|V  qdS )zfWalk the cls.mro() for parent classes that are also singletons

        For use in instance()
        N)ry   r0   r   r4   subclassr   r   r   	_walk_mro  s    
zSingletonConfigurable._walk_mroc                 C   s0   |   sdS |  D ]}t|j| rd|_qdS )z>unset _instance for this class and singleton parents.
        N)initializedr   rM   	_instancer   r   r   r   clear_instance  s
    z$SingletonConfigurable.clear_instancec                 O   s\   | j du r,| |i |}|  D ]
}||_ q 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   rM   r   r   r   )r4   argsr#   rb   r   r   r   r   instance  s    
zSingletonConfigurable.instancec                 C   s   t | do| jduS )zHas an instance been created?r   N)hasattrr   r3   r   r   r   r   *  s    z!SingletonConfigurable.initialized)
r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s   


+r   )r   copyr   r   rB   loaderr   r   r   r   Ztraitlets.traitletsr   r	   r
   r   r   r   r   r   r   Ztraitlets.utils.textr   r   textwrapr   rr   r   r   r   rO   r   r   r   r   r   <module>   s   ,
   	(