
    Je_                        d Z ddlZddlZddlZddlZddlmZm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 ddlmZ ddlmZmZ dd	lmZmZ dd
lmZmZ ddlmZ ddl m!Z!m"Z"m#Z# ddl$m%Z% ddl&m'Z'  ejP                  e)      Z* e+e!      D  cg c]  } | jY                         r	 e-e!|        c} Z.d Z/ G d de      Z0yc c} w )z
Spyder completion plugin.

This plugin is in charge of creating and managing multiple code completion and
introspection providers.
    N)ListUnion)parse)iter_entry_points)QMutexQMutexLockerQTimerSlotSignal)CONF)SpyderPluginV2Plugins)on_plugin_availableon_plugin_teardown)_running_under_pytest	NoDefault)CompletionRequestTypesSpyderCompletionProviderCOMPLETION_ENTRYPOINT)CompletionConfigPage)CompletionContainerc                 *      G  fdd       }|S )z#Return a partial class constructor.c                   T    e Zd Z ej                  W j
                  gW  i W Zy)partialclass.<locals>.NewClsN)__name__
__module____qualname__	functoolspartialmethod__init__)argsclskwdss   B/usr/lib/python3/dist-packages/spyder/plugins/completion/plugin.pyNewClsr   3   s#    *9**3<<G$G$G    r'    )r$   r#   r%   r'   s   ``` r&   partialclassr*   1   s    H H HMr(   c                       e Zd ZdZdZdZej                  ej                  gZ	ej                  ej                  ej                  gZdZi ZdZeZ eeee      Z	  ee      Z	  eee      Z	  e       Z	  eee      Z	  ee      Z	  eeee      Z	  ee      Z 	 dZ!dZ"e#jH                  hZ%e#jH                  hZ&db fd	Z'e(defd	       Z)defd
Z*d Z+d Z, e-ej                        d        Z. e-ej                        d        Z/ e-ej                        d        Z0 e-ej                        d        Z1 e-ej                        d        Z2 e3ej                        d        Z4 e3ej                        d        Z5 e3ej                        d        Z6 e3ej                        d        Z7 e3ej                        d        Z8d Z9de:fdZ;dcde:fdZ<de=e>eef      fdZ?d Z@dddZAdddZBd  ZCeDd!        ZE eF       d"        ZGd# ZHd$ ZId% ZJd& ZKd' ZLd( ZMd) ZNe(d*eOd+ed,efd-       ZPd*eOd+edefd.ZQd*eOd+efd/ZRd0 ZSd*eOfd1ZTdcd2ZU eFe      d+efd3       ZVd4ede:fd5ZWd4efd6ZXd7edeOfd8ZYd7ede:fd9ZZd4ede=e   fd:Z[d4ede:fd;Z\d<e=e   d=ede=e   fd>Z]d+efd?Z^d+efd@Z_dA Z`dB ZadC ZbdD ZcdE ZddF ZedG ZfdH ZgdI Zhd4ed=edJefdKZid4edLedMefdNZjd=edJefdOZk	 	 dedPefdQZl eFee      dRed4efdS       Zmd4edRefdTZn eFeee      dUedVedWefdX       Zo eFe      dVefdY       ZpdVefdZZqdVefd[Zrd\efd]Zsd^efd_Ztd=ed`efdaZu xZvS )fCompletionPlugina  
    Spyder completion plugin.

    This class provides a completion and linting plugin for the editor in
    Spyder.

    This plugin works by forwarding all the completion/linting requests to a
    set of :class:`SpyderCompletionProvider` instances that are discovered
    and registered via entrypoints.

    This plugin can assume that `fallback`, `snippets`, `lsp` and `kite`
    completion providers are available, since they are included as part of
    Spyder.
    completionsFNrunningstoppedc                    t         |   ||       i | _        i | _        i | _        i | _        d| _        t        t        j                        | _	        i | _
        i | _        | j                  d      | _        g | _        g | _        t!        t"              D ]K  }	 d|j$                  v rt&        j)                  d|        |j+                         }| j-                  |       M | j3                  d       | j5                         \  }}t7        t8        |      | _        d	|i| _        y # t.        $ r}t&        j1                  d|        |d }~ww xY w)
Nr   completions_wait_for_mskitezLoading entry point: z4Failed to load completion provider from entry point Fplugin_loaded	providersr-   )superr"   _available_providersr6   language_statusrequestsreq_idr   	Recursivecollection_mutexsource_priorityprovider_speedget_confwait_for_msapplication_menus_to_create!items_to_add_to_application_menusr   r   nameloggerdebugresolve"_instantiate_and_register_provider	Exceptionwarningregister_statusbar_widgetsgather_providers_and_configtabsr*   r   CONF_WIDGET_CLASSADDITIONAL_CONF_TABS)	selfparentconfigurationentry_pointProvidereconf_providers	conf_tabs	__class__s	           r&   r"   zCompletionPlugin.__init__   sj   / %'!   "   !'v'7'7 8  " !  ==)BC ,.( 24. --BC 	K
 [---4[MBC&..077A	" 	''e'< '+&J&J&L#!- N"<%2I$>!    ((3} 6 7s   D''9D''	E0E

Ereturnc                      t        d      S )NzCompletion and lintingr   r)   r(   r&   get_namezCompletionPlugin.get_name  s    )**r(   c                     t        d      S )NzThis plugin is in charge of handling and dispatching, as well as of receiving the responses of completion and linting requests sent to multiple providers.rZ   rO   s    r&   get_descriptionz CompletionPlugin.get_description  s     @ A 	Ar(   c                 $    | j                  d      S )Nr-   )create_iconr]   s    r&   get_iconzCompletionPlugin.get_icon  s    ..r(   c                 2   | j                   j                  | j                         t               rXt        j
                  j                  d      s9| j                  D ])  }| j                  |   }t        j                  |d          + y | j                          y )NSPY_TEST_USE_INTROSPECTIONinstance)sig_interpreter_changedconnectupdate_completion_statusr   osenvirongetr6   r   unobserve_configurationstart_all_providersrO   provider_nameprovider_infos      r&   on_initializezCompletionPlugin.on_initialize  s|    $$,,T-J-JK  !::>>">?%)^^ LM$(NN=$AM00z1JKL   "r(   )pluginc                 d    | j                  t        j                        }|j                  |        y N)
