
    z	i8                         S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJ	r	J
r
JrJrJrJr  SSKJrJr  SSKJr   " S S5      r " S	 S
\R*                  5      r " S S\5      r " S S\5      rg)z#Lazy testers for optional features.    N)UnionIterableDictOptionalCallableType)MissingOptionalLibraryErrorOptionalDependencyImportWarning   )wrap_methodc                   (    \ rS rSrSrSrS rS rSrg)_RequireNow   zHelper callable that accepts all function signatures and simply calls
:meth:`.LazyDependencyManager.require_now`.  This helpful when used with :func:`.wrap_method`,
as the callable needs to be compatible with all signatures and be picklable._tester_featurec                     Xl         X l        g Nr   )selftesterfeatures      R/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/utils/lazy_tester.py__init___RequireNow.__init__$   s        c                 N    U R                   R                  U R                  5        g r   )r   require_nowr   )r   _args_kwargss      r   __call___RequireNow.__call__(   s      /r   )r   r   N)	__name__
__module____qualname____firstlineno____doc__	__slots__r   r    __static_attributes__ r   r   r   r      s    T (I 0r   r   c                   x   \ rS rSrSrSrSSSSS.S jr\R                  S\	4S j5       r
S	 r\R                  S
\S\4S j5       r\R                  S
\S\\/\4   4S j5       rS r\R                  S\S\4S j5       r\R                  S\S\\/\4   4S j5       rS rS\4S jr\R*                  S 5       rSrg)LazyDependencyManager,   a  A mananger for some optional features that are expensive to import, or to verify the
existence of.

These objects can be used as Booleans, such as ``if x``, and will evaluate ``True`` if the
dependency they test for is available, and ``False`` if not.  The presence of the dependency
will only be tested when the Boolean is evaluated, so it can be used as a runtime test in
functions and methods without requiring an import-time test.

These objects also encapsulate the error handling if their dependency is not present, so you can
do things such as::

    from qiskit.utils import LazyImportManager
    HAS_MATPLOTLIB = LazyImportManager("matplotlib")

    @HAS_MATPLOTLIB.require_in_call
    def my_visualisation():
        ...

    def my_other_visualisation():
        # ... some setup ...
        HAS_MATPLOTLIB.require_now("my_other_visualisation")
        ...

    def my_third_visualisation():
        if HAS_MATPLOTLIB:
            from matplotlib import pyplot
        else:
            ...

In all of these cases, ``matplotlib`` is not imported until the functions are entered.  In the
case of the decorator, ``matplotlib`` is tested for import when the function is called for
the first time.  In the second and third cases, the loader attempts to import ``matplotlib``
when the :meth:`require_now` method is called, or when the Boolean context is evaluated.  For
the ``require`` methods, an error is raised if the library is not available.

This is the base class, which provides the Boolean context checking and error management.  The
concrete classes :class:`LazyImportTester` and :class:`LazySubprocessTester` provide convenient
entry points for testing that certain symbols are importable from modules, or certain
command-line tools are available, respectively.
_bool	_callback_name_install_msgNnamecallbackinstallmsgc                B    SU l         X l        Xl        X0l        X@l        g)a  
Args:
    name: the name of this optional dependency.
    callback: a callback that is called immediately after the availability of the library is
        tested with the result.  This will only be called once.
    install: how to install this optional dependency.  Passed to
        :class:`.MissingOptionalLibraryError` as the ``pip_install`` parameter.
    msg: an extra message to include in the error raised if this is required.
Nr-   )r   r4   r5   r6   r7   s        r   r   LazyDependencyManager.__init__X   s     
!
	r   returnc                     g)a  Subclasses of :class:`LazyDependencyManager` should override this method to implement the
actual test of availability.  This method should return a Boolean, where ``True`` indicates
that the dependency was available.  This method will only ever be called once.

:meta public:
Fr)   r   s    r   _is_available#LazyDependencyManager._is_availableh   s     r   c                     U R                   c=  U R                  5       U l         U R                  b  U R                  U R                   5        U R                   $ r   )r.   r=   r/   r<   s    r   __bool__LazyDependencyManager.__bool__r   s@    ::++-DJ~~)tzz*zzr   feature_or_callablec                     g r   r)   r   rB   s     r   require_in_call%LazyDependencyManager.require_in_cally   s    JMr   c                     g r   r)   rD   s     r   rE   rF   |   s    [^r   c                    ^ ^^ [        U[        5      (       a  UmUU 4S jnU$ Um[        TSS5      =(       d    [        TSS5      =(       d    [        T5      m[        R                  " T5      UUU 4S j5       nU$ )ay  Create a decorator for callables that requires that the dependency is available when the
decorated function or method is called.

Args:
    feature_or_callable (str or Callable): the name of the feature that requires these
        dependencies.  If this function is called directly as a decorator (for example
        ``@HAS_X.require_in_call`` as opposed to
        ``@HAS_X.require_in_call("my feature")``), then the feature name will be taken to be
        the function name, or class and method name as appropriate.

