
    <Bh5Z                       S r SSKJr  SSKrSSKrSSKJr  SSKJrJ	r	  SSK
JrJr  SSKrSSKJr  SS	KJr  SS
KJr  SSKJr  SSKJrJrJr  SSKJrJrJrJrJrJ r J!r!  SSK"J#r#  SSK$J%r%J&r&  SSK'J(r(  \(       aP  SSK)J*r*  SSK
J+r+  SSK,J-r-  SSK.J/r/  SSK0J1r1  SSK2J3r3  SSK4J5r5  SSK6J7r7J8r8J9r9J:r:J;r;J<r<J=r=J>r>J?r?J@r@JArAJBrBJCrCJDrDJErEJFrFJGrG  \R                  " \I5      rJ " S S\R                  5      rL\R                  SS j5       rNg)a0  
This module contains a subclass implementation of pluggy's
`PluginManager <https://pluggy.readthedocs.io/en/stable/api_reference.html#pluggy.PluginManager>`_.

Additionally, it contains a function we use to construct the ``PluginManager`` object and
register all plugins during conda's startup process.
    )annotationsN)distributions)	getmoduleisclass)TYPE_CHECKINGoverload   )dals) DEFAULT_CONSOLE_REPORTER_BACKEND)context)
deprecated)CondaValueError EnvironmentSpecPluginNotDetectedPluginError   )environment_specifierspost_solvesprefix_data_loadersreporter_backendssolverssubcommandsvirtual_packagesPluginConfig)
CondaSpecs	spec_name)health_checks)Iterable)Literal)AuthBase)Action)Solver)	MatchSpec)PackageRecord)CondaAuthHandlerCondaEnvironmentSpecifierCondaHealthCheckCondaPostCommandCondaPostSolveCondaPostTransactionActionCondaPreCommandCondaPrefixDataLoaderCondaPrefixDataLoaderCallableCondaPreSolveCondaPreTransactionActionCondaReporterBackendCondaRequestHeaderCondaSettingCondaSolverCondaSubcommandCondaVirtualPackagec                    ^  \ rS rSrSrSrS7S8U 4S jjjrS9S jrS7S:U 4S jjjrS;S jr	S7S<S jjr
\    S=S	 j5       r\    S>S
 j5       r\S?S j5       r\    S@S j5       r\    SAS j5       r\    SBS j5       r\    SCS j5       r\SDS j5       r\    SES j5       r\      SFS j5       r\        SGS j5       r\SHS j5       r\    SIS j5       r\    SJS j5       r\    SKS j5       r\    SLS j5       r\    SMS j5       rS rSNS jrS7SOS jjrSPS jrSQS jrSRS jrSRS  jrSSS! jrSTS" jr\" S#S$S%S&9SUS' j5       rSVS( jrSWS) jrSXS* jrSYS+ jrSZS, jrS[S- jrS\S. jr      S]S/ jr        S^S0 jrSSS1 jr S_S2 jr!S`S3 jr"       Sa               SbS4 jjr#       Sa               SbS5 jjr$S6r%U =r&$ )cCondaPluginManagerL   z_