get_pluginr   Preferencesregister_plugin_preferencesrO   preferencess     r&   on_preferences_availablez)CompletionPlugin.on_preferences_available!  s$    oog&9&9://5r(   c                 
   | j                  t        j                        }|j                         }| j                  j
                  j                  |j
                         |j                  j                  | j                         y rs   )rt   r   MainInterpreterget_containercompletion_statussig_open_preferences_requestedrf   re   rO   maininterpretermi_containers      r&   on_maininterpreter_availablez-CompletionPlugin.on_maininterpreter_available&  sh    //'*A*AB&446 	==EE77	9 	,,44((	*r(   c                    | j                         }| j                  t        j                        | _        |j                         D ]  }| j                  j                  |        | j                  j                  | j                         y rs   )r|   rt   r   	StatusBar	statusbarall_statusbar_widgetsadd_status_widgetr}   rO   	containersbs      r&   on_statusbar_availablez'CompletionPlugin.on_statusbar_available2  sh    &&(	):):;113 	1BNN,,R0	1(()?)?@r(   c                     | j                  t        j                        }| j                  D ]  \  }} |j                  |i |  | j
                  D ]  \  }} |j                  |i |  y rs   )rt   r   MainMenurB   create_application_menurC   add_item_to_application_menu)rO   	main_menur#   kwargss       r&   on_mainmenu_availablez&CompletionPlugin.on_mainmenu_available:  sx    OOG$4$45	 !<< 	?LD&-I--t>v>	? !BB 	DLD&2I22DCFC	Dr(   c                     | j                  t        j                        }|j                  j	                  | j                         y rs   )rt   r   PythonpathManagersig_pythonpath_changedrf   rO   pythonpath_managers     r&   on_pythonpath_manager_availablez0CompletionPlugin.on_pythonpath_manager_availableF  s4    !__W-F-FG1199''	)r(   c                 d    | j                  t        j                        }|j                  |        y rs   )rt   r   ru   deregister_plugin_preferencesrw   s     r&   on_preferences_teardownz(CompletionPlugin.on_preferences_teardownL  s$    oog&9&9:11$7r(   c                     | j                  t        j                        }|j                         }|j                  j                  | j                         y rs   )rt   r   r{   r|   re   
disconnectr   s      r&   on_maininterpreter_teardownz,CompletionPlugin.on_maininterpreter_teardownQ  sA    //'*A*AB&446,,77((	*r(   c                     | j                         }| j                  t        j                        | _        |j                         D ]'  }| j                  j                  |j                         ) y rs   )r|   rt   r   r   r   r   remove_status_widgetIDr   s      r&   on_statusbar_teardownz&CompletionPlugin.on_statusbar_teardownY  sT    &&(	):):;113 	7BNN//6	7r(   c                    | j                  t        j                        }t        j                  |j
                        }| j                  D ]  \  }}|d   }|j                  |        | j                  D ]  \  }} |j                  |i |}|j                          |j                  d   }|j                  d   }d }t        |d      r|j                  }nt        |d      r|j                  }|||j                  ||        y )Nr   itemmenu_id	action_id)r   )rt   r   r   inspect	signaturer   rB   remove_application_menurC   bindapply_defaults	argumentshasattrr   r   !remove_item_from_application_menu)	rO   r   r   r#   r   r   bindingr   item_ids	            r&   on_mainmenu_teardownz%CompletionPlugin.on_mainmenu_teardown`  s   OOG$4$45	%%i&L&LM	 << 	7LD&1gG--g6	7 !BB 	.LD&$innd5f5G""$$$V,D''	2GGt[)..y),,";;W < .	.r(   c                     | j                  t        j                        }|j                  j	                  | j                         y rs   )rt   r   r   r   r   r   s     r&   on_pythonpath_manager_teardownz/CompletionPlugin.on_pythonpath_manager_teardownx  s4    !__W-F-FG11<<''	)r(   c                     | j                   D ]7  }| j                   |   }|d   | j                  k(  s%|d   j                          9 y)z&Stop all running completion providers.statusrd   N)r6   RUNNINGshutdownrm   s      r&   stop_all_providersz#CompletionPlugin.stop_all_providers  sE    !^^ 	5M NN=9MX&$,,6j)224		5r(   c                     d}| j                   D ]>  }| j                   |   }|d   | j                  k(  s%|d   }|j                         }||z  }@ |S )z+Check if any provider has any pending task.Fr   rd   )r6   r   	can_close)rO   r   rn   ro   providerprovider_can_closes         r&   r   zCompletionPlugin.can_close  se    	!^^ 	0M NN=9MX&$,,6(4%-%7%7%9"//		0 r(   c                     d}| j                   D ]Q  }| j                   |   }|d   | j                  k(  s%|d   }|j                         }||z  }|sB|j                          S |S )z:Check if any provider has any pending task before closing.Fr   rd   )r6   r   r   r   )rO   
