
    G@dy                        d Z ddlZddl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 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 ddlmZmZmZmZm Z  ddl!m"Z" eeef         Z#ee ef         Z$ee$e#f         Z%d  e&e          D             Z' ej(        e)          Z* G d de          Z+ G d dee+          Z, e,            Z-dS )zGlobal plugin registry.    N)DictListUnionTypeAnySetOptionalTuple)QObjectSignal)dependencies)_running_under_pytest)CONF)SpyderConfigurationAccessor)PluginsConfigPage)SpyderAPIError)PluginsSpyderPluginV2SpyderDockablePluginSpyderPluginWidgetSpyderPlugin)imac                 n    g | ]2}|                     d           s|dk    t          t          |          3S )r   All)
startswithgetattrr   ).0attrs     Glib/python3.11/site-packages/spyder/api/plugin_registration/registry.py
<listcomp>r!   $   sF     > > >$ooc**>/3u}} w%%/<}}    c                   2    e Zd ZeZdZdZdZdZdZ	d Z
d ZdS )PreferencesAdapterplugin_registryN c                     d S N self_unuseds     r    apply_plugin_settingsz(PreferencesAdapter.apply_plugin_settings3       r"   c                     d S r(   r)   r*   s     r    
apply_confzPreferencesAdapter.apply_conf6   r.   r"   )__name__
__module____qualname__r   CONF_WIDGET_CLASSNAMECONF_VERSIONADDITIONAL_CONF_OPTIONSADDITIONAL_CONF_TABSCONF_SECTIONr-   r0   r)   r"   r    r$   r$   *   sS        )DL"L      r"   r$   c                       e Zd ZdZ eee          Z	  fdZdededefdZ	dededefdZ
d	ed
ee         dee         fdZdedee         dedefdZdedee         dedededefdZd	efdZd	efdZd	efdZdddedee         dedededefdZ	 	 d8d	ededefdZd	edefdZ	 d9d	ed efd!Z	 	 d:d	ed"ed#edefd$Zd9d efd%Z	 d;d'ee e                  defd(Z!	 	 d<d'ee e                  d)edefd*Z"d	edefd+Z#d	efd,Z$d	edefd-Z%d	edefd.Z&d/ Z'd0e(eee         f         fd1Z)d0e(eee         f         fd2Z*d3 Z+d4 Z,d5 Z-d	edefd6Z.d7 Z/ xZ0S )=SpyderPluginRegistrya'  
    Global plugin registry.

    This class handles a plugin initialization/teardown lifetime, including
    notifications when a plugin is available or not.

    This registry alleviates the limitations of a topological sort-based
    plugin initialization by enabling plugins to have bidirectional
    dependencies instead of unidirectional ones.

    Notes
    -----
    1. This class should be instantiated as a singleton.
    2. A plugin should not depend on other plugin to perform its
       initialization since it could cause deadlocks.
    c                 ~   t                                                       t                              |            d | _        i | _        i | _        i | _        i | _        t          i           | _	        t          i           | _
        t          i           | _        t          i           | _        i | _        i | _        d S r(   )super__init__r$   mainplugin_dependentsplugin_dependenciesr%   plugin_availabilitysetold_pluginsenabled_pluginsinternal_pluginsexternal_pluginsall_internal_pluginsall_external_plugins)r+   	__class__s    r    r>   zSpyderPluginRegistry.__init__X   s    ##D))) 	 "$ $&   " $&  r77  #2ww !$B !$B %'! %'!!!r"   plugindependent_pluginkeyc                     | j                             |i           }|                    |g           }|                    |           |||<   || j         |<   dS )z=Add `dependent_plugin` to the list of dependents of `plugin`.N)r@   getappend)r+   rK   rL   rM   r@   plugin_strict_dependentss         r    _update_dependentsz'SpyderPluginRegistry._update_dependents   sd     266vrBB#4#8#8b#A#A  ''(8999!9#):v&&&r"   required_pluginc                     | j                             |i           }|                    |g           }|                    |           |||<   || j         |<   dS )z>Add `required_plugin` to the list of dependencies of `plugin`.N)rA   rO   rP   )r+   rK   rS   rM   rA   plugin_strict_dependenciess         r    _update_dependenciesz)SpyderPluginRegistry._update_dependencies   se     #6::62FF%8%<%<S"%E%E""))/:::#=C +> (((r"   plugin_namerequired_pluginsoptional_pluginsc                     |D ]0}|                      ||d           |                     ||d           1|D ]0}|                      ||d           |                     ||d           1dS )z8Update the dependencies and dependents of `plugin_name`.requiresoptionalN)rV   rR   )r+   rW   rX   rY   rK   s        r    _update_plugin_infoz(SpyderPluginRegistry._update_plugin_info   s     ' 	E 	EF%%k6:FFF##FKDDDD& 	E 	EF%%k6:FFF##FKDDDD	E 	Er"   main_windowPluginClassexternalreturnc                 
    t          t          j                            }t          t          j                            }j        t
                              d d            j        rt          j	                   t          |          D ]6}|t          j        k    r$t          t          |t          z                       }7t          |          D ]6}|t          j        k    r$t          t          |t          z                       }7                     ||            |t                    }| j        <   |j                             fd           |                                                                 |r xj        hz  c_        n xj        hz  c_        |rMj        }j        }	j        }