The conda plugin manager to implement behavior additional to pluggy's default plugin manager.
Nc                  > Uc  [         n[        TU ]  " U/UQ70 UD6  [        R                  " U R
                  5      U l        [        R                  " U R                  5      U l        [        R                  " U R                  5      U l
        g N)r   super__init__	functoolscacheget_solver_backendget_cached_solver_backendget_session_headersget_cached_session_headersget_request_headersget_cached_request_headers)selfproject_nameargskwargs	__class__s       5lib/python3.13/site-packages/conda/plugins/manager.pyr<   CondaPluginManager.__init__U   sl    $L777 *39P9P)Q&*3//$:R:R*S'*3//$:R:R*S'    c                   Sn[        U5      =n(       a'  UR                  (       a  UR                  R                  nX1L a  U$ [        U5      (       a  U SUR                   3$ U SUR
                  R                   S[        U5       S3$ )Nz<unknown_module>.[])r   __spec__namer   __qualname__rI   id)rE   pluginprefixmodules       rJ   get_canonical_name%CondaPluginManager.get_canonical_name`   s    #''F'V____))F M V__XQv22344 XQv//<<=Qr&zl!LLrL   c                   >  [         TU ]  XS9$ ! [         a     g[         a0  n[	        SU=(       d    U R                  U5       SU S35      UeSnAff = f)z
Call :meth:`pluggy.PluginManager.register` and return the result or
ignore errors raised, except ``ValueError``, which means the plugin
had already been registered.
rR   Nz"Error while loading conda plugin:  ())r;   register
ValueError	Exceptionr   rX   )rE   rU   rR   errrI   s       rJ   r^   CondaPluginManager.registerr   sq    
	 7#F#66 	 	4:4226:;2cU!E 	s    
A	A+AAc                V    SnU H   nU R                  U5      (       d  M  US-  nM"     U$ )z
Load the provided list of plugins and fail gracefully on error.
The provided list of plugins can either be classes or modules with
:attr:`~conda.plugins.hookimpl`.
r   r   )r^   )rE   pluginscountrU   s       rJ   load_pluginsCondaPluginManager.load_plugins   s2     F}}V$$
  rL   c           
        Sn[        5        Hi  nUR                   HV  nUR                  U:w  d  Ub  UR                  U:w  a  M(   UR	                  5       nU R                  U5      (       d  MQ  US-  nMX     Mk     U$ ! [
         aG  n[        R                  SUR                   SU S3[        R                  (       a  UOSS9   SnAM  SnAff = f)zLoad modules from querying the specified setuptools ``group``.

:param str group: Entry point group to load plugins.
:param str name: If given, loads only plugins with the given ``name``.
:rtype: int
:return: The number of plugins loaded by this call.
r   Nz'Error while loading conda entry point: r\   r]   )exc_infor   )r   entry_pointsgrouprR   loadr`   logwarningr   infor^   )rE   rk   rR   re   distentry_pointrU   ra   s           rJ   load_entrypoints#CondaPluginManager.load_entrypoints   s     !OD#00$$-$)9)9T)A(--/F ==((QJE/  1 $2  ! 
 KKA+BRBRASSUVYUZZ[\(/$    
s   A<<
C<CCc                    g r:    rE   rR   s     rJ   get_hook_results#CondaPluginManager.get_hook_results        !$rL   c                    g r:   ru   rv   s     rJ   rw   rx      s     %(rL   c                    g r:   ru   rv   s     rJ   rw   rx      s    ORrL   c                    g r:   ru   rv   s     rJ   rw   rx      ry   rL   c                    g r:   ru   rv   s     rJ   rw   rx           "%rL   c                    g r:   ru   rv   s     rJ   rw   rx      r~   rL   c                    g r:   ru   rv   s     rJ   rw   rx      r~   rL   c                    g r:   ru   rv   s     rJ   rw   rx      s    TWrL   c                    g r:   ru   rv   s     rJ   rw   rx      s      #rL   c                   g r:   ru   )rE   rR   hosts      rJ   rw   rx           $'rL   c                   g r:   ru   )rE   rR   r   paths       rJ   rw   rx      r   rL   c                    g r:   ru   rv   s     rJ   rw   rx      s    QTrL   c                    g r:   ru   rv   s     rJ   rw   rx      s     &)rL   c                    g r:   ru   rv   s     rJ   rw   rx           +.rL   c                    g r:   ru   rv   s     rJ   rw   rx      s     ,/rL   c                    g r:   ru   rv   s     rJ   rw   rx      s     '*rL   c                    g r:   ru   rv   s     rJ   rw   rx      r   rL   c                *   U R                    SU 3n[        U R                  US5      nUc  [        SU S35      eU" S0 UD6VVs/ s H  oU  H  ofPM     M     nnnUVs/ s H&  n[	        UR
                  [        5      (       a  M$  UPM(     n	nU	(       a@  [        [        SSR                  U	Vs/ s H  n[        U5      PM     sn5       S35      5      e[        US S	9n[        5       n
UVs/ s H6  oR
                  U
;   d"  U
R                  UR
                  5      (       d  M4  UPM8     nnU(       aF  [        [        S
U SSR                  UVs/ s H  n[        U5      PM     sn5       SU S35      5      eU$ s  snnf s  snf s  snf s  snf s  snf )zc
Return results of the plugin hooks with the given name and
raise an error if there is a conflict.
_NzCould not find requested `z	` pluginszF
                    Invalid plugin names found:

                    , z\

                    Please report this issue to the plugin author(s).
                    c                    U R                   $ r:   r[   )rU   s    rJ   <lambda>5CondaPluginManager.get_hook_results.<locals>.<lambda>  s    V[[rL   )keyz"
                    Conflicting `z&` plugins found:

                    zE

                    Multiple conda plugins are registered via the `zy` hook.
                    Please make sure that you don't have any incompatible plugins installed.
                    ru   )rF   getattrhookr   
isinstancerR   strr
   joinsortedsetadd)rE   rR   rH   specnamer   itemsitemrd   rU   invalidseen	conflictsconflicts                rJ   rw   rx     s   
 ''($0tyy(D1< :4&	JKK%)^F^F^E44^F )0Tfz&++s7S6T YY'B'F'BCD E
 
 &@A u!(
!(vKK4,?488FKKCXF 	 
 ""& (YYiHi(HiHIJ KDDL: N	  I G U  C
  Is*   E;#FF.F-3F$FFc                    U R                  S5      Vs0 s H  nUR                  R                  5       U_M      sn$ s  snf )z2Return a mapping from solver name to solver class.r   rw   rR   lower)rE   solver_plugins     rJ   get_solversCondaPluginManager.get_solvers3  sH     "&!6!6y!A
!A $$&5!A
 	
 
   %;c                    Uc  [         R                  nUR                  5       nU R                  5       nUR	                  US5      nUc   [        SU SSR                  U5       35      eUR                  $ )a2  
Get the solver backend with the given name (or fall back to the
name provided in the context).

See ``context.solver`` for more details.

Please use the cached version of this method called
:meth:`get_cached_solver_backend` for high-throughput code paths
which is set up as a instance-specific LRU cache.
Nz.You have chosen a non-default solver backend (z,) but it was not recognized. Choose one of: r   )r   solverr   r   getr   r   backend)rE   rR   solvers_mappingr   s       rJ   r?   %CondaPluginManager.get_solver_backend:  s     <>>Dzz|**, (++D$7 !@ G=99_-.0  $$$rL   c                   ^ U R                  S5      n[        U4S jU5       5      n[        U5      S:  a  US   R                  $ g)z2
Get the auth handler with the given name or None
auth_handlersc              3     >#    U  HB  oR                   R                  5       TR                  5       R                  5       :X  d  M>  Uv   MD     g 7fr:   )rR   r   strip).0r   rR   s     rJ   	<genexpr>6CondaPluginManager.get_auth_handler.<locals>.<genexpr>]  s5      
*Tiioo.?4::<CUCUCW.WDD]s   =A	Ar   N)rw   tuplelenhandler)rE   rR   r   matchess    `  rJ   get_auth_handler#CondaPluginManager.get_auth_handlerX  sM     --o> 
*
 
 w<!1:%%%rL   c                    U R                  S5      Vs0 s H  nUR                  R                  5       U_M      sn$ s  snf )z
Return a mapping of plugin setting name to CondaSetting objects.

This method intentionally overwrites any duplicates that may be present
settingsr   )rE   config_params     rJ   get_settingsCondaPluginManager.get_settingse  sH     !% 5 5j A
 A ##%|3 A
 	
 
r   c                x    U R                  S5       H%  nXR                  ;   d  M  UR                  U5        M'     g)z
Invokes ``CondaPreCommand.action`` functions registered with ``conda_pre_commands``.

:param command: name of the command that is currently being invoked
pre_commandsNrw   run_foractionrE   commandr   s      rJ   invoke_pre_commands&CondaPluginManager.invoke_pre_commandsp  s/     )).9D,,&G$ :rL   c                x    U R                  S5       H%  nXR                  ;   d  M  UR                  U5        M'     g)z
Invokes ``CondaPostCommand.action`` functions registered with ``conda_post_commands``.

:param command: name of the command that is currently being invoked
post_commandsNr   r   s      rJ   invoke_post_commands'CondaPluginManager.invoke_post_commandsz  s/     ))/:D,,&G$ ;rL   c                    U R                  5        HF  u  pUR                  S5      (       a  M  U R                  U5      (       a  M5  U R                  U5        MH     g)zI
Disables all currently registered plugins except built-in conda plugins
zconda.plugins.N)list_name_plugin
startswith
is_blockedset_blocked)rE   rR   rU   s      rJ   disable_external_plugins+CondaPluginManager.disable_external_plugins  sE     !113LD??#344T__T=R=R  & 4rL   c                    U R                  S5      Vs0 s H  nUR                  R                  5       U_M      sn$ s  snf )Nr   r   )rE   
subcommands     rJ   get_subcommands"CondaPluginManager.get_subcommands  sF     #33MB
B
 OO!!#Z/B
 	
 
r   z25.3z25.9z@Use `conda.plugins.manager.get_virtual_package_records` instead.)addendumc                6    [        U R                  S5      5      $ )Nr   r   rw   rE   s    rJ   get_virtual_packages'CondaPluginManager.get_virtual_packages  s     T**+=>??rL   c                6    [        U R                  S5      5      $ )Nr   r   r   s    rJ   get_reporter_backends(CondaPluginManager.get_reporter_backends  s    T**+>?@@rL   c                    U R                  5       Vs0 s H  nUR                  U_M     nnUR                  US5      nUc5  [        R	                  SU S[
         S35        UR                  [
        5      $ U$ s  snf )z
Attempts to find a reporter backend while providing a fallback option if it is
not found.

This method must return a valid ``CondaReporterBackend`` object or else it will
raise an exception.
Nz"Unable to find reporter backend: "z"; falling back to using "")r   rR   r   rm   rn   r   )rE   rR   reporter_backendreporter_backends_maps       rJ   get_reporter_backend'CondaPluginManager.get_reporter_backend  s     %)$>$>$@!
$@  !!#33$@ 	 !
 144T4@#KK4TF ;**J)K1N ),,-MNN##!
s   A7c                B    [        S U R                  S5      5       5      $ )Nc              3  B   #    U  H  nUR                  5       v   M     g 7fr:   )to_virtual_package)r   r   s     rJ   r   ACondaPluginManager.get_virtual_package_records.<locals>.<genexpr>  s#      
A ##%%As   r   r   r   s    rJ   get_virtual_package_records.CondaPluginManager.get_virtual_package_records  s(     
--.@A
 
 	
rL   c                v    U R                  SUS9Vs0 s H  nUR                  UR                  _M     sn$ s  snf )Nsession_headers)r   rw   rR   value)rE   r   r   s      rJ   rA   &CondaPluginManager.get_session_headers  sG     --.?d-K
K IItzz!K
 	
 
   !6c                v    U R                  SXS9Vs0 s H  nUR                  UR                  _M     sn$ s  snf )Nrequest_headers)r   r   r   )rE   r   r   r   s       rJ   rC   &CondaPluginManager.get_request_headers  sG     --.?d-V
V IItzz!V
 	
 
r   c              #  X   #    U R                  S5       H  nUR                  v   M     g 7f)Nr   )rw   loader)rE   r   s     rJ   get_prefix_data_loaders*CondaPluginManager.get_prefix_data_loaders  s&     ))*?@D++ As   (*c           	         U R                  S5       H  n UR                  X5        M     g ! [         a1  n[        R	                  SUR
                   SU S35         S nAMP  S nAff = f)Nr   zError running health check: r\   r]   )rw   r   r`   rm   rn   rR   )rE   rV   verboser   ra   s        rJ   invoke_health_checks'CondaPluginManager.invoke_health_checks  s]    ))/:DF, ;  :499+RuANOs   ,
A'&A""A'c                V    U R                  S5       H  nUR                  X5        M     g)z
Invokes ``CondaPreSolve.action`` functions registered with ``conda_pre_solves``.

:param specs_to_add:
:param specs_to_remove:

pre_solvesNrw   r   )rE   specs_to_addspecs_to_remover   s       rJ   invoke_pre_solves$CondaPluginManager.invoke_pre_solves  s%     )),7DKK6 8rL   c                X    U R                  S5       H  nUR                  XU5        M     g)z
Invokes ``CondaPostSolve.action`` functions registered with ``conda_post_solves``.

:param repodata_fn:
:param unlink_precs:
:param link_precs:
r   Nr  )rE   repodata_fnunlink_precs
link_precsr   s        rJ   invoke_post_solves%CondaPluginManager.invoke_post_solves  s'     ))-8DKK:> 9rL   c                    U R                  5       R                  5        H0  u  p[        R                  " XR                  UR
                  5        M2     g)zw
Iterates through all registered settings and adds them to the
:class:`conda.common.configuration.PluginConfig` class.
N)r   r   r   add_plugin_setting	parameteraliases)rE   rR   settings      rJ   load_settings CondaPluginManager.load_settings  s<    
 "..0668MD++D2C2CW__U 9rL   c                    [        U5      $ )z
Retrieve the configuration for the plugin.
Returns:
    PluginConfig: The configuration object for the plugin, initialized with raw data from the context.
r   )rE   datas     rJ   
get_configCondaPluginManager.get_config  s     D!!rL   c                   U R                  S5      n/ nU H  n[        R                  SUR                  5        UR	                  U5      R                  5       (       a4  [        R                  SUUR                  5        UR                  U5        M{  [        R                  SUUR                  5        M     [        U5      S:X  a  US   $ [        U5      S:  aC  [        [        SU SS	R                  UVs/ s H  oDR                  PM     sn5       S
35      5      e[        XVs/ s H  oDR                  PM     snS9es  snf s  snf )z
Returns the environment_spec plugin that can handle the provided file.

Raises PluginError if more than one environment_spec plugin is found to be able to handle the file.
Raises EnvironmentSpecPluginNotDetected if no plugins were found.
r   z!EnvironmentSpec hook: checking %sz"EnvironmentSpec hook: %s can be %sz1EnvironmentSpec hook: %s can NOT be handled by %sr   r   zR
                    Too many plugins found that can handle the environment file 'z':

                    r   zn

                    Please make sure that you don't have any overlapping plugins installed.
                )rR   plugin_names)rw   rm   debugrR   environment_spec
can_handleappendr   r   r
   r   r   )rE   filenamehooksfoundr   s        rJ   get_environment_specifiers-CondaPluginManager.get_environment_specifiers  s1    %%&>?DII9499E$$X.99;;		8II
 T"		GII   u:?8OZ!^RRZQ[ \YYe<ed		e<=> ?
 
 /(Eutu(E
 	
  = )Fs   5D>$E
c                    / nU R                  S5       H)  n	UR                  U	R                  UUUUUUU5      5        M+     U$ )a  Get the plugin-defined pre-transaction actions.

:param transaction_context: Mapping between target prefixes and PrefixActions
    instances
:param target_prefix: Target prefix for the action
:param unlink_precs: Package records to be unlinked
:param link_precs: Package records to link
:param remove_specs: Specs to be removed
:param update_specs: Specs to be updated
:param neutered_specs: Specs to be neutered
:return: The plugin-defined pre-transaction actions
pre_transaction_actionsrw   r  r   
rE   transaction_contexttarget_prefixr  r  remove_specsupdate_specsneutered_specsactionsr   s
             rJ   get_pre_transaction_actions.CondaPluginManager.get_pre_transaction_actions-  sT    , ))*CDDNN'!   "
 E rL   c                    / nU R                  S5       H)  n	UR                  U	R                  UUUUUUU5      5        M+     U$ )a  Get the plugin-defined post-transaction actions.

:param transaction_context: Mapping between target prefixes and PrefixActions
    instances
:param target_prefix: Target prefix for the action
:param unlink_precs: Package records to be unlinked
:param link_precs: Package records to link
:param remove_specs: Specs to be removed
:param update_specs: Specs to be updated
:param neutered_specs: Specs to be neutered
:return: The plugin-defined post-transaction actions
post_transaction_actionsr'  r(  s
             rJ   get_post_transaction_actions/CondaPluginManager.get_post_transaction_actionsR  sT    , ))*DEDNN'!   "
 F rL   )rD   rB   r@   r:   )rF   
str | NonereturnNone)rU   objectr6  r   )rR   r5  r6  r5  )r6  int)rk   r   rR   r5  r6  r9  )rR   zLiteral['subcommands']r6  zlist[CondaSubcommand])rR   zLiteral['virtual_packages']r6  zlist[CondaVirtualPackage])rR   zLiteral['solvers']r6  zlist[CondaSolver])rR   zLiteral['pre_commands']r6  zlist[CondaPreCommand])rR   zLiteral['post_commands']r6  zlist[CondaPostCommand])rR   zLiteral['auth_handlers']r6  zlist[CondaAuthHandler])rR   zLiteral['health_checks']r6  zlist[CondaHealthCheck])rR   zLiteral['pre_solves']r6  zlist[CondaPreSolve])rR   zLiteral['post_solves']r6  zlist[CondaPostSolve])rR   zLiteral['session_headers']r   r   r6  list[CondaRequestHeader])rR   zLiteral['request_headers']r   r   r   r   r6  r:  )rR   zLiteral['settings']r6  zlist[CondaSetting])rR   zLiteral['reporter_backends']r6  zlist[CondaReporterBackend])rR   z"Literal['pre_transaction_actions']r6  zlist[CondaPreTransactionAction])rR   z#Literal['post_transaction_actions']r6  z list[CondaPostTransactionAction])rR   zLiteral['prefix_data_loaders']r6  zlist[CondaPrefixDataLoader])rR   z!Literal['environment_specifiers']r6  zlist[CondaEnvironmentSpecifier])r6  zdict[str, CondaSolver])rR   r5  r6  ztype[Solver])rR   r   r6  ztype[AuthBase] | None)r6  zdict[str, CondaSetting])r   r   r6  r7  )r6  r7  )r6  zdict[str, CondaSubcommand])r6  ztuple[CondaVirtualPackage, ...])r6  z tuple[CondaReporterBackend, ...])rR   r   r6  r0   )r6  tuple[PackageRecord, ...])r   r   r6  dict[str, str])r   r   r   r   r6  r<  )r6  z'Iterable[CondaPrefixDataLoaderCallable])rV   r   r   boolr6  r7  )r  frozenset[MatchSpec]r  r>  r6  r7  )r
  r   r  r;  r  r;  r6  r7  )r6  r   )r   r   r6  r&   )NNNNNNN)r)  zdict[str, str] | Noner*  r5  r  Iterable[PackageRecord] | Noner  r?  r+  Iterable[MatchSpec] | Noner,  r@  r-  r@  r6  zlist[Action])'__name__