cancelabler   rn   ro   r   r   s          r&   on_closezCompletionPlugin.on_close  st    	!^^ 	(M NN=9MX&$,,6(4%-%7%7%9"//	%%%'	( r(   optionsc                    t        i       }|D ]  }|dk(  r| j                  d      | _        t        |t              s0|^}}}|dk(  r[| j                  d|f      }|r#| j                  |       | j                  |       r| j                  |       | j                  |       |dk(  s||hz  } | j                  j                  d|fi        y)z
        Update plugin and/or provider configurations.

        Settings are propagated from changes on the configuration page and/or
        provider tabs.
        r1   enabled_providersprovider_configurationupdate_source_menuN)setr@   rA   
isinstancetuplestart_provider_instanceregister_statusbar_widgetshutdown_provider_instanceunregister_statusbarsig_editor_rpcemit)rO   r   providers_to_updateoptionoption_namern   __provider_statuss           r&   after_configuration_updatez+CompletionPlugin.after_configuration_update  s     ""g 	;F22#'==-$/ FE*28/]R"55&*mm,m<'>O&44]C66}E77F11-@ $<<'M?:'!	;* 	  !5z2Fr(   c                 j    | j                   D ]$  }| j                   |   }|d   j                          & y )Nrd   )r6   on_mainwindow_visiblerm   s      r&   r   z&CompletionPlugin.on_mainwindow_visible  s4    !^^ 	>M NN=9M*%;;=	>r(   c                 z    | j                   D ],  }| j                  d|fd      }|s| j                  ||       . y)aS  
        Register status bar widgets for all providers with the container.

        Parameters
        ----------
        plugin_loaded: bool
            True if the plugin is already loaded in Spyder, False if it is
            being loaded. This is needed to avoid adding statusbar widgets
            multiple times at startup.
        r   Tr3   N)r6   r@   r   )rO   r4   provider_keyprovider_ons       r&   rK   z+CompletionPlugin.register_statusbar_widgets  sJ     !NN 	?L--$l3T;K..  / ?		?r(   c                 "   | j                         }| j                  |   d   }|j                  |j                  |      }|rO|D ]I  }|j                  |   }|| j
                  j                         vs/| j
                  j                  |       K yy)aQ  
        Register statusbar widgets for a given provider.

        Parameters
        ----------
        provider_name: str
            Name of the provider that is going to create statusbar widgets.
        plugin_loaded: bool
            True if the plugin is already loaded in Spyder, False if it is
            being loaded.
        rd   N)r|   r6   rK   STATUS_BAR_CLASSESstatusbar_widgetsr   get_status_widgetsr   )rO   rn   r4   r   r   widgets_idsid_current_widgets           r&   r   z*CompletionPlugin.register_statusbar_widget  s     &&(	>>-0<::''8" E!*!<!<S!A dnn??AANN44^DE r(   c                    | j                         }| j                         j                  |      }|D ]K  }||j                  v s| j                         j                  |       | j                  j                  |       M y)z
        Unregister statusbar widgets for a given provider.

        Parameters
        ----------
        provider_name: str
            Name of the provider that is going to delete statusbar widgets.
        N)r|   get_provider_statusbar_keysr   remove_statusbar_widgetr   r   )rO   rn   r   provider_keysr   s        r&   r   z%CompletionPlugin.unregister_statusbar  sv     &&(	**,HH  	9C i111""$<<SA33C8	9r(   c                 6    | j                         j                  S rs   )r|   r}   r]   s    r&   r}   z"CompletionPlugin.completion_status  s    !!#555r(   c                    | j                  t        j                        }|j                         j                  }|j
                  }|j                  }d|v r|j                  d      d   }d|v r|j                  d      \  }}n|d}}|j                         }|j                         }d| }|r	|d| dz  }| j                  j                  ||       y )N(r   : zCompletions: ))rt   r   r{   r|   interpreter_statusvalue_interpretersplitstripr}   update_status)rO   r   	mi_statusr   tool_tipkindrD   	new_values           r&   rg   z)CompletionPlugin.update_completion_status  s    //'*A*AB#113FF	))%<KK$Q'E%<S)JD$$Dzz|zz|#D6*	1TF!$I,,YAr(   c                 ,   g }g }| j                         }| j                  D ]  }| j                  |   d   }|j                  D ]  }t        |d| j	                  |             t        |d| j                  |             t        |d| j                  |             t        |d| j                  ||             |D ]#  \  }}t        ||| j                  |||             %  ||j                  z  }|j                  ||j                         f        ||fS )a  
        Gather and register providers and their configuration tabs.

        This method iterates over all completion providers, takes their
        corresponding configuration tabs, and patches the methods that
        interact with writing/reading/removing configuration options to
        consider provider options that are stored inside this plugin's
        `provider_configuration` option, which makes providers unaware
        of the CompletionPlugin existence.
        rd   
get_option
set_optionremove_optionapply_settings)gather_create_opsr6   	CONF_TABSsetattrwrap_get_optionwrap_set_optionwrap_remove_optionwrap_apply_settingswrap_create_opappendr[   )	rO   rU   rV   widget_funcsr   r   tabrD   poss	            r&   rL   z0CompletionPlugin.gather_providers_and_configtabs   s:    	--/ NN 	GL~~l3J?H)) J\,,\:<\,,\:<_//=? -00lCE ". JID#C //c<HJJJ$ +++I!!<1B1B1D"EF+	G. y((r(   c                 $   t        j                  t              }g }|D ]o  \  }}|j                  d      st        j                  |      }|j
                  }d|j
                  v sHd}|D ]  }|dk(  r n|dz  } |j                  ||f       q |S )z
        Extract all the create_* methods declared in the
        :class:`spyder.api.preferences.PluginConfigPage` class
        create_r      )r   
