
    ɱ^d                        d Z dZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ej                  dk\  rddlmZ nddlZej                  dk\  rddlZ	 ddlmZ ddlmZ 	 eZg d	Z	 g d
Z	 ddddddZd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'd Z(d Z)d*dZ*d Z+d*d Z,d! Z-d" Z.d# Z/d$ Z0d% Z1d& Z2d' Z3d( Z4d) Z5y# e$ r ddlmZ ddlmZ Y vw xY w# e$ r eZY w xY w)+zHelpDev - Extracts information about the Python environment easily.

Authors:
    - Daniel Cosmo Pizetta <daniel.pizetta@usp.br>

Since:
    2019/04/16

License:
    MIT

z0.7.1    N)      )metadatar      )urlopen)urlparse)PyQt4PyQt5PySidePySide2)qtpy	pyqtgraphQtz https://pypi.python.org/pypi/pipz$https://repo.continuum.io/pkgs/free/zhttps://gitlab.comzhttps://github.comzhttps://google.com)PyPICondaGitLabGitHubGooglec                     t        j                  | d      }t        j                  dk\  rt	        |d      j                         }|S t        |d      j                         }|S )zRun command in subprocess and return the splited output.

    Returns:
        str: Splited output from command execution.
    F)shell)r   r   zutf-8)
subprocesscheck_outputsysversion_infostrstripunicode)commandoutputs     2/usr/lib/python3/dist-packages/helpdev/__init__.py_run_subprocess_splitr"   B   s\     $$WE:F
6!VW%++- M )//1M    c                     | j                         D ]R  \  }}t        dj                  |             |j                         D ]   \  }}t        dj                  ||             " T y)z%Print output in a nested list format.z	* {:-<79}z    - {:.<30} {}N)itemsprintformat)	info_dictkeysub_dictsub_key	sub_values        r!   print_outputr-   S   sd    "* AXk  %&"*.."2 	AGY$++GY?@	AAr#   c                 <   |j                  d      D cg c]
  }d|z   dz    }}dj                  |      }t        j                  d|z   dz         }t	        j
                  |       }| j                         D ]  }t        j                  ||      }|r||=   |S c c}w )aC  Filter the dict_packages with expression regex.

    In the expression, each item separated by comma is splitted and then
    surrounded parenthesis (i.e. group), then joined with OR (``|``).
    The expressions are finally started to match the begin until the
    end ignoring case (``i``). See the example below ::

        expression = "sphinx.*,qtpy,PYQT5"


    Then it will be processed resulting in ::

        expression = "(?i:^((sphinx.*)|(qtpy)|(PYQT5))$)"


    If the expression of all of them not match with the package name,
    this package is removed from the dict (a copy of it).

    Args:
        dict_packages (dict): Dictionary with package_name:version_number.
        expression (str): Regular expression separated by commas.

    Returns:
        dict(rst): Filtered dict with that matches the expression.
    ,()|z(?i:^(z)$))splitjoinrecompilecopydeepcopykeyssearch)	dict_packages
expressionitemexpression_listexpression_strcompiled_expcp_dict_packagesr)   matchs	            r!   filter_packagesrC   [   s    6 5?4D4DS4IJDsTzC'JOJXXo.N::h7%?@L}}]3!!# &		,, %&
  Ks   Bc                 h   di i}t        | g      }|rt        j                  }	 t        j                  |       }|j                  t              }ddj                  |      i|d<   |D ]P  }t        |t              r	d|d   |<   t        |t              rd|d   |d   <   8d}d|j                  |      i|d<    n 	 |t        _        |S ddj                  |       i|d<   |S # t        $ r dd	j                  |       i|d<   Y Ft        $ r)}dd
j                  t        |            i|d<   Y d}~rd}~ww xY w)a  Get the custom filter from the package imported.

    This is a way to promote a standard format to get a customized information
    from a specific package. This function try to import the package and
    run the public method ``get_custom_helpdev(help_dev_version='')`` from
    that package which gives a customized filter to provide the results.

    For example, this line ::

        info_dict = helpdev.customize('spyder')

    will try this ::

        from spyder import get_custom_helpdev
        custom_filter = get_custom_helpdev(helpdev.__version__)

    Then, it will apply that filter.

    Args:
        package (str): Import name to check installation.

    Returns:
        dict(str): Customized information from imported packages.
    REPORTFilterz{}r   tupler   z/Unknown, filter has a unknown item/format '{}'.StatuszCUnknown, package '{}' does not provide 'custom_helpdev()' function.zError, '{}'NzNot installed, package '{}'.)check_installedr   path	importlibimport_modulecustom_helpdev__version__r'   