|                                }t3          j        ||	||
dt2          j                   |S )z,Instantiate and register a Spyder 5+ plugin.zRegistering plugin z - )configurationc                  <                          j                  S )N)	omit_conf)notify_plugin_availability	CONF_FILE)r_   rW   r+   s   r    <lambda>zBSpyderPluginRegistry._instantiate_spyder5_plugin.<locals>.<lambda>   s$    D33{'< 4 > > r"   N)kind)listrC   REQUIRESOPTIONALr5   loggerdebugrg   r   register_pluginr   r   ALL_PLUGINSr]   r%   sig_plugin_readyconnect
initialize_notify_plugin_dependenciesrG   rF   _spyder_module_name_spyder_package_name_spyder_versionget_descriptionr   addPLUGIN)r+   r^   r_   r`   rX   rY   rK   plugin_instancemodulepackage_nameversiondescriptionrW   s   ` `         @r    _instantiate_spyder5_pluginz0SpyderPluginRegistry._instantiate_spyder5_plugin   sS   
  K$8 9 9::K$8 9 9::!&H;HH;HHIII  	. ---+,, 	M 	MF$$#',<{,J(K(K#L#L +,, 	M 	MF$$#',<{,J(K(K#L#L  	  .>!1	3 	3 	3 &+kFFF,;[) 	(00> > > > > >	? 	? 	?
 	""$$$ 	((555  	3!!k]2!!!!!k]2!! 	I 4F&;L!1G)99;;KV\; 'L4GI I I I r"   argskwargsc                    |j         } ||g|R i |}t          |d          rCt          j        | v r4|                     t          j                  }|                    |           n|                                 || j        |<   |r| xj        |hz  c_        n| xj	        |hz  c_	        |                     t          j
                  }	|	                    |           |                     |d           |S )z+Instantiate and register a Spyder 4 plugin.COMPLETION_PROVIDER_NAMEF)r5   hasattrr   Completions
get_pluginregister_completion_pluginro   r%   rG   rF   Preferencesregister_plugin_preferencesrf   )
r+   r^   r_   r`   r   r   rW   r{   completionspreferencess
             r    _instantiate_spyder4_pluginz0SpyderPluginRegistry._instantiate_spyder4_plugin   s    "& &+kCDCCCFCC?$>?? 	."d**"oog.ABB66GGG++--- -<[)  	3!!k]2!!!!!k]2!! oog&9:://@@@ 	''U;;;r"   c                 l   | j         |         }| j                            |i           }|                    dg           }|                    dg           }||z   D ]Y}|| j         v rN| j                            |d          r3t                              d| d           |                    |           ZdS )z.Notify a plugin of its available dependencies.r[   r\   FPlugin z has already loadedN)r%   rA   rO   rB   rm   rn   _on_plugin_availabler+   rW   r{   rA   rX   rY   rK   s          r    rt   z0SpyderPluginRegistry._notify_plugin_dependencies   s    .{;"6::;KK.22:rBB.22:rBB&)99 	A 	AF---+//>> ALL!F6!F!F!FGGG#88@@@		A 	Ar"   c                 r   | j                             |i           }|                    dg           }|                    dg           }||z   D ]i}|| j        v r^| j                            |d          rCt                              d| d| d           | j        |         }|                    |           jdS )z>Notify dependents of a plugin that is going to be unavailable.r[   r\   FzNotifying plugin z that z is going to be turned offN)r@   rO   r%   rB   rm   rn   _on_plugin_teardown)r+   rW   r@   rX   rY   rK   r{   s          r    _notify_plugin_teardownz,SpyderPluginRegistry._notify_plugin_teardown  s     266{BGG,00R@@,00R@@&)99 	E 	EF---+//>> ELL "LV "L "L$/"L "L "L M M M&*&:6&BO#77DDD	E 	Er"   c                 p   | j         |         }| j                            |i           }|                    dg           }|                    dg           }||z   D ][}|| j         v rP| j                            |d          r5t                              d| d|            |                    |           \dS )z*Disconnect a plugin from its dependencies.r[   r\   FzDisconnecting z from N)r%   rA   rO   rB   rm   rn   r   r   s          r    _teardown_pluginz%SpyderPluginRegistry._teardown_plugin  s    .{;"6::;KK.22:rBB.22:rBB&)99 	@ 	@F---+//>> @LL!M+!M!MV!M!MNNN#77???		@ 	@r"   F)r`   c                :   t          |t          t          f          s!t          | dt           dt                     d}t          |t                    r|                     |||          }n.t          |t                    r|                     |||||          }|S )a  
        Register a plugin into the Spyder registry.

        Parameters
        ----------
        main_window: spyder.app.mainwindow.MainWindow
            Reference to Spyder's main window.
        PluginClass: type[SpyderPluginClass]
            The plugin class to register and create. It must be one of
            `spyder.app.registry.SpyderPluginClass`.
        *args: tuple
            Positional arguments used to initialize the plugin
            instance.
        external: bool
            If True, then the plugin is stored as a external plugin. Otherwise
            it will be marked as an internal plugin. Default: False
        **kwargs: dict
            Optional keyword arguments used to initialize the plugin instance.

        Returns
        -------
        plugin: SpyderPluginClass
            The instance of the registered plugin.

        Raises
        ------
        TypeError
            If the `PluginClass` does not inherit from any of
            `spyder.app.registry.SpyderPluginClass`

        Notes
        -----
        The optional `*args` and `**kwargs` will be removed once all
        plugins are migrated.
        z does not inherit from z nor N)