getmembersr   
startswithr   
parametersr  )	rO   membersr  rD   callsigr  r  params	            r&   r   z"CompletionPlugin.gather_create_opsH  s     $$%9:! 
	5JD$y)''- ^^
s~~-C!+ ! H,!q! !''s4
	5 r(   c                 (    | t         dffd	}|S )a=  
        Wraps `get_option` method for a provider config tab to consider its
        actual section nested inside the `provider_configuration` key of this
        plugin options.

        This wrapper method allows configuration tabs to not be aware about
        their presence behind the completion plugin.
        Nc                 l    |t        |t              r	ddg|}ndd|f}j                  |||      S Nr   values)r   r   r@   )rO   r   defaultsectionrq   r   s       r&   wrapperz1CompletionPlugin.wrap_get_option.<locals>.wrapperh  sN    fe,6( '%'F 7($&F??67G<<r(   r   rO   r   r  rq   s    ` @r&   r   z CompletionPlugin.wrap_get_option]  s     *3T 	= r(   c                      | 	 	 dfd	}|S )a=  
        Wraps `set_option` method for a provider config tab to consider its
        actual section nested inside the `provider_configuration` key of this
        plugin options.

        This wrapper method allows configuration tabs to not be aware about
        their presence behind the completion plugin.
        c                 p    |t        |t              r	ddg|}ndd|f}j                  ||||      S )Nr   r  )recursive_notification)r   r   set_conf)rO   r   r   r  r  rq   r   s        r&   r  z1CompletionPlugin.wrap_set_option.<locals>.wrapper~  s[    fe,6( '%'F 7($&F??w'= # ? ?r(   )NFr)   r  s    ` @r&   r   z CompletionPlugin.wrap_set_options  s     15+0	? r(   c                     | dfd	}|S )a@  
        Wraps `remove_option` method for a provider config tab to consider its
        actual section nested inside the `provider_configuration` key of this
        plugin options.

        This wrapper method allows configuration tabs to not be aware about
        their presence behind the completion plugin.
        c                 l    |1t        |t              r	ddg|}ndd|f}j                  ||      S y r  )r   r   remove_conf)rO   r   r  rq   r   s      r&   r  z4CompletionPlugin.wrap_remove_option.<locals>.wrapper  sS    fe,6( '%'F 7($&F))&':: r(   rs   r)   r  s    ` @r&   r   z#CompletionPlugin.wrap_remove_option  s     	; r(   c                     fd}|S )a<  
        Wraps `create_*` methods for a provider config tab to consider its
        actual section nested inside the `provider_configuration` key of this
        plugin options.

        This wrapper method allows configuration tabs to not be aware about
        their presence behind the completion plugin.
        c                    |j                  dd       Dt        |      }t        |   t              rddg|   |<   ndd|   f|<   t        |      }t	        | j
                        } ||i |}|j                  |        |S )Nr  r   r  )rj   listr   r   getattrrP   	setParent)	rO   r#   r   arg_listr  widgetcreate_nameopt_posr   s	         r&   r  z0CompletionPlugin.wrap_create_op.<locals>.wrapper  s    zz)T*2:d7mU30(H)(g)(HW%
 1(HW)'HW% X4;;4D4*6*FT"Mr(   r)   )rO   r&  r'  r   r  s    ``` r&   r   zCompletionPlugin.wrap_create_op  s    	  r(   c                 .    |j                   fd}|S )aA  
        Wraps `apply_settings` method for a provider config tab to consider its
        actual section nested inside the `provider_configuration` key of this
        plugin options.

        This wrapper method allows configuration tabs to not be aware about
        their presence behind the completion plugin.
        c                     t        i       } |       D ])  }t        |t              r|ddg|hz  } |dd|fhz  }+ |S r  )r   r   r   )rO   wrapped_optsoptprev_methodr   s      r&   r  z5CompletionPlugin.wrap_apply_settings.<locals>.wrapper  s~    r7L"4( Lc5) &>&.&@;>&@ %A AL !0(Hc&K %L LLL  r(   )r   )rO   Tabr   r  r,  s     ` @r&   r   z$CompletionPlugin.wrap_apply_settings  s     ((		  r(   rS   rn   provider_configurationsc                    t        | j                        }| j                  }||vr|||d}|||<   ||   }t        | j                        }t        |d         }|d   }|d   }|j	                         |j	                         z
  }	|	D ]  }
||
   ||
<   ||
   ||