Returns:
    Callable: a decorator that will make its argument require this dependency before it is
    called.
c                 L   >^  [         R                  " T 5      UU U4S j5       nU$ )Nc                  6   > TR                  T5        T" U 0 UD6$ r   r   argskwargsr   functionr   s     r   outELazyDependencyManager.require_in_call.<locals>.decorator.<locals>.out   s!    $$W-#T4V44r   )	functoolswraps)rO   rP   r   r   s   ` r   	decorator8LazyDependencyManager.require_in_call.<locals>.decorator   s%    *5 +5 
r   r$   Nr"   c                  6   > TR                  T5        T" U 0 UD6$ r   rK   rL   s     r   rP   2LazyDependencyManager.require_in_call.<locals>.out   s!    W%T,V,,r   )
isinstancestrgetattrrR   rS   )r   rB   rT   rP   r   rO   s   `   @@r   rE   rF      s|     )3//)G &Hnd3 xT28} 	 
	"	- 
#	- 
r   feature_or_classc                     g r   r)   r   r[   s     r   require_in_instance)LazyDependencyManager.require_in_instance   s    CFr   c                     g r   r)   r]   s     r   r^   r_      s    TWr   c                    ^ ^ [        U[        5      (       a  UmUU 4S jnU$ Un[        USS5      =(       d    [        USS5      =(       d    [        U5      m[        US[	        T T5      S9  U$ )a  A class decorator that requires the dependency is available when the class is
initialized.  This decorator can be used even if the class does not define an ``__init__``
method.

Args:
    feature_or_class (str or Type): the name of the feature that requires these
        dependencies.  If this function is called directly as a decorator (for example
        ``@HAS_X.require_in_instance`` as opposed to
        ``@HAS_X.require_in_instance("my feature")``), then the feature name will be taken
        as the name of the class.

Returns:
    Callable: a class decorator that ensures that the wrapped feature is present if the
    class is initialized.
c                 2   > [        U S[        TT5      S9  U $ )Nr   before)r   r   )class_r   r   s    r   rT   <LazyDependencyManager.require_in_instance.<locals>.decorator   s    FJ{47QRr   r$   Nr"   r   rc   )rX   rY   rZ   r   r   )r   r[   rT   re   r   s   `   @r   r^   r_      sr      &,,&G !FND1 vz406{ 	
 	FJ{4/IJr   r   c                 d    U (       a  g[        U R                  XR                  U R                  S9e)a  Eagerly attempt to import the dependencies in this object, and raise an exception if they
cannot be imported.

Args:
    feature: the name of the feature that is requiring these dependencies.

Raises:
    MissingOptionalLibraryError: if the dependencies cannot be imported.
N)libnamer4   pip_installr7   )r	   r0   r1   r2   )r   r   s     r   r   !LazyDependencyManager.require_now   s*     )JJW--TYY
 	
r   c              #   ^   #    U R                   nSU l          Sv   Xl         g! Xl         f = f7f)a\  
Create a context, during which the value of the dependency manager will be ``False``.  This
means that within the context, any calls to this object will behave as if the dependency is
not available, including raising errors.  It is valid to call this method whether or not the
dependency has already been evaluated.  This is most useful in tests.
FN)r.   )r   previouss     r   disable_locally%LazyDependencyManager.disable_locally   s)      ::
	"!JJs   -" -*-)r.   r/   r1   r2   r0   )r"   r#   r$   r%   r&   r'   r   abcabstractmethodboolr=   r@   typingoverloadr   rE   rY   r   r^   r   
contextlibcontextmanagerrm   r(   r)   r   r   r+   r+   ,   s   'R DI#dDd   	t   __M8MM M__^3^8XJPXDX;Y^ ^(T __FDFTF F__WCWHdVT\<RW W D
3 
  " "r   r+   c                      ^  \ rS rSrSrSrSSSSS.S\\\\\	\   4   \	\   4   S\