issubclassr   r   	TypeErrorr   r   )r+   r^   r_   r`   r   r   instances          r    ro   z$SpyderPluginRegistry.register_plugin'  s    P +'EFF 	D{ C C-C C4@C C D D D k>22 	B77[(4 4HH\22 	B77[(D&B BH r"   Tnotify_mainre   c                    t                               d| d           d| j        |<   |r| j                            ||           | j                            |i           }|                    dg           }|                    dg           }||z   D ]-}|| j        v r"| j        |         }|                    |           .|t          j
        k    r2t                      s&| j        |         }|                    |            dS dS dS )a  
        Notify dependent plugins of a given plugin of its availability.

        Parameters
        ----------
        plugin_name: str
            Name of the plugin that is available.
        notify_main: bool
            If True, then a signal is emitted to the main window to perform
            further registration steps.
        omit_conf: bool
            If True, then the main window is instructed to not write the
            plugin configuration into the Spyder configuration file.
        r   z, has finished loading, sending notificationsTr[   r\   N)rm   rn   rB   rq   emitr@   rO   r%   r   r   r   r   r   )	r+   rW   r   re   r@   rX   rY   rK   r{   s	            r    rf   z/SpyderPluginRegistry.notify_plugin_availability_  s?   " 	 -{ - - - 	. 	. 	. 15 -  	?!&&{I>>> !266{BGG,00R@@,00R@@&)99 	B 	BF---"&"6v">44[AAA'---6J6L6L-"2;?O77===== .---r"   c                     | j         |         }d}t          |t                    r|                                }n*t          |t                    r|                    d          }|S )aE  
        Check if a plugin from the registry can be deleted by its name.

        Paremeters
        ----------
        plugin_name: str
            Name of the plugin to check for deletion.

        Returns
        -------
        plugin_deleted: bool
            True if the plugin can be deleted. False otherwise.
        T)r%   
isinstancer   	can_closer   closing_plugin)r+   rW   r{   
can_deletes       r    can_delete_pluginz&SpyderPluginRegistry.can_delete_plugin  sf     .{;
o~66 	>(2244JJ66 	>(77==Jr"   save_undockedc                 <   | j         |         }t          |t                    r|                    |           dS t          |t                    rL|j        r|r|                    dd           n|                    dd           |                                 dS dS )aj  
        Dock plugin if undocked and save undocked state if requested

        Parameters
        ----------
        plugin_name: str
            Name of the plugin to check for deletion.
        save_undocked : bool, optional
            True if the undocked state needs to be saved. The default is False.

        Returns
        -------
        None.
        r   undocked_on_window_closeTFN)r%   r   r   close_windowr   _undocked_window
set_option_close_window)r+   rW   r   r{   s       r    dock_undocked_pluginz)SpyderPluginRegistry.dock_undocked_plugin  s      .{;o';<< 	,((}(EEEEE);<< 
	,/ 7M 7**.6 6 6 6  **.7 7 7 ))+++++
	, 
	,r"   teardowncheck_can_deletec                    t                               d|            | j        |         }|r|                     |          }|sdS t	          |t
                    r<t	          |t                    r^	 |                                                                 |                                	                                 n`# t          $ r Y nTw xY w|                                }|r:	 |                                 |	                                 n# t          $ r Y nw xY w	 |	                                 n# t          $ r Y nw xY w|r*|                     |           |                     |           	 |                    d           nb# t          $ r Y nVw xY wt	          |t                    r=	 |	                                 n# t          $ r Y nw xY w|r|                     |           | j                            |d           | j                            |d           |j        rt)          j        |           | j        D ]C}| j        |         }dD ]1}	|                    |	g           }