<    ||kD  r|j	                         |j	                         z  }|D ]  }||   ||   k7  s||   ||<   ||   ||<     |j
                  |j
                  k7  rJ|j	                         |j	                         z
  }|D ]$  }|j                  |       |j                  |       & t        |      ||fS )Nversionr  defaultsr1  r  r2  )dictCONF_DEFAULTSCONF_VERSIONr   keysmajorpopstr)rS   rn   r.  provider_defaultsprovider_conf_versionprovider_configcurrent_conf_versioncurrent_conf_valuescurrent_defaultsnew_keysnew_keypreserved_keyskeydeleted_keyss                 r&   _merge_default_configurationsz.CompletionPlugin._merge_default_configurations  s    !!7!78 ( 5 5 77 1+-O 6E#M2 2-@ %h&;&; <$_Y%?@-h7*:6 %))+.A.F.F.HH 	CG+<W+E((9'(BW%	C !#77 .2247H7M7M7OON% F#C(,=c,BB,=c,B$S)/@/E',F
 %**.B.H.HH %))+.?.D.D.FF ' 1C$((-'++C01 )*,? " 	"r(   c                     | j                  d      }| j                  |||      \  }}}|||d}|||<   | j                  d|       |S )z&Get provider configuration dictionary.r   r0  )r@   rE  r  )rO   rS   rn   r.  r;  r>  r:  new_provider_configs           r&   get_provider_configurationz+CompletionPlugin.get_provider_configuration  su     #'--$#&
 #@@}&=?				 -))

 2E. 	.0GH""r(   c                     | j                  d      }|j                  }t        D ]:  }|j                  |i       }|j                  | j
                  |<   |dz
  ||<   |||<   < || _        | j                  d|       y)z9Sort request priorities based on Provider declared order.request_prioritiesr  N)r@   DEFAULT_ORDERCOMPLETION_REQUESTSrj   SLOWr?   r>   r  )rO   rS   rn   source_prioritiesprovider_priorityrequestrJ  s          r&   update_request_prioritiesz*CompletionPlugin.update_request_priorities  s     !MM*>?$22* 	<G!2!6!6w!C19D.0AA0E}-);g&		<  1*,=>r(   c                 R   | j                         }|j                  j                  | j                         |j                  j                  | j                         |j
                  j                  | j                         |j                  j                  | j                         |j                  j                  | j                         |j                  j                  | j                         |j                  j                  |j                         |j                  j                  |j                         |j                  j                  | j                         | j                   j                  |j"                         | j$                  j                  |j&                         y)z)Connect SpyderCompletionProvider signals.N)r|   sig_provider_readyrf   provider_availablesig_stop_completionssig_response_readyreceive_responsesig_exception_occurred"sig_language_completions_availablesig_disable_providerr   sig_show_widgetshow_widgetsig_call_statusbarstatusbar_rpcsig_open_filer   python_path_updatere   main_interpreter_changed)rO   provider_instancer   s      r&   connect_provider_signalsz)CompletionPlugin.connect_provider_signals-  sH   &&(	,,44T5L5LM..66%%	',,44T5J5JK0088''	)<<DD33	5..66++	-))11!!	
 	,,44##	%''//0B0BC##++00	2$$,,66	8r(   c                    |j                   }|| j                  v ry || j                  |<   t        j                  dj	                  |             | j                  ||      }| j                  ||        || |d         }| j                  |       || j                  d| j                  |<   | j                  D ]  }| j                  |   }d||<    y )Nz"Completion plugin: Registering {0}r  )rd   r   F)COMPLETION_PROVIDER_NAMEr8   rE   rF   formatrH  rQ  rc  STOPPEDr6   r9   )rO   rS   rn   r<  rb  languageserver_statuss          r&   rH   z3CompletionPlugin._instantiate_and_register_providerG  s     99D5553;!!-09@@ 	
 99m% 	&&x? %T?8+DE 	%%&78 *ll)
}%
 ,, 	1H 00:M+0M-(	1r(   c                     | j                   D ]P  }| j                   |   }|d   | j                  k(  s|s'| j                  d|fd      }|s>|d   j                          R y)z(Start all detected completion providers.r   r   Trd   N)r6   rg  r@   start)rO   forcern   ro   provider_enableds        r&   rl   z$CompletionPlugin.start_all_providersi  sd    !^^ 	6M NN=9MX&$,,6%#'==(-8$$@ #!*-335	6r(   c                 v    | j                   |   }| j                  |d<   | j                  j                  |       y)zAIndicate that the completion provider `provider_name` is running.r   N)r6   r   rS  r   rm   s      r&   rT  z#CompletionPlugin.provider_availables  s4     }5"&,,h$$]3r(   rh  c                    d}| j                   j                  |i       }| j                  D ]D  }| j                  |   }|d   | j                  k(  s%|d   }|j	                  |      }||z  }|||<   F || j                   |<   |S )z<Start completion providers for a given programming language.Fr   rd   )r9   rj   r6   r   &start_completion_services_for_language)rO   rh  startedlanguage_providersrn   ro   r   provider_starteds           r&   rp  z7CompletionPlugin.start_completion_services_for_languagez  s    !1155hC!^^ 	EM NN=9MX&$,,6(4CCHM !++4D"=1	E *<X&r(   c                     | j                   D ]:  }| j                   |   }|d   }|d   | j                  k(  s*|j                  |       < | j                  j	                  |       y)z;Stop completion providers for a given programming language.rd   r   N)r6   r   %stop_completion_services_for_languager9   r8  )rO   rh  rn   ro   rd   s        r&   ru  z6CompletionPlugin.stop_completion_services_for_language  sd    !^^ 	IM NN=9M$Z0HX&$,,6>>xH		I
 	  *r(   rD   c                 &    | j                   |   d   S )zAGet the :class:`SpyderCompletionProvider` identified with `name`.rd   r5   )rO   rD   s     r&   get_providerzCompletionPlugin.get_provider  s    ~~d#J//r(   c                     | j                   j                  |i       j                  d| j                        }|| j                  k(  S )zReturn if provider is running.r   )clientsrj   rg  r   )rO   rD   r   s      r&   is_provider_runningz$CompletionPlugin.is_provider_running  s8    !!$+//$,,G%%r(   c                 x    g }|| j                   v r$| j                   |   }|D cg c]
  }||   s	| }}|S c c}w )z<Return the list of providers available for a given language.)r9   )rO   rh  r6   r   ps        r&    available_providers_for_languagez1CompletionPlugin.available_providers_for_language  sK    	t+++"228<O$3Jqq7IJIJ Ks   
