
    Jey                        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% e&e      D  cg c]!  } | jO                  d      s| dk7  r	 e(e|       # c} Z) ejT                  e+      Z, G d de      Z- G d dee-      Z. e.       Z/yc c} w )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)imar   Allc                   0    e Zd ZeZdZdZdZdZdZ	d Z
d Zy)PreferencesAdapterplugin_registryN c                      y N self_unuseds     I/usr/lib/python3/dist-packages/spyder/api/plugin_registration/registry.pyapply_plugin_settingsz(PreferencesAdapter.apply_plugin_settings3           c                      y 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&   r*   r!   r(   r%   r   r   *   s-    )DL"Lr(   r   c                   d    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	 	 d6d	ededefdZd	edefdZ	 d7d	edefd Z	 	 d8d	ed!ed"edefd#Zd7defd$Z	 d9d%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'd.e(eee   f   fd/Z)d.e(eee   f   fd0Z*d1 Z+d2 Z,d3 Z-d	edefd4Z.d5 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        j                  |        d | _        i | _        i | _        i | _        i | _        t        i       | _	        t        i       | _
        t        i       | _        t        i       | _        i | _        i | _        y 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%   r8   zSpyderPluginRegistry.__init__X   s    ##D) 	 "$ $&   " $&  r7  #2w !$B !$B %'! %'!r(   plugindependent_pluginkeyc                     | j                   j                  |i       }|j                  |g       }|j                  |       |||<   || j                   |<   y)z=Add `dependent_plugin` to the list of dependents of `plugin`.N)r:   getappend)r#   rE   rF   rG   r:   plugin_strict_dependentss         r%   _update_dependentsz'SpyderPluginRegistry._update_dependents   sX     2266vrB#4#8#8b#A  ''(89!9#):v&r(   required_pluginc                     | j                   j                  |i       }|j                  |g       }|j                  |       |||<   || j                   |<   y)z>Add `required_plugin` to the list of dependencies of `plugin`.N)r;   rI   rJ   )r#   rE   rM   rG   r;   plugin_strict_dependenciess         r%   _update_dependenciesz)SpyderPluginRegistry._update_dependencies   sY     #66::62F%8%<%<S"%E""))/:#=C +>  (r(   plugin_namerequired_pluginsoptional_pluginsc                     |D ](  }| j                  ||d       | j                  ||d       * |D ](  }| j                  ||d       | j                  ||d       * y)z8Update the dependencies and dependents of `plugin_name`.requiresoptionalN)rP   rL   )r#   rQ   rR   rS   rE   s        r%   _update_plugin_infoz(SpyderPluginRegistry._update_plugin_info   sp     ' 	EF%%k6:F##FKD	E ' 	EF%%k6:F##FKD	Er(   main_windowPluginClassexternalreturnc                     t        t        j                              }t        t        j                              }j                  t
        j                  d d        j                  rt        j                         t        |      D ]1  }|t        j                  k(  st        t        |t        z               }3 t        |      D ]1  }|t        j                  k(  st        t        |t        z               }3  j                  ||        |t              }| j                  <   |j                  j!                   fd       |j#                           j%                         |r xj&                  hz  c_        n xj(                  hz  c_        |r]j*                  }j,                  }	j.                  }