isinstancer   rG   AttributeError	Exception)	packageinfo	installedsys_pathmodcustom_filterr=   msgerrs	            r!   	customizerZ      sQ   4 b>D  	*I88	))'2C..{;M 'M(BCDN% dC(+0DN4(e,.5DN47+KC&.

40@%ADN  K #$B$I$I'$RSXK-  	E& )44:F7OEDN  	H&(<(<SX(FGDN	Hs   *C D1 D1D,,D1c                    t        j                  d       t        j                  |       }| D ]|  }d}t        j
                  }t        j                  dk\  r)t        t        j                  j                  |            }n	 t        |       d}|s|j                  |       |t        _        ~ t        j                          |S # t        $ r d}Y Ct        $ r d}Y Ow xY w)aX  Return a list of installed packages from import_list.

    Note that the strings in the list must match the import name, e.g.
    pyqt5 will not work as the import name is PyQt5.

    Args:
        import_list (list(str)): List of of import names to check installation.

    Returns:
        list(str): Filtered list of installed packages.
    ignoreTr   F)warningsfilterwarningsr7   r8   r   rJ   r   boolrK   util	find_spec
__import__RuntimeWarningrQ   removeresetwarnings)import_listimport_list_returncurrent_importspecrU   s        r!   rI   rI      s     H%{3 & 88 v%	00@AD>* %%n5 /4 # "  s   ?CC
CCc                     d} t         j                  j                  d      r>t        ddg      }|j	                  d      D ]  }d|v s|j	                  d      d   }  n nt         j                  j                  d	      r=t        d
g      }|j	                  d      D ]  }d|v s|j	                  d      d   }  nD nBt         j                  j                  d      r#t        g d      }d|v r|j                  dd      } 	 ddl}t        t        |j                         j                  dz              dz   }t        t        |j                         j                  dz              dz   }t        t        |j                         j                  dz              dz   }t        t        |j                         j                  dz              dz   }dt        j                         | j                         ||||di}|S # t        $ r d}|x}x}}Y @w xY w)zCheck hardware information.

    It uses subprocess commands for each system along with ``psutil`` library.
    So you need to install psutil library.

    Returns:
        dict(str): Dictionary filled with respective information.
     darwinsysctlz-a
brand_stringz:    linuxlscpuzModel name::win32)wmiccpugetnameNamer   Ni@B z MBzUnknown, needs psutil libraryHARDWARE)Machine	ProcessorzTotal MemoryzFree Memoryz
Total Swapz	Free Swap)r   platform
startswithr"   r3   replacepsutilr   intvirtual_memorytotalfreeswap_memoryImportErrormachinelstrip)	rv   all_infoliner   memmem_freeswap	swap_freerS   s	            r!   check_hardwarer      s    C ||x(((D)9:NN4( 	D%jj&q)	
 
	 	 	)('3NN4( 	D$jjoa(	
 
	 	 	)()GHX""62.C	J
 #f++-33g=>?%Gs600277'ABCeK3v))+11G;<=EF..055?@AEI	 ((***, $#D K'  *-&)))y8*s   ?G8 8HHc                      dt        j                         t        j                         t        j                          t        j                         di} | S )zxCheck operating system information.

    Returns:
        dict(str): Dictionary filled with respective information.
    zOPERATING SYSTEM)SystemReleasePlatformVersion)r}   systemreleaseversionrS   s    r!   check_osr   ,  sH     ( ((*!**, ((*D Kr#   c                  (   di i} t         j                  dk\  rb| d   j                  t         j                  j                  t         j                  j
                  t         j                  j                  d       | S | d   j                  dddd       | S )zCheck threads information.

    Get information from ``sys`` library.

    Returns:
        dict(str): Dictionary filled with respective information.
    THREADSr   r   )r   ry   LockUnknown, needs Python>=3.3)r   r   updatethread_infor   rx   lockr   s    r!   check_threadr   >  s     r?D
6!Y//__))__))	 K 	Y411	 Kr#   c                  6   dt         j                  j                  t         j                  j                  t         j                  j                  t         j                  j
                  t         j                  j                  t         j                  j                  t         j                  j                  t         j                  j                  t         j                  j                  t         j                  j                  t         j                  j                  di} | S )zCheck float limits information.

    Get information from ``sys`` library.

    Returns:
        dict(str): Dictionary filled with respective information.
    FLOAT)EpsilonDigits	PrecisionMaximumzMaximum Exp.zMax. 10 Exp.MinimumzMiminim Exp.zMin. 10 Exp.RadixRounds)r   