||
v r|
                    |           2D| j        D ]C}| j        |         }dD ]1}	|                    |	g           }||v r|                    |           2D| j                            |           | xj        |hz  c_        | xj        |hz  c_        | xj        |hz  c_        | xj        |hz  c_        | j                            |           dS )a  
        Remove and delete a plugin from the registry by its name.

        Paremeters
        ----------
        plugin_name: str
            Name of the plugin to delete.
        teardown: bool
            True if the teardown notification to other plugins should be sent
            when deleting the plugin, False otherwise.
        check_can_delete: bool
            True if the plugin should validate if it can be closed when this
            method is called, False otherwise.

        Returns
        -------
        plugin_deleted: bool
            True if the registry was able to teardown and remove the plugin.
            False otherwise.
        zDeleting plugin FTN>   r\   r[   )rm   rn   r%   r   r   r   r   
get_widgetclosedeleteLaterRuntimeErrorget_containerr   r   on_closer   r@   poprA   rg   r   unregister_pluginrO   removerB   rD   rE   rF   rG   )r+   rW   r   r   r{   r   	containerrK   all_plugin_dependentsrM   r@   all_plugin_dependenciesrA   s                r    delete_pluginz"SpyderPluginRegistry.delete_plugin  s   , 	555666.{;  	//<<J uo~66 *	: /+?@@ #..0066888#..00<<>>>>#   D ,99;;	 !)))!--////'   ++----    :%%k222 ,,[999((....   66 	:++----    :,,[999 	"";555 $$[$777$ 	4 "?333, 	: 	:F$($:6$B!/ : :$9$=$=c2$F$F!"333%,,[999:
 . 	< 	<F&*&>v&F#/ < <&=&A&A#r&J&J#"555'..{;;;<
 	 $$[111[M)-+.+. 	  ---ts[   2AB? ?
CC&(D 
DD D5 5
EE2F 
FF.G 
GGc                     t          | j                  t          | j                  z  D ]}|                     ||           dS )a  
        Dock undocked plugins and save undocked state if required.

        Parameters
        ----------
        save_undocked : bool, optional
            True if the undocked state needs to be saved. The default is False.

        Returns
        -------
        None.

        r   N)rC   rG   rF   r   )r+   r   rW   s      r    dock_all_undocked_pluginsz.SpyderPluginRegistry.dock_all_undocked_plugins-  s_     D)**S1F-G-GG	: 	:K%%= & : : : :	: 	:r"   N	excludingc                    |pt          i           }d}t          | j                  t          | j                  z  D ]D}||vr>| j        |         }t	          |t
                    r||                     |          z  }|s nE|S )aY  
        Determine if all plugins can be deleted except the ones to exclude.

        Parameters
        ----------
        excluding: Optional[Set[str]]
            A set that lists plugins (by name) that will not be deleted.

        Returns
        -------
        bool
            True if all plugins can be closed. False otherwise.
        T)rC   rG   rF   r%   r   r   r   )r+   r   r   rW   r{   s        r    can_delete_all_pluginsz+SpyderPluginRegistry.can_delete_all_plugins@  s     (R		 D)**S1F-G-GG	 	K)++"&"6{"Co|<< !7!7!D!DDI$ r"   close_immediatelyc                    |pt          i           }d}|                     |          }|s|sdS |                     d           t          | j                  D ]I}||vrC| j        |         }t          |t                    r!||                     |dd          z  }|s|s nJ|sdS t          | j                  D ]I}||vrC| j        |         }t          |t                    r!||                     |dd          z  }|s|s nJ|sdS t          | j                  D ]I}||vrC| j        |         }t          |t                    r!||                     |dd          z  }|s|s nJ|s|sdS t          | j                  D ]I}||vrC| j        |         }t          |t                    r!||                     |dd          z  }|s|s nJ|S )ap  
        Remove all plugins from the registry.

        The teardown mechanism will remove external plugins first and then
        internal ones, where the Spyder 4 plugins will be removed first and
        then the Spyder 5 ones.

        Parameters
        ----------
        excluding: Optional[Set[str]]
            A set that lists plugins (by name) that will not be deleted.
        close_immediately: bool
            If true, then the `can_close` status will be ignored.

        Returns
        -------
        all_deleted: bool
            True if all the plugins were closed and deleted. False otherwise.
        T)r   Fr   )r   r   )