|j1                         }t3        j4                  ||	||
dt2        j6                         |S )z,Instantiate and register a Spyder 5+ plugin.zRegistering plugin z - )configurationc                  >    j                   j                        S )N)	omit_conf)notify_plugin_availability	CONF_FILE)rY   rQ   r#   s   r%   <lambda>zBSpyderPluginRegistry._instantiate_spyder5_plugin.<locals>.<lambda>   s"    D33{'<'< 4 > r(   N)kind)listr=   REQUIRESOPTIONALr/   loggerdebugra   r   register_pluginr   r   ALL_PLUGINSrW   r   sig_plugin_readyconnect
initialize_notify_plugin_dependenciesrA   r@   _spyder_module_name_spyder_package_name_spyder_versionget_descriptionr   addPLUGIN)r#   rX   rY   rZ   rR   rS   rE   plugin_instancemodulepackage_nameversiondescriptionrQ   s   ` `         @r%   _instantiate_spyder5_pluginz0SpyderPluginRegistry._instantiate_spyder5_plugin   s   
  K$8$8 9:K$8$8 9:!&&*;-s;-HI    -+, 	MF$#',<{,J(K#L 	M +, 	MF$#',<{,J(K#L 	M
 	  .>!1	3 &kF,;[) 	((00>	?
 	""$ 	((5 !!k]2!!!k]2! 44F&;;L!11G)99;KV\; 'L4G4GI r(   argskwargsc                    |j                   } ||g|i |}t        |d      rCt        j                  | v rA| j	                  t        j                        }|j                  |       n|j                          || j                  |<   |r| xj                  |hz  c_        n| xj                  |hz  c_	        | j	                  t        j                        }	|	j                  |       | j                  |d       |S )z+Instantiate and register a Spyder 4 plugin.COMPLETION_PROVIDER_NAMEF)r/   hasattrr   Completions
get_pluginregister_completion_pluginri   r   rA   r@   Preferencesregister_plugin_preferencesr`   )
r#   rX   rY   rZ   r{   r|   rQ   ru   completionspreferencess
             r%   _instantiate_spyder4_pluginz0SpyderPluginRegistry._instantiate_spyder4_plugin   s     "&& &kCDCFC?$>?""d*"oog.A.AB66G++- -<[) !!k]2!!!k]2! oog&9&9://@ 	''U;r(   c                 b   | j                   |   }| j                  j                  |i       }|j                  dg       }|j                  dg       }||z   D ]X  }|| j                   v s| j                  j                  |d      s/t        j                  d| d       |j                  |       Z y)z.Notify a plugin of its available dependencies.rU   rV   FPlugin z has already loadedN)r   r;   rI   r<   rg   rh   _on_plugin_availabler#   rQ   ru   r;   rR   rS   rE   s          r%   rn   z0SpyderPluginRegistry._notify_plugin_dependencies   s    ..{;"66::;K.22:rB.22:rB&)99 	AF---++//>LL76(2E!FG#88@		Ar(   c                 h   | j                   j                  |i       }|j                  dg       }|j                  dg       }||z   D ]j  }|| j                  v s| j                  j                  |d      s/t        j                  d| d| d       | j                  |   }|j                  |       l y)z>Notify dependents of a plugin that is going to be unavailable.rU   rV   FzNotifying plugin z that z is going to be turned offN)r:   rI   r   r<   rg   rh   _on_plugin_teardown)r#   rQ   r:   rR   rS   rE   ru   s          r%   _notify_plugin_teardownz,SpyderPluginRegistry._notify_plugin_teardown  s     2266{BG,00R@,00R@&)99 	EF---++//>LL#4VHF$/=0J"L M&*&:&:6&BO#77D	Er(   c                 f   | j                   |   }| j                  j                  |i       }|j                  dg       }|j                  dg       }||z   D ]Z  }|| j                   v s| j                  j                  |d      s/t        j                  d| d|        |j                  |       \ y)z*Disconnect a plugin from its dependencies.rU   rV   FzDisconnecting z from N)r   r;   rI   r<   rg   rh   r   r   s          r%   _teardown_pluginz%SpyderPluginRegistry._teardown_plugin  s    ..{;"66::;K.22:rB.22:rB&)99 	@F---++//>LL>+fVH!MN#77?		@r(   F)rZ   c                    t        |t        t        f      st        | dt         dt               d}t        |t              r| j	                  |||      }|S t        |t              r| j                  |||||      }|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   	TypeErrorrz   r   )r#   rX   rY   rZ   r{   r|   instances          r%   ri   z$SpyderPluginRegistry.register_plugin'  s    P +'EF{m+B-.eL>C D D k>277[(4H  \277[(D&BH r(   notify_mainr_   c                     t         j                  d| d       d| j                  |<   |r| j                  j	                  ||       | j
                  j                  |i       }|j                  dg       }|j                  dg       }||z   D ]1  }|| j                  v s| j                  |   }|j                  |       3 |t        j                  k(  r,t               s!| j                  |   }|j                  |        yyy)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 notificationsTrU   rV   N)rg   rh   r<   rk   emitr:   rI   r   r   r   r   r   r   )	r#   rQ   r   r_   r:   rR   rS   rE   ru   s	            r%   r`   z/SpyderPluginRegistry.notify_plugin_availability_  s   " 	w{m ,- - 	. 15  - !!&&{I> !2266{BG,00R@,00R@&)99 	BF---"&"6"6v">44[A	B
 '---6J6L"22;?O77= 7M-r(   c                     | j                   |   }d}t        |t              r|j                         }|S t        |t              r|j                  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#   rQ   ru   
can_deletes       r%   can_delete_pluginz&SpyderPluginRegistry.can_delete_plugin  s[     ..{;
o~6(224J  6(77=Jr(   save_undockedc                    | j                   |   }t        |t              r|j                  |       yt        |t              rD|j
                  r|r|j                  dd       n|j                  dd       |j                          yy)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#   rQ   r   ru   s       r%   dock_undocked_pluginz)SpyderPluginRegistry.dock_undocked_plugin  s      ..{;o';<((}(E);<//M**.6  **.7 ))+ =r(   teardowncheck_can_deletec                 B   t         j                  d|        | j                  |   }|r| j                  |      }|syt	        |t
              rt	        |t              r>	 |j                         j                          |j                         j                          n3|j                         }|r!	 |j                          |j                          	 |j                          |r"| j                  |       | j                  |       	 |j                  d       n4t	        |t              r$	 |j                          |r| j                  |       | j                   j#                  |d       | j$                  j#                  |d       |j&                  rt)        j*                  |       | j                   D ]@  }| j                   |   }dD ]*  }	|j-                  |	g       }
||
v s|
j/                  |       , B | j$                  D ]@  }| j$                  |   }dD ]*  }	|j-                  |	g       }||v s|j/                  |       , B | j0                  j#                  |       | xj2                  |hz  c_        | xj4                  |hz  c_        | xj6                  |hz  c_        | xj8                  |hz  c_        | j                  j#                  |       y# t        $ r Y w xY w# t        $ r Y w xY w# t        $ r Y w xY w# t        $ r Y w xY w# t        $ r Y w xY w)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>   rV   rU   )rg   rh   r   r   r   r   r   
get_widgetclosedeleteLaterRuntimeErrorget_containerr   r   on_closer   r:   popr;   ra   r   unregister_pluginrI   remover<   r>   r?   r@   rA   )r#   rQ   r   r   ru   r   	containerrE   all_plugin_dependentsrG   r:   all_plugin_dependenciesr;   s                r%   delete_pluginz"SpyderPluginRegistry.delete_plugin  s   , 	'}56..{; //<Jo~6 /+?@#..0668#..0<<> ,99;	!)!--/
++- %%k2 ,,[9((. 6++- ,,[9 	"";5  $$[$7$$ ""?3,, 	:F$($:$:6$B!/ :$9$=$=c2$F!"33%,,[9:	: .. 	<F&*&>&>v&F#/ <&=&A&A#r&J#"55'..{;<	< 	  $$[1[M)-+.+. 	  -I $  (       
   sZ   <K / K! K1 L (L 	KK!	K.-K.1	K>=K>	LL	LLc                     t        | j                        t        | j                        z  D ]  }| j                  ||        y)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)r=   rA   r@   r   )r#   r   rQ   s      r%   dock_all_undocked_pluginsz.SpyderPluginRegistry.dock_all_undocked_plugins-  sF     D))*S1F1F-GG	:K%%= & :	:r(   	excludingc                    |xs t        i       }d}t        | j                        t        | j                        z  D ]@  }||vs| j                  |   }t	        |t
              s(|| j                  |      z  }|r? |S  |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)r=   rA   r@   r   r   r   r   )r#   r   r   rQ   ru   s        r%   can_delete_all_pluginsz+SpyderPluginRegistry.can_delete_all_plugins@  s     (R		 D))*S1F1F-GG	K)+"&"6"6{"Co|<!7!7!DDI$	 r(   close_immediatelyc                 z   |xs t        i       }d}| j                  |      }|s|sy| j                  d       t        | j                        D ]E  }||vs| j                  |   }t        |t              s(|| j                  |dd      z  }|rB|rE n |syt        | j                        D ]E  }||vs| j                  |   }t        |t              s(|| j                  |dd      z  }|rB|rE n |syt        | j                        D ]E  }||vs| j                  |   }t        |t              s(|| j                  |dd      z  }|rB|rE n |s|syt        | j                        D ]F  }||vs| j                  |   }t        |t              s(|| j                  |dd      z  }|rB|rE |S  |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   )