77c                 ^    t        | j                  |            }ddh}||z
  t               k(  S )zp
        Return if fallback and snippets are the only available providers for
        a given language.
        snippetsfallback)r   r}  )rO   rh  available_providersfallback_providerss       r&   is_fallback_onlyz!CompletionPlugin.is_fallback_only  s;    
 "11(;=(*5#&88SUBBr(   r6   req_typec                 B    | j                   |   t        |fd      S )z(Sort providers for a given request type.c                     |    S rs   r)   )r|  request_orders    r&   <lambda>z=CompletionPlugin.sort_providers_for_request.<locals>.<lambda>  s    }Q/? r(   rC  )r>   sorted)rO   r6   r  r  s      @r&   sort_providers_for_requestz+CompletionPlugin.sort_providers_for_request  s#     ,,X6i%?@@r(   c                     | j                   |   }|d   | j                  k(  rJ|d   }|j                          | j                  D ]%  }| j                  |   }|j	                  |      ||<   ' yy)zStart a given provider.r   rd   N)r6   rg  rk  r9   rp  )rO   rn   ro   rb  rh  rr  s         r&   r   z(CompletionPlugin.start_provider_instance  s~    }5"dll2 -j 9##% 00 %)%9%9(%C"%LL  #=1 3r(   c                     | j                   |   }|d   | j                  k(  rM|d   j                          | j                  |d<   | j                  D ]  }| j                  |   }||v sd||<    yy)zShutdown a given provider.r   rd   FN)r6   r   r   rg  r9   )rO   rn   ro   rh  rr  s        r&   r   z+CompletionPlugin.shutdown_provider_instance  s    }5"dll2*%..0&*llM(# 00 >%)%9%9(%C" $668=&}5> 3r(   c                 P    | j                         }||d<    |j                  |i |S )NrP   )r|   create_actionrO   r#   r   r   s       r&   r  zCompletionPlugin.create_action  s2    &&(	$x&y&&777r(   c                 F    | j                         } |j                  |i |S rs   )r|   
get_actionr  s       r&   r  zCompletionPlugin.get_action  s(    &&(	#y##T4V44r(   c                 j    | j                  t        j                        }|r |j                  |i |S y rs   )rt   r   r   get_application_menurO   r#   r   r   s       r&   r  z%CompletionPlugin.get_application_menu  s8     OOG$4$45	19114B6BB r(   c                 F    | j                         } |j                  |i |S rs   )r|   get_menur  s       r&   r  zCompletionPlugin.get_menu  s(    &&(	!y!!42622r(   c                 >    | j                   j                  ||f       y rs   )rB   r  rO   r#   r   s      r&   r   z(CompletionPlugin.create_application_menu  s    ((//v?r(   c                 F    | j                         } |j                  |i |S rs   )r|   create_menur  s       r&   r  zCompletionPlugin.create_menu  s(    &&(	$y$$d5f55r(   c                 >    | j                   j                  ||f       y rs   )rC   r  r  s      r&   r   z-CompletionPlugin.add_item_to_application_menu  s    ..55tVnEr(   c                 l    | j                  t        j                        }|r |j                  |i | y y rs   )rt   r   r   r   r  s       r&   r   z2CompletionPlugin.remove_item_from_application_menu  s3    OOG$4$45	7I77HH r(   c                 H    | j                         } |j                  |i | y rs   )r|   add_item_to_menur  s       r&   r  z!CompletionPlugin.add_item_to_menu  s%    &&(	"	""D3F3r(   reqc                 @   	  j                   	 xj                   dz  c_         ||t        j                  |d         i dd j                  	<    j	                  |j                               }t        |D cg c]  } j                  |    c}      }| j                  v rK|dkD  rF j                  dkD  r%t        j                   j                  	 fd       nd j                  	   d	<   |D ](  } j                  |   }|d
   j                  |||	       * yc c}w )aS  
        Send a completion or linting request to all available providers.

        The completion request `req_type` needs to have a response.

        Parameters
        ----------
        language: str
            Name of the programming language of the file that emits the
            request.
        req_type: str
            Type of request, one of
            :class:`spyder.plugins.completion.api.CompletionRequestTypes`
        req: dict
            Request body
            {
                'filename': str,
                **kwargs: request-specific parameters
            }
        r  response_instanceF)rh  r  r  sources	timed_out   r   c                  &    j                         S rs   )receive_timeout)r;   rO   s   r&   r  z/CompletionPlugin.send_request.<locals>.<lambda>  s    $*>*>v*F r(   Tr  rd   N)r;   weakrefrefr:   r}  lowersumr?   AGGREGATE_RESPONSESrA   r	   