\   S\
\\/S4      S	\
\   S
\
\   4
U 4S jjjrS rSrU =r$ )LazyImportTester   zA lazy dependency tester for importable Python modules.  Any required objects will only be
imported at the point that this object is tested for its Boolean value.)_modulesNr3   name_map_or_modulesr4   r5   r6   r7   c                d  > [        U[        5      (       a5  UR                  5        VVs0 s H  u  pgU[        U5      _M     snnU l        O7[        U[
        5      (       a
  US0U l        OU Vs0 s H  ofS_M     snU l        U R                  (       d  [        S5      eUb  Ou[        U R                  5      S:X  a  U R                  R                  5       u  nO?[        U R                  R                  5       5      nSR                  USS 5       SUS    3n[        T	U ]-  X#XES9  gs  snnf s  snf )	a  
Args:
    name_map_or_modules: if a name map, then a dictionary where the keys are modules or
        packages, and the values are iterables of names to try and import from that
        module.  It should be valid to write ``from <module> import <name1>, <name2>, ...``.
        If simply a string or iterable of strings, then it should be valid to write
        ``import <module>`` for each of them.

Raises:
    ValueError: if no modules are given.
r)   zno modules suppliedNr   z, z and r3   )rX   dictitemstuplery   rY   
ValueErrorlenkeysjoinsuperr   )
r   rz   r4   r5   r6   r7   modulenames	all_names	__class__s
            r   r   LazyImportTester.__init__   s   ( )400GZG`G`GbcGbmfVU5\1GbcDM+S110"5DM6IJ6IFRZ6IJDM}}2331$mm((*GTdmm0023Iii	#2/0im_EDdwP d Ks   D'/D-c           	         0 n[         R                  " [        5      nU R                  R	                  5        H1  u  p4 [
        R                  " U5      nU H  n	 [        XY5      n
M     M3     U(       d  U(       a  U R                  (       a  SU R                   S3OSnSU S3nUR	                  5        H   u  p6USR!                  SU S	U< 35      -  nM"     UR	                  5        H=  u  p4[        U5      S
:X  a	  SUS    S3OSU 3nUSR!                  SU SU S35      -  nM?     ["        R$                  " U[&        S9  gg! [         aS  nUR                  R                  S5      nUR                  S5      nXxS [        U5       :X  a   S nA  gXaU'    S nAGMd  S nAf[         a  nXaU'    S nAGM|  S nAff = f! [         a    X#   R                  U	5         GM  f = f)N.F'zoptional packageszWhile trying to import z, some components were located but raised other errors during import. You might have an incompatible version installed. Qiskit will continue as if the optional is not available. z
 - module 'z' failed to import with: r   zattribute 'r   zattributes z
 - 'z' imported, but z couldn't be found)categoryT)collectionsdefaultdictlistry   r~   	importlibimport_moduleModuleNotFoundErrorr4   splitr   ImportErrorrZ   AttributeErrorappendr0   r   warningswarnr
   )r   failed_modulesfailed_namesr   r   importedexcfailed_partstarget_partsr4   _package_descriptionmessage
attributess                 r   r=   LazyImportTester._is_available  s   "..t4!]]002MF$226: 6/A ! 3* \7;zzAdjj\"3GZ)*=)> ?M M   .335277]6(:STWSZ#[\\  6!-!3!3!5:=e*/{58*A6Q\]b\cOd
277VF83CJ<Oa#bcc "6 MM',KLC ' 	"xx~~c2%||C00C#l2C#DD !),v& ),v& & 6 (//556s;   EF;
F8=FFF8(F33F8;GG)r"   r#   r$   r%   r&   r'   r   rY   r   r   r   r   rq   r   r=   r(   __classcell__r   s   @r   rw   rw      s    O I #59!%!#Q"3S(3--?(@(3-#OP#Q sm	#Q
 8TFDL12#Q ##Q c]#Q #QJ' 'r   rw   c                      ^  \ rS rSrSrSrSSSSS.S\\\\   4   S\	\   S\	\
\/S4      S	\	\   S
\	\   4
U 4S jjjrS rSrU =r$ )LazySubprocessTesteriF  zA lazy checker that a command-line tool is available.  The command will only be run once, at
the point that this object is checked for its Boolean value.
)_commandNr3   commandr4   r5   r6   r7   c                   > [        U[        5      (       a  U4O
[        U5      U l        U R                  (       d  [	        S5      e[
        TU ]  U=(       d    U R                  S   X4US9  g)z
Args:
    command: the strings that make up the command to be run.  For example,
        ``["pdflatex", "-version"]``.

Raises:
    ValueError: if an empty command is given.
zno command suppliedr   r3   N)rX   rY   r   r   r   r   r   )r   r   r4   r5   r6   r7   r   s         r   r   LazySubprocessTester.__init__M  sV    " '1#&>&>
E'N}}233d6dmmA&6`cdr   c                      [         R                  " U R                  S[         R                  [         R                  S9  g! [        [         R
                  4 a     gf = f)NT)checkstdoutstderrF)
subprocessrunr   DEVNULLOSErrorSubprocessErrorr<   s    r   r=   "LazySubprocessTester._is_availablec  sP    	NNT*2D2DZM_M_  334 		s   =A   AA)r"   r#   r$   r%   r&   r'   r   rY   r   r   r   rq   r   r=   r(   r   r   s   @r   r   r   F  s     I #59!%!esHSM)*e sm	e
 8TFDL12e #e c]e e, r   r   )r&   ro   r   rt   rR   r   r   rr   r   r   r   r   r   r   r   qiskit.exceptionsr	   r
   
classtoolsr   r   ABCr+   rw   r   r)   r   r   <module>r      sh    * 
        B B Z #0 0B"CGG B"JR, Rj%0 %r   