r=   r   r   rA   r   r   r   r   r@   r   )r#   r   r   r   rQ   ru   s         r%   delete_all_pluginsz'SpyderPluginRegistry.delete_all_plugins^  s!   * (R		 //)/D	!2 	&&T&: t445 	K)+"&"6"6{"Co|<!3!3#ee "4 "M MI$->	  t445 	K)+"&"6"6{"Co|<!3!3#ee "4 "M MI$->	  t445 	K)+"&"6"6{"Co~>!3!3#ee "4 "M MI$->	 !2 t445 	K)+"&"6"6{"Co~>!3!3#ee "4 "M MI$->	 r(   c                 ^    || 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#   rQ   ru   s      r%   r   zSpyderPluginRegistry.get_plugin  sE    & $..."22;?O"" 7;- 80 "0 1 1r(   c                 0    | xj                   |hz  c_         y)z
        Add a plugin name to the set of enabled plugins.

        Parameters
        ----------
        plugin_name: str
            Name of the plugin to add.
        Nr?   r#   rQ   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22r(   c                 :    | j                   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)r<   rI   r   s     r%   is_plugin_availablez(SpyderPluginRegistry.is_plugin_available  s     ''++K??r(   c                    i | _         i | _        i | _        i | _        t	        i       | _        t	        i       | _        t	        i       | _        t	        i       | _        	 | j                  j                          y# t        t        f$ r Y yw xY w)z$Reset and empty the plugin registry.N)r:   r;   r   r<   r=   r>   r?   r@   rA   rk   