float_infoepsilondigmant_digmaxmax_exp
max_10_expminmin_exp
min_10_expradixroundsr   s    r!   check_floatr   X  s     ..~~))..11** ^^33 ^^66** ^^33 ^^66nn**~~,,D Kr#   c                      di i} t         j                  dk\  rI| d   j                  t         j                  j                  t         j                  j
                  d       | S | d   j                  ddd       | S )zCheck int limits information.

    Get information from ``sys`` library.

    Returns:
        dict(str): Dictionary filled with respective information.
    INTEGER)r   rp   )zBits per DigitzSize of DigitzUnknown, needs Python>=3.1)r   r   r   int_infobits_per_digitsizeof_digitr   s    r!   	check_intr   s  sy     r?D
6!Y"||::!ll77	
 K 	Y;:	

 Kr#   c                  n    i } | j                  t                      | j                  t                      | S )z4Check numbers related float and integer information.)r   r   r   r   s    r!   check_numbersr     s(    DKKKK	Kr#   c                 :   ddt        |       dz   ii}| dkD  rt        j                  |        n
d|d   d<   |S t        j	                         D ]  \  }}|j                         j                  d      s&t        |      }d}d}t        j                         }	 t        j                  |j                        }t        j                         |z
  }
d}t        j                         }	 t        ||       }t        j                         |z
  }|rdj                  |