__module__rS   __firstlineno____doc__r@   r<   rX   r^   rf   rr   r   rw   r   r?   r   r   r   r   r   r   r   r   r   r   r   rA   rC   r   r   r  r  r  r  r#  r/  r3  __static_attributes____classcell__)rI   s   @rJ   r7   r7   L   s    !%	T 	TM$ $
"H $*$	$ $ (/(	"( ( R R$+$	$ $ %,%	% % %,%	% % %,%	% % W W#*#	# # '.'9<'	!' ' '.'9<'DG'	!' ' T T)0)	#) ) .6.	(. . /7/	)/ / *2*	$* * .5.	(. ..`
%<	
%%'
 S
@
@A$,


7*7 .7 
	7?? 0? .	?
 
? V",
` 6:$(7;59373759#2# "# 5	#
 3# 1# 1# 3# 
#N 6:$(7;59373759#2# "# 5	#
 3# 1# 1# 3# 
# #rL   r7   c                 d   [        5       n U R                  [        5        U R                  " [        /[
        R                  Q[        R                  Q[        P[        R                  Q[        R                  Q[        R                  Q[        R                  Q76   U R                  [        5        U $ )z
Get a cached version of the :class:`~conda.plugins.manager.CondaPluginManager` instance,
with the built-in and entrypoints provided by the plugins loaded.
)r7   add_hookspecsr   rf   r   r   rd   r   r   r   r   r   r   rr   r   )plugin_managers    rJ   get_plugin_managerrJ  x  s     ()N  ,			!	!	 
			 			
 
			 
	"	"	 
	$	$	 
 	'	'	 ##I.rL   )r6  r7   )OrD  
__future__r   r=   loggingimportlib.metadatar   inspectr   r   typingr   r   pluggy
auxlib.ishr
   base.constantsr   base.contextr   deprecationsr   
exceptionsr   r   r    r   r   r   r   r   r   r   configr   hookspecr   r   subcommands.doctorr   collections.abcr   r   requests.authr    core.path_actionsr!   
core.solver"   models.match_specr#   models.recordsr$   typesr%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   	getLoggerrA  rm   PluginManagerr7   r>   rJ  ru   rL   rJ   <module>rc     s    #   , & *   = " % 
   ! + -(&*#-.    ( !i-- iX  rL   