rC   r   r   rG   r%   r   r   r   rF   r   )r+   r   r   r   rW   r{   s         r    delete_all_pluginsz'SpyderPluginRegistry.delete_all_plugins^  s   * (R		 //)/DD	 	!2 	5 	&&T&::: t455 	 	K)++"&"6{"Co|<< !3!3#ee "4 "M "M MI$ ->  	5 t455 	 	K)++"&"6{"Co|<< !3!3#ee "4 "M "M MI$ ->  	5 t455 	 	K)++"&"6{"Co~>> !3!3#ee "4 "M "M MI$ ->  	!2 	5 t455 	 	K)++"&"6{"Co~>> !3!3#ee "4 "M "M MI$ -> r"   c                 X    || j         v r| j         |         }|S t          d| d          )a  
        Get a reference to a plugin instance by its name.

        Parameters
        ----------
        plugin_name: str
            Name of the plugin to retrieve.

        Returns
        -------
        plugin: SpyderPluginClass
            The instance of the requested plugin.

        Raises
        ------
        SpyderAPIError
            If the plugin name was not found in the registry.
        r   z was not found in the registry)r%   r   )r+   rW   r{   s      r    r   zSpyderPluginRegistry.get_plugin  sM    & $..."2;?O""  "0; "0 "0 "0 1 1 1r"   c                 (    | xj         |hz  c_         dS )z
        Add a plugin name to the set of enabled plugins.

        Parameters
        ----------
        plugin_name: str
            Name of the plugin to add.
        NrE   r+   rW   s     r    set_plugin_enabledz'SpyderPluginRegistry.set_plugin_enabled  s      	-r"   c                     || j         v S )a>  
        Determine if a given plugin is enabled and is going to be
        loaded.

        Parameters
        ----------
        plugin_name: str
            Name of the plugin to query.

        Returns
        -------
        plugin_enabled: bool
            True if the plugin is enabled and False if not.
        r   r   s     r    is_plugin_enabledz&SpyderPluginRegistry.is_plugin_enabled       d222r"   c                 8    | j                             |d          S )a1  
        Determine if a given plugin was loaded and is available.

        Parameters
        ----------
        plugin_name: str
            Name of the plugin to query.

        Returns
        -------
        plugin_available: bool
            True if the plugin is available and False if not.
        F)rB   rO   r   s     r    is_plugin_availablez(SpyderPluginRegistry.is_plugin_available  s     '++K???r"   c                 B   i | _         i | _        i | _        i | _        t	          i           | _        t	          i           | _        t	          i           | _        t	          i           | _        	 | j	        
                                 dS # t          t          f$ r Y dS w xY w)z$Reset and empty the plugin registry.N)r@   rA   r%   rB   rC   rD   rE   rF   rG   rq   
disconnectr   r   r+   s    r    resetzSpyderPluginRegistry.reset  s     "$ $&   " $&  r77  #2ww !$B !$B	!,,.....<( 	 	 	DD	s   .B	 	BBall_pluginsc                     || _         d S r(   )rH   r+   r   s     r    set_all_internal_pluginsz-SpyderPluginRegistry.set_all_internal_plugins      $/!!!r"   c                     || _         d S r(   )rI   r   s     r    set_all_external_pluginsz-SpyderPluginRegistry.set_all_external_plugins  r   r"   c                     || _         d S r(   )r?   )r+   r?   s     r    set_mainzSpyderPluginRegistry.set_main"  s    			r"   c                 *    t          j        d          S )Nplugins)r   iconr   s    r    get_iconzSpyderPluginRegistry.get_icon%  s    x	"""r"   c                      t          d          S )Nr   )r   r   s    r    get_namezSpyderPluginRegistry.get_name(  s    ||r"   c                     || j         v S )aN  
        Determine if a plugin name is contained in the registry.

        Parameters
        ----------
        plugin_name: str
            Name of the plugin to seek.

        Returns
        -------
        is_contained: bool
            If True, the plugin name is contained on the registry, False
            otherwise.
        )r%   r   s     r    __contains__z!SpyderPluginRegistry.__contains__+  r   r"   c                 *    t          | j                  S r(   )iterr%   r   s    r    __iter__zSpyderPluginRegistry.__iter__<  s    D()))r"   )TF)F)TTr(   )NF)1r1   r2   r3   __doc__r   strboolrq   r>   rR   rV   r   r]   r   r   Spyder5PluginClassr   Spyder4PluginClasstupledictr   rt   r   r   SpyderPluginClassro   rf   r   r   r   r   r	   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__)rJ   s   @r    r;   r;   :   s        " vc4((	%' %' %' %' %'P; ; ;# ; ; ; ;?3 ? ?"%? ? ? ?