||      |d   |<    |S # t        $ r/}	t        |	      }d	j                  ||      |d   |<   d
}Y d}	~	d}	~	ww xY w# t        $ r/}	t        |	      }dj                  ||      |d   |<   d
}Y d}	~	d}	~	ww xY w)zCheck network connection for URLS list with timeout.

    Args:
        timeout (int): timout in seconds.

    Returns:
        dict(str): Dictionary filled with respective information.
    NETWORKTimeoutsr   zUnknown, must be > 0shttpFrk   zDNS ERROR: {}s URL: {}TN)timeoutzLOAD ERROR: {}s URL: {}z"DNS: {:.4f}s LOAD: {:.4f}s URL: {})r   socketsetdefaulttimeoutURLSr%   lowerr~   r	   timegethostbynamenetlocrQ   r'   r   )r   rS   rx   urlurlinfoerrordns_errstart_rY   dns_elapsedload_errload_elapseds                r!   check_networkr     s    Gs* D
 {  )%<Y	"ZZ\ Y	c99;!!&)smGE GIIKE((8
 ))+-K HIIKEC1
  99;.L(L(S(ST_T`TW)YY%;YB K-  c((@(G(GQT(UY%  s8(A(H(HSV(WY%s0   D'#E"'	E0%EE"	F+%FFc                     dt        j                         t        j                         t        j                  di} t        j
                  dk\  r| d   j                  t        j                  j                  dj                  t        j                  j                  j                  t        j                  j                  j                  t        j                  j                  j                        d       | S | d   j                  ddd       | S )zCheck Python information.

    It is Python environment dependent. Get information from ``platform``
    and ``sys`` libraries.

    Returns:
        dict(str): Dictionary filled with respective information.
    zPYTHON DISTRIBUTION)r   z
C CompilerzC API Versionr   z{}.{}.{})ImplementationzImplementation Versionr   )r}   python_versionpython_compilerr   api_versionr   r   implementationrx   r'   r   majorminormicror   s    r!   check_pythonr     s     " //1#335!ooD 6!"#**"1166'1'8'89K9K9S9S9Y9Y9<9K9K9S9S9Y9Y9<9K9K9S9S9Y9Y([	 K 	"#**;'C	
 Kr#   c                 &   d}| rt        g d      }nt        ddg      }|j                  d      dd }di i}|D ]@  }|j                  d	      }d	j                  |      j                         }|d
   |d   |d   <   B |rt        |d   |      |d<   |S )zCheck PIP installed packages filtering for packages.

    Returns:
        dict(str): Dictionary filled with respective information.
    rk   )piplistz-er   r   rn      NzPYTHON PACKAGES rp   r   )r"   r3   r4   rC   )	edit_modepackagesall_packagesline_packagesrS   r   splittedcleaneds           r!   check_python_packagesr     s     L,-BC -eV_= !&&t,QR0Mr"D  9::c?((8$**,.5aj
+9
 "1$7H2I8"TKr#   c                  "   di i} 	 t        ddg      }|j                  d      D ]@  }d|v r|j                  d      d   | d   d<   "d	|v s'|j                  d      d   | d   d
<   B | S # t        j                  t        f$ r d| d   d<   Y | S w xY w)zCheck Conda Python distribution information.

    It is Python/Conda environment dependent.

    Returns:
        dict(str): Dictionary filled with respective information.
    zCONDA DISTRIBUTIONcondarS   rn   zconda version : z : rp   r   zconda-build version : BuildConda not available!rH   )r"   r3   r   CalledProcessErrorFileNotFoundError2and3)rS   r   r   s      r!   check_condar     s     !"%D	K('6):; NN4( 	KD!T)8<

58I!8L)*95)T16:jj6G6J)*73		K K ))+AB F/E!"8, KFs   A) )!BBc                 x   di i}d}	 | st        g d      }nt        g d      }|j                  d      dd }|D ]@  }|j                  d      }d	j                  |      j                         }|d
   |d   |d   <   B 	 |rt        |d   |      |d<   |S # t        j                  t
        f$ r d|d   d<   Y 9w xY w)zCheck conda inslalled packages information filtering for packages.

    It is Python/Conda environment dependent.

    Returns:
        dict(str): Dictionary filled with respective information.
    zCONDA PACKAGESrk   )r   r   --no-pip--export)r   r   r   r   z	--developrn   r   N=r   rp   r   r   rH   )r"   r3   r4   r   r   r   rC   )r   r   rS   r   r   r   r   r   s           r!   check_conda_packagesr   &  s     b!DL<0 2> ?L 1 2K LL %**404 " 	<Dzz#Hhhx(..0G18D!"71:.	<
 !06F1G!RK ))+AB B+Ax(Bs   B !B98B9c                      di i} t               D ]&  }t        |      \  }}|| d   |dz   <   || d   |dz   <   ( | d   sd| d   d<   | S )zCheck all Qt bindings related information.

    Returns:
        dict(str): Dictionary filled with respective information.
    zQT BINDINGS Versionz Qt VersionzNo Qt binding available!rH   )installed_qt_bindingsqt_binding_information)rS   bindingbinding_version
qt_versions       r!   check_qt_bindingsr  K  sw     2D(* B&<W&E#4C]Gj017A]Gm34B
 (B]H%Kr#   c                      di i} t               D ]J  }t        |      \  }}}}}|| d   |dz   <   || d   |dz   <   || d   |dz   <   || d   |dz   <   || d   |dz   <   L | d   sd| d   d<   | S )	zCheck all Qt abstractions related information.

    Returns:
        dict(str): Dictionary filled with respective information.
    zQT ABSTRACTIONSr   z Bindingz Binding Variablez Import Namez StatuszNo Qt abstractions available!rH   )installed_qt_abstractionsqt_abstraction_information)rS   abstractionabs_vbindbind_varimp_namestatuss          r!   check_qt_abstractionsr  _  s     r"D02 B2L[2Y/tXx<Aj 89<@j 89EM.A AB@Hn <=;Ai 78B !",K)Kr#   c                  ^    i } | j                  t               | j                  t               | S )z7Check Qt related bindings and abstractions information.)r   r  r  r   s    r!   check_qtr  v  s&    DKK!"KK%&Kr#   c                  "    t        t              S )zvReturn a list of qt bindings available.

    Returns:
        list(str): List filled with respective information.
    rf   )rI   QT_BINDINGS r#   r!   r   r   ~  s     {33r#   c                  "    t        t              S )zReturn a list of qt abstraction layers available.

    Returns:
        dict(str): Dictionary filled with respective information.
    r  )rI   QT_ABSTRACTIONSr  r#   r!   r  r    s     77r#   c                    t         j                  }d}d}d}d}| dk(  r2	 ddlm} d	t        j                  vrd
}nt        j                  d	   }d}nM| dk(  r2	 ddlm} dt        j                  vrd
}nt        j                  d   }d}n| dk(  r	 ddlm} ddlm} d}ny|t         _        |||| |fS # t        $ r t	        d      t
        $ r-}t        j                  d      }dt        |      z   }Y d}~d}~ww xY w# t        $ r t	        d      t        $ r/}d}t        j                  d      }dt        |      z   }Y d}~d}~ww xY w# t        $ r}d
}d
}dt        |      z   }Y d}~d}~ww xY w)a  Get abstraction layer version and binding (default or current if in use).

    Note:
        - The name of the installed package can differ from the import name.
          This is an weird thing from PIP/CONDA, e.g, the abstraction 'qt.py'
          is imported as 'Qt'.
        - Since each package is build as it is, sometimes we are not able to
          define its information, e.g, Qt.py is installed but no binding is.
          This will cause an error that, for now, it is impossible to us to
          show any other information about it, e.g, version. We need to deal
          with a better way.
        - This function should be called with pre-defined list of installed
          packages passed throuw import_name, do not use it to try import.

    Todo:
        - Add info installed (y/n), imported (y/n), importable/status (error).

    Args:
        import_name (str): Import name of abstraction for Qt.

    Raises:
        ImportError: When the import is not found.

    Returns:
        tuple: (abstraction version,
                environment variable,
                binding variable,
                import name,
                status)
    rk   OKr   r   rN   zPyQtGraph cannot be imported.zERROR - NPYQTGRAPH_QT_LIBzNot set or inexistentzos.environ['PYQTGRAPH_QT_LIB']r   zQtPy cannot be imported.zNo Qt binding foundQT_APIzos.environ['QT_API']r   )__binding__zQt.__binding__)rk   rk   rk   rk   rk   )r   rJ   r   rN   r   rQ   importlib_metadatar   r   osenvironr   RuntimeErrorr   r  )import_namerU   r   env_varbinding_varr
  rY   s          r!   r  r    s   B xxHKGKFk!	+< RZZ/-Gjj!34G6			+7 2::%-Gjj*G,		
	+51 ' $ CH+{FCCg  	?=>> 	+,44[AK#c(*F	+  	:899 	++G,44V<K#c(*F	+   	+
 2K-G#c(*F	+sG   B/ C; E	 /C8#C33C8;E%EE		E.E))E.c                    t         j                  }| dk(  r	 ddlm} ddlm} n:| dk(  r	 ddlm} ddlm} n'| dk(  r	 dd	lm} dd	l	m} n| dk(  r	 dd	l
m} dd	lm} ny|t         _        ||fS # t
        $ r t        d      w xY w# t
        $ r t        d      w xY w# t
        $ r t        d
      w xY w# t
        $ r t        d      w xY w)a  Get binding information of version and Qt version.

    Note:
        The name of the installed package can differ from the import name.
        This is an weird thing from PIP/CONDA, e.g, the binding 'pyqt5'
        in PIP is 'pyqt' in Conda and both are imported as 'PyQt5'.

    Args:
        import_name (str): Import name of binding for Qt.

    Raises:
        ImportError: When the import is not found.

    Returns:
        tuple: (binding version,
                qt version)
    r
   r   )PYQT_VERSION_STR)QT_VERSION_STRzPyQt4 cannot be imported.r   zPyQt5 cannot be imported.r   r  zPySide cannot be imported.r   zPySide2 cannot be imported.)rk   rk   )r   rJ   PyQt4.Qtr"  r#  r   PyQt5.QtCorer   rN   PySide.QtCorer   PySide2.QtCore)r  rU   r   r   s       r!   r   r     s    ( xxHg	;@= 
		;DA 
	 	<9? 
		!	=:@  CH$$;  	;9::	;  	;9::	;  	<:;;	<  	=;<<	=s-   A- B B B5 -BBB25C
c                      di i} t         j                  | d   d<   t        t         j                        D ]  \  }}|| d   |<    | S )z|Check Python path from ``sys`` library.

    Returns:
        dict(str): Dictionary filled with respective information.
    PATHSPython)r   
executable	enumeraterJ   rS   numrJ   s      r!   
check_pathr/  +  sP     R=D!nnDM(sxx( "	T!Wc" Kr#   c                  T    di i} t        t                     D ]  \  }}|| d   |<    | S )zqCheck Python scope or dir().

    Returns:
        dict(str): Dictionary filled with respective information.
    SCOPE)r,  dirr-  s      r!   check_scoper3  ;  s<     R=Dsu% "	T!Wc" Kr#   )FN)6__doc__rN   r7   r  r}   r5   r   r   r   r   r]   r   rK   r   r  importlib.utilurllib.requestr   urllib.parser	   r   urllib2FileNotFoundErrorr   	NameErrorOSErrorr  r  r   r"   r-   rC   rZ   rI   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r   r  r  r   r/  r3  r  r#   r!   <module>r<     sI     	  	   
  v8v &%%.
 6 0- : /3""""A%P:z0f6r$4626r@@2"J(.48^DB7%t g   !   %$%s$   C $C CCC'&C'