singleShotr6   send_request)
rO   rh  r  r  r6   r|  slow_provider_countrn   ro   r;   s
   `        @r&   r  zCompletionPlugin.send_request  s   * q ! !(S1D-E!F!
f 99(..:JK	!9"Ma4#6#6q#9"MN t///4G!4K!#!!$"2"2"FH 6:f%k2 ' 	1M NN=9M*%22(C1	1 #Ns   7Dnotification_typenotificationc                     | j                  |j                               }|D ]:  }| j                  |   }|d   | j                  k(  s%|d   j	                  |||       < y)a  
        Send a notification to all available completion providers.

        Parameters
        ----------
        language: str
            Name of the programming language of the file that emits the
            request.
        notification_type: str
            Type of request, one of
            :class:`spyder.plugins.completion.api.CompletionRequestTypes`
        notification: dict
            Request body
            {
                'filename': str,
                **kwargs: notification-specific parameters
            }
        r   rd   N)r}  r  r6   r   send_notification)rO   rh  r  r  r6   rn   ro   s          r&   r  z"CompletionPlugin.send_notification(  sd    ( 99(..:JK	& 	?M NN=9MX&$,,6j);;/?	?r(   c                     | j                   D ]9  }| j                   |   }|d   | j                  k(  s%|d   j                  ||       ; y)a  
        Send a notification to all available completion providers for all
        programming languages.

        Parameters
        ----------
        req_type: str
            Type of request, one of
            :class:`spyder.plugins.completion.api.CompletionRequestTypes`.
        req: dict
            Request body:
            {
                'filename': str,
                **kwargs: notification-specific parameters
            }
        r   rd   N)r6   r   broadcast_notification)rO   r  r  rn   ro   s        r&   r  z'CompletionPlugin.broadcast_notificationC  sN    " "^^ 	#M NN=9MX&$,,6j)@@c#	#r(   project_pathc                     | j                   D ]:  }| j                   |   }|d   | j                  k(  s%|d   j                  |||       < y)a  
        Handle project path updates on Spyder.

        Parameters
        ----------
        project_path: str
            Path to the project folder being added or removed.
        update_kind: str
            Path update kind, one of
            :class:`spyder.plugins.completion.WorkspaceUpdateKind`.
        instance: object
            Reference to :class:`spyder.plugins.projects.plugin.Projects`.
        r   rd   N)r6   r   project_path_update)rO   r  update_kindrd   rn   ro   s         r&   r  z$CompletionPlugin.project_path_updateZ  sP     "^^ 	M NN=9MX&$,,6j)== +x	r(   filenamec                     |L|I| j                   D ]9  }| j                   |   }|d   | j                  k(  s%|d   j                  ||       ; yyy)ak  
        Handle file modifications and file switching events, including when a
        new file is created.

        Parameters
        ----------
        filename: str
            Path to the file that was changed/opened/focused.
        language: str
            Name of the programming language of the file that was
            changed/opened/focused.
        Nr   rd   )r6   r   file_opened_closed_or_updated)rO   r  rh  rn   ro   s        r&   r  z.CompletionPlugin.file_opened_closed_or_updatedp  sa     H$8!% , $} = *dll:!*-KK (,, %9r(   c                     | j                   D ]:  }| j                   |   }|d   | j                  k(  s%|d   j                  |||       < y)a  
        Register file to perform completions.
        If a language client is not available for a given file, then this
        method should keep a queue, such that files can be initialized once
        a server is available.

        Parameters
        ----------
        language: str
            Programming language of the given file.
        filename: str
            Filename to register.
        codeeditor: spyder.plugins.editor.widgets.codeeditor.CodeEditor
            Codeeditor to send the client configurations.
        r   rd   N)r6   r   register_file)rO   rh  r  
codeeditorrn   ro   s         r&   r  zCompletionPlugin.register_file  sP      "^^ 	M NN=9MX&$,,6j)77h
	r(   completion_sourcer;   respc                    t         j                  dj                  ||             || j                  vryt	        | j
                        5  | j                  |   }||d   |<   | j                  |       ddd       y# 1 sw Y   yxY w)z4Process request response from a completion provider.z4Completion plugin: Request {0} Got response from {1}Nr  )rE   rF   rf  r:   r   r=   match_and_reply)rO   r  r;   r  request_responsess        r&   rW  z!CompletionPlugin.receive_response  s     	   &v/@ A	C &$//0 	) $f 5>Bi():;  (	) 	) 	)s   
)A<<Bc                    || j                   vryt        j                  dj                  |             t	        | j
                        5  | j                   |   }d|d<   | j                  |       ddd       y# 1 sw Y   yxY w)z6Collect all provider completions and reply on timeout.Nz'Completion plugin: Request {} timed outTr  )r:   rE   rF   rf  r   r=   r  )rO   r;   r  s      r&   r  z CompletionPlugin.receive_timeout  sv     &>EEfMN$//0 	) $f 5-1k*  (	) 	) 	)s   	&A88Bc                   	 || j                   vry| j                   |   		d   j                         }	d   }| j                  |      }| j                  ||      }|| j                  v r[	d   }t        	fd|D              }|s|r=| j                  |       yt        	fd|D              }|s|r| j                  |       yyyt        	fd|D              }|r| j                  |       yy)zw
        Decide how to send the responses corresponding to req_id to
        the instance that requested them.
        Nrh  r  r  c              3   ,   K   | ]  }|d    v   ywr  Nr)   .0sourcer  s     r&   	<genexpr>z3CompletionPlugin.match_and_reply.<locals>.<genexpr>  s$      ?#)  &):9)EE ?s   c              3   F   K   | ]  }d    j                  |        ywr  rj   r  s     r&   r  z3CompletionPlugin.match_and_reply.<locals>.<genexpr>  s+      #C'- $5Y#?#C#CF#K #C   !c              3   F   K   | ]  }d    j                  |        ywr  r  r  s     r&   r  z3CompletionPlugin.match_and_reply.<locals>.<genexpr>  s)      ?#)  1;??G ?r  )r:   r  r}  r  r  allskip_and_replyany)
rO   r;   rh  r  r  sorted_providersr  all_returnedany_nonemptyr  s
            @r&   r  z CompletionPlugin.match_and_reply  s   
 & MM&1$Z0668$Z0"CC::+ t///)+6I ?-=? ?L''/  # #C1A#C  C<''/ $0    ?-=? ?L##F+ r(   c                    | j                   |   }|d   }t         |d                }d}|| j                  v r^t        | j                   j	                         D cg c]%  \  }}|d   |k(  rt         |d                |k(  r|' c}}xs dg      }||k(  }t
        j                  dj                  |             | j                   |= |r| j                  |       yyc c}}w )z
        Skip intermediate responses coming from the same CodeEditor
        instance for some types of requests, and send the last one to
        it.
        r  r  Tr  z%Completion plugin: Request {} removedN)	r:   idSKIP_INTERMEDIATE_REQUESTSmaxitemsrE   rF   rf  gather_and_reply)	rO   r;   r  r  r  do_sendrC  r   
max_req_ids	            r&   r  zCompletionPlugin.skip_and_reply  s     !MM&1$Z0E01DEGH t666&*mm&9&9&; Kd$0101348II  K  4	J
 +G<CCFKLMM&! !!"34 Ks   *C
r  c                 ,   |d   }|d   } |d          }t         j                  dj                  |             |t        j                  k(  r| j                  |      }n| j                  ||      }	 |r|j                  ||       yy# t        $ r Y yw xY w)z
        Gather request responses from all providers and send them to the
        CodeEditor instance that requested them.
        r  r  r  zGather responses for {0}N)	rE   rF   rf  r   DOCUMENT_COMPLETIONgather_completionsgather_responseshandle_responseRuntimeError)rO   r  r  req_id_responsesr  	responsess         r&   r  z!CompletionPlugin.gather_and_reply  s    
 %Z0,Y7B-.ABD/66x@A-AAA//0@AI--h8HII	 !11(IF ! 	 	s   1B 	BBr  c                 (  	 | j                   t        j                     	t        t	        	j                               	fd      	|D ci c]  }|d }}g }t               }t        	      D ]u  \  }}||vr||   j                  dg       D ]S  }|d   j                         }||v r|j                  |       ||d   f|d<   |j                  |       ||xx   dz  cc<   U w t        j                  dj                  |             d|i}|S c c}w )	z+Gather completion responses from providers.c                     |    S rs   r)   )r|  
prioritiess    r&   r  z5CompletionPlugin.gather_completions.<locals>.<lambda>  s    *Q- r(   r  r   paramslabelsortTextr  zResponses statistics: {0})r>   r   r  r  r!  r6  r   	enumeraterj   r   addr  rE   rF   rf  )
rO   r  r  merge_statsr  
dedupe_setpriorityresponse
dedupe_keyr  s
            @r&   r  z#CompletionPlugin.gather_completions  s/   ))"668
D!23 79
 0@@Vvqy@@	U
 )* 5 	)Hf--,V4882F )%g.446
+z*(0(:2F'G$  *F#q(#)	) 	077DEy)	% As   

Dr  c                 x    d}| j                   |   D ]#  }||v s||   j                  dd      }|s  d|iS  d|iS )z7Gather responses other than completions from providers.Nr  )r>   rj   )rO   r  r  r  r  s        r&   r  z!CompletionPlugin.gather_responses1  s^    **84 	F"$V,004@(##	
 (##r(   rs   )F)T)additionN)wr   r   r   __doc__NAMECONF_SECTIONr   ru   r{   REQUIRESr   r   r   OPTIONAL	CONF_FILErN   rM   r   CONTAINER_CLASSr   r9  intr3  rV  rS  objectr   re   rY  r_  r   r   rU  r   rg  r   r  r  r  r"   staticmethodr[   r^   ra   rp   r   ry   r   r   r   r   r   r   r   r   r   r   r   boolr   r   r   r   r   r   rK   r   r   propertyr}   r
   rg   rL   r   r   r   r   r   r   r   rE  rH  rQ  rc  rH   rl   rT  rp  ru  rw  rz  r}  r  r  r   r   r  r  r  r  r   r  r   r   r  r  r  r  r  r  r  rW  r  r  r  r  r  r  __classcell__)rW   s   @r&   r,   r,   8   s    D L##W%<%<=H  '";";W=N=NOHI   *O  S$/   $FF3	 %h *0c):& 3KM C-N "#;	 GG 	22"
 	22@?F +c + +A A
/#  3 346 56  7 78	* 9	*  1 12A 3A  0 01	D 2	D  9 9:) ;)
 w2238 48 w667* 8* w0017 27 w//0. 1.. w889) :)5	4 	D G$uUCZ7H2I G>>?$E29( 6 6 
VB B0&)P*,2,60 /"0H /"58/"?C/" /"b#3K #25#:>#.?2J ?14?84 14 1D6 
#Y4 4 4s t +c +0 0)A 0& & &
 c C C CA!#YA25A:>s)AS 	> 	>8
5C3@6FI
4
11S 11C 11d 11f??47?GK?6#s # #. BL%) , 
#s^,c ,S , ,(c S 0 
#sD)%()25)=A) ) 
#Y)c ) )',c ',R5S 58$ .4 6$ $ $r(   r,   )1r  r    r   loggingrh   typingr   r   r  packaging.versionr   pkg_resourcesr   qtpy.QtCorer   r   r	   r
   r   spyder.config.managerr   spyder.api.pluginsr   r   )spyder.api.plugin_registration.decoratorsr   r   spyder.config.baser   r   spyder.config.userr   spyder.plugins.completion.apir   r   r   "spyder.plugins.completion.confpager   #spyder.plugins.completion.containerr   	getLoggerr   rE   dirisupperr"  rL  r*   r,   )cs   0r&   <module>r     s       	   $ + B B ' 6- 6 (B B D C 
		8	$
 !$$: ;Lqyy{ 5q9 L A$~ A$Ls    C