disconnectr   r   r#   s    r%   resetzSpyderPluginRegistry.reset  s     "$ $&   " $&  r7  #2w !$B !$B	!!,,.<( 		s   A9 9B
Ball_pluginsc                     || _         y r    )rB   r#   r   s     r%   set_all_internal_pluginsz-SpyderPluginRegistry.set_all_internal_plugins  
    $/!r(   c                     || _         y r    )rC   r   s     r%   set_all_external_pluginsz-SpyderPluginRegistry.set_all_external_plugins  r   r(   c                     || _         y r    )r9   )r#   r9   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    xx	""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)1r+   r,   r-   __doc__r   strboolrk   r8   rL   rP   r   rW   r   r   Spyder5PluginClassrz   Spyder4PluginClasstupledictr   rn   r   r   SpyderPluginClassri   r`   r   r   r   r   r	   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__)rD   s   @r%   r5   r5   :   s   " c4(	%'P; ; ;# ;?3 ? ?"%?
Es 
E.23i
E.23i
E9"9019 9  29v$"$01$ $ 	$ "&	$ +=	$LAs AE3 E@C @" ,16"6/06 6 %)6 	6  1	6r 8<5:'>c '>04'>.2'>RS T 2 ;@,",37,B @D/3j j j(,j8<jX:t :( @D*23s8*<HL< BF5:RHSX,> R.2R?CRh1c 1.? 14	.c 	.3S 3T 3"@s @t @  D0#C.?)@$@A00#C.?)@$@A0#3 3 3"*r(   r5   )0r   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   dir
startswithgetattrrj   	getLoggerr+   rg   r   r5   PLUGIN_REGISTRY)attrs   0r%   <module>r      s      E E E (   6 & @ F 0  *
 >+??@ <);;< ,.@@A  36g, >$ooc*tu} w% > 
		8	$4  C*7$6 C*L '(y>s   <&C