Es 
E.23i
E.23i
E 
E 
E 
E9"9019 9  29 9 9 9v$"$01$ $ 	$ "&	$ +=	$ $ $ $LAs A A A AE3 E E E E@C @ @ @ @" ,16 6 6"6/06 6 %)6 	6  1	6 6 6 6r 8<5:'> '>c '>04'>.2'> '> '> '>RS T    2 ;@, ,",37, , , ,B @D/3j j j j(,j8<j j j jX: :t : : : :( @D *23s8*<HL   < BF5:R RHSX,> R.2R?CR R R Rh1c 1.? 1 1 1 14	.c 	. 	. 	. 	.3S 3T 3 3 3 3"@s @t @ @ @ @      D0#C.?)@$@A0 0 0 00#C.?)@$@A0 0 0 0  # # #  3 3 3 3 3 3"* * * * * * *r"   r;   ).r   loggingtypingr   r   r   r   r   r   r	   r
   qtpy.QtCorer   r   spyderr   spyder.config.baser   r   spyder.config.managerr   spyder.api.config.mixinsr   (spyder.api.plugin_registration._confpager   spyder.api.exceptionsr   spyder.api.pluginsr   r   r   r   r   spyder.utils.icon_managerr   r   r   r   dirrp   	getLoggerr1   rm   r$   r;   PLUGIN_REGISTRYr)   r"   r    <module>r      s       E E E E E E E E E E E E E E E E E E E E ( ' ' ' ' ' ' '        6 6 6 6 6 6 6 6 & & & & & & @ @ @ @ @ @ F F F F F F 0 0 0 0 0 0              * ) ) ) ) )
 >+??@ <);;< ,.@@A > >##g,, > > > 
	8	$	$    4    C* C* C* C* C*7$6 C* C* C*L '&((r"   