
>gT!M                 @   s   d  d l  Z  d  d l Z d  d l Z d  d l m Z m Z d  d l m Z m Z m	 Z	 e j
 d e j  Z e j
 d e j  Z e  j d  Z Gd d   d  Z d  d	 l m Z d  d
 l m Z m Z d S)    N)joinsplit)INTERPRETER_DIR_TPLSPUBLIC_DIR_REOLD_SITE_DIRSz
    (?:\#!\s*){0,1}  # shebang prefix
    (?P<path>
        .*?/bin/.*?)?
    (?P<name>
        python|pypy)
    (?P<version>
        \d[\.\d]*)?
    (?P<debug>
        -dbg)?
    (?P<options>.*)
    am  
    (?P<name>.*?)
    (?:\.
        (?P<stableabi>abi\d+)
     |(?:\.
        (?P<soabi>
            (?P<impl>cpython|pypy)
            -
            (?P<ver>\d{2})
            (?P<flags>[a-z]*)
        )?
        (?:
            (?:(?<!\.)-)?  # minus sign only if soabi is defined
            (?P<multiarch>[^/]*?)
        )?
    ))?
    (?P<debug>_d)?
    \.so$dhpythonc            	   @   s  e  Z d  Z d Z d Z d Z d Z d Z d Z f  Z	 i  Z
 d d d d d d d d d  Z d	 d
   Z d d   Z d d   Z d d d d  Z d d d  Z e d d    Z e d d    Z e d d    Z e d d    Z d d d d d  Z d d d d d  Z d d    Z d! d"   Z d d# d$  Z d d% d&  Z d d' d(  Z d d) d*  Z d d+ d,  Z  d d- d.  Z! e d/ d0    Z" e d1 d2    Z# d d3 d4  Z$ d5 d6   Z% d d7 d8  Z& d d9 d: d;  Z' d S)<Interpretera  
    :attr path: /usr/bin/ in most cases
    :attr name: pypy or python (even for python3 and python-dbg) or empty string
    :attr version: interpreter's version
    :attr debug: -dbg version of the interpreter
    :attr impl: implementation (cpytho2, cpython3 or pypy)
    :attr options: options parsed from shebang
    :type path: str
    :type name: str
    :type version: Version or None
    :type debug: bool
    :type impl: str
    :type options: tuple
    z	/usr/bin/pythonNF c             C   sC  t    } | d =| d =t | t  rf x | j   D], }	 | |	 d  k r3 t | |	  | |	 <q3 q3 Wn~ | r | j d d  j   r | r t |  | d <q xC |  j |  j	   D]) \ }	 }
 | |	 d  k r |
 | |	 <q q Wn  xX | j	   D]J \ }	 }
 |
 d  k	 rt
 |  |	 |
  q |	 d k r t
 |  |	 |
  q q Wd  S)Nselfvalue.r
   version)locals
isinstancer   keysgetattrreplaceisdigitVersionparseitemssetattr)r   r   pathnamer   debugimploptionsZparamskeyval r    ,/usr/share/dh-python/dhpython/interpreter.py__init__S   s$    	"zInterpreter.__init__c             C   sI  | d k r | d k r+ t  d |   n  | d k ru |  j r |  j j d k rb d |  j d <qr d	 |  j d <q q | d k r d |  j d <q ng | d
 k r | d  k	 r t |  } |  j r |  j d k r | j d k r d |  _ q d	 |  _ q n  | d k r| d  k rn/ | d k r8t |  |  j | <n | |  j | <d  S)Nr   r	   pypyr
   zinterpreter not supported: %s   cpython3r   cpython2r   r   r   r   )zpythonr#   r
   )zpathznamezimplzoptions)
ValueErrorr   major__dict__r   r   r   bool)r   r   r   r    r    r!   __setattr__n   s*    	zInterpreter.__setattr__c             C   se   |  j  } | j d  s% | d 7} n  | |  j |  j  7} |  j ra | d d j |  j  7} n  | S)N/ )r   endswith_vstrr   r   r   )r   resultr    r    r!   __repr__   s    		zInterpreter.__repr__c             C   s   |  j  |  j  S)N)r/   r   )r   r    r    r!   __str__   s    zInterpreter.__str__c             C   s   |  j  d k r |  j S| p( |  j p( d } | re | sG | |  j k re |  j  d k r\ d n d } n- t | t  r | t d d  k r d } n  |  j r d j |  S|  j t |  S)Nr#   r
   r%   3r(      zpython{}-dbg)	r   r   r   default_versionr   r   r   formatstr)r   r   consider_default_verr    r    r!   r/      s    $		zInterpreter._vstrc             C   s   d j  |  j |  j |   S)Nz{}{})r6   r   r/   )r   r   r    r    r!   binary   s    zInterpreter.binaryc             C   s   d j  |  j |  j d d   S)zLike binary(), but returns path to default intepreter symlink
        if version matches default one for given implementation.
        z{}{}r8   T)r6   r   r/   )r   r    r    r!   	binary_dv   s    zInterpreter.binary_dvc             C   s   |  j  r t |  j   Sd  S)N)r   default)r   r    r    r!   r5      s    	zInterpreter.default_versionc             C   s   t  j |   } | s i  S| j   } d | k rN t | d j    | d <n  | d d k r{ | d d k r{ d | d <n  | S)a^  Return dict with parsed shebang

        >>> sorted(Interpreter.parse('/usr/bin/python3.2-dbg').items())
        [('debug', '-dbg'), ('name', 'python'), ('options', ()), ('path', '/usr/bin/'), ('version', '3.2')]
        >>> sorted(Interpreter.parse('#! /usr/bin/python3.2').items())
        [('debug', None), ('name', 'python'), ('options', ()), ('path', '/usr/bin/'), ('version', '3.2')]
        >>> sorted(Interpreter.parse('/usr/bin/python3.2-dbg --foo --bar').items())
        [('debug', '-dbg'), ('name', 'python'), ('options', ('--foo', '--bar')), ('path', '/usr/bin/'), ('version', '3.2')]
        r   r   r	   r   N2)
SHEBANG_REsearch	groupdicttupler   )Zshebangr0   r    r    r!   r      s     zInterpreter.parsec             C   s   t    } t | d  1 } | j d  } d | k rE t d   n  Wd QXt | d  j d  d } | j d	  s t d
 |   n  |  j |  } | s t d
 |   n  x* | j   D] \ } } t	 | | |  q W| S)z!Read file's shebang and parse it.rb`   s    zcannot parse binary fileNzutf-8
r   z#!zdoesn't look like a shebang: %s)
r   openreadr'   r7   r   
startswithr   r   r   )clsfpathZinterpreterfpdataZparsedr   r   r    r    r!   	from_file   s    	zInterpreter.from_filec             C   s   y t  | p |  j  } Wn5 t k
 rP } z t d |   WYd d } ~ Xn X|  j d k ri d } n@ | t  d  >r d | } n# | t  d  >r d | } n d	 } | r d
 | } n  | r d | | f } n  | S)a  Return path to site-packages directory.

        Note that returned path is not the final location of .py files

        >>> i = Interpreter('python')
        >>> i.sitedir(version='3.1')
        '/usr/lib/python3/dist-packages/'
        >>> i.sitedir(version='2.5')
        '/usr/lib/python2.5/site-packages/'
        >>> i.sitedir(version=Version('2.7'))
        '/usr/lib/python2.7/dist-packages/'
        >>> i.sitedir(version='3.1', gdb=True, package='python3-foo')
        'debian/python3-foo/usr/lib/debug/usr/lib/python3/dist-packages/'
        >>> i.sitedir(version=Version('3.2'))
        '/usr/lib/python3/dist-packages/'
        zcannot find valid version: %sNr#   z/usr/lib/pypy/dist-packages/z2.6z /usr/lib/python%s/site-packages/z3.0z /usr/lib/python%s/dist-packages/z/usr/lib/python3/dist-packages/z/usr/lib/debug%szdebian/%s%s)r   r   	Exceptionr'   r   )r   packager   gdberrr   r    r    r!   sitedir   s     #	zInterpreter.sitedirc                s4  y t  | p |  j  } Wn5 t k
 rP } z t d |   WYd d } ~ Xn Xg  } xm t j |  j g   D]V } t | t  r | j	 | j
 |   qm | |  } | d k	 rm | j	 |  qm qm W| rd d   | D } |  j j d  r| j	 d j
 |   qn    r0  f d d   | D } n  | S)z5Return deprecated paths to site-packages directories.zcannot find valid version: %sNc             S   s   g  |  ] } d  j  |   q S)z/usr/lib/debug{})r6   ).0ir    r    r!   
<listcomp>  s   	 z,Interpreter.old_sitedirs.<locals>.<listcomp>cpythonz(/usr/lib/debug/usr/lib/pyshared/python{}c                s"   g  |  ] } d  j    |   q S)zdebian/{}{})r6   )rQ   rR   )rM   r    r!   rS     s   	 )r   r   rL   r'   r   getr   r   r7   appendr6   rF   )r   rM   r   rN   rO   r0   itemresr    )rM   r!   old_sitedirs   s$    #zInterpreter.old_sitedirsc             C   sL   t  |  j j |  } | rH | j d  } | r; t |  St |  j  Sd S)z.Return version assigned to site-packages path.r   N)r   r   matchgroupsr   r;   )r   r   rZ   Zversr    r    r!   parse_public_version  s    
z Interpreter.parse_public_versionc                s   d j    j  } |   j j k r{   f d d   t j   D } t j d j d d   | D   } |   j j | <n   j j | } | j	 |  S)zBReturn True if path is used by another interpreter implementation.zshould_ignore_{}c                s+   g  |  ]! \ } } |   j  k r |  q Sr    )r   )rQ   kv)r   r    r!   rS   &  s   	 z-Interpreter.should_ignore.<locals>.<listcomp>|c             s   s   |  ] } d  j  |  Vq d S)z({})N)r6   )rQ   rR   r    r    r!   	<genexpr>'  s    z,Interpreter.should_ignore.<locals>.<genexpr>)
r6   r   	__class___cacher   r   recompiler   r>   )r   r   Z	cache_keyexprZregexpr    )r   r!   should_ignore"  s    %zInterpreter.should_ignorec             C   s   t  | p |  j  } d |  j k r* d n d } | t  d  k rJ | | St |  \ } } | j d  sx | d 7} n  t | d d | d d
  |  j |  | f  S)a  Given path to a .py file, return path to its .pyc/.pyo file.

        This function is inspired by Python 3.2's imp.cache_from_source.

        :param fpath: path to file name
        :param version: Python version

        >>> i = Interpreter('python')
        >>> i.cache_file('foo.py', Version('3.1'))
        'foo.pyc'
        >>> i.cache_file('bar/foo.py', '3.4')
        'bar/__pycache__/foo.cpython-34.pyc'
        z-Oocz3.1z.py__pycache__z
%s.%s.py%sNr$   )r   r   r   r   r.   r   	magic_tag)r   rH   r   Z	last_charfdirfnamer    r    r!   
cache_file-  s    zInterpreter.cache_filec             C   sD   t  | p |  j  } |  j d k r( d S|  j d |  } t |  S)zReturn magic number.r&   r
   z"import imp; print(imp.get_magic()))r   r   r   _executeeval)r   r   r0   r    r    r!   magic_numberF  s
    zInterpreter.magic_numberc             C   sK   t  | p |  j  } |  j j d  r; | t  d  >r; d S|  j d |  S)zReturn Python magic tag (used in __pycache__ dir to tag files).

        >>> i = Interpreter('python')
        >>> i.magic_tag(version='3.4')
        'cpython-34'
        rT   z3.2r
   z import imp; print(imp.get_tag()))r   r   r   rF   ro   )r   r   r    r    r!   rk   N  s    "zInterpreter.magic_tagc             C   sh   t  | p |  j  } y# |  j |  d d  \ } } Wn) t k
 rc t j d d d d SYn X| S)zReturn multiarch tag.Nr4   zcannot get multiarchexc_infoTr
   )r   r   _get_configrL   logr   )r   r   soabi	multiarchr    r    r!   rv   Z  s    #	zInterpreter.multiarchc             C   sH   t  | p |  j  } |  j d k rD | t  d  ?rD d j | j  Sd  S)Nr%   z3.2zabi{})r   r   r   r6   r(   )r   r   r    r    r!   	stableabie  s    zInterpreter.stableabic             C   sh   t  | p |  j  } y# |  j |  d d  \ } } Wn) t k
 rc t j d d d d SYn X| S)z)Return SOABI flag (used to in .so files).Nr4   zcannot get soabirr   Tr
   )r   r   rs   rL   rt   r   )r   r   ru   rv   r    r    r!   ru   k  s    #	zInterpreter.soabic             C   s   |  j  d k r d Sy |  j   d } | r0 | SWn+ t k
 r^ d } t j d d d Yn Xd j |  j  } |  j } |  j r | d	 >r | d
 7} q | d 7} n0 | d ?r | d 7} n | d k r | d 7} n  | S)zReturn INCLUDE_DIR path.

        >>> Interpreter('python2.7').include_dir
        '/usr/include/python2.7'
        >>> Interpreter('python3.4-dbg').include_dir
        '/usr/include/python3.4dm'
        r#   z/usr/lib/pypy/includer4   r
   zcannot get include pathrr   Tz/usr/include/{}z3.3_dZdmz3.2mZmu)r   rs   rL   rt   r   r6   r   r   )r   r0   r   r    r    r!   include_dirw  s(    			

zInterpreter.include_dirc             C   s   |  j  d k r d S|  j   d d  \ } } | j d  rS | j d d  } n  | rl | rl t | |  St d j |     d S)	zReturn libfoo.so file path.r#   r
   r$      z.az.sozcannot find library file for {}N)r   rs   r.   r   r   rL   r6   )r   ZlibplZ	ldlibraryr    r    r!   library_file  s    zInterpreter.library_filec       
      C   s  t  | p |  j  } d | k r< | j d d  \ } } n d } t j |  } | s[ d S| j   } | d r | s | j d k r t  d | d d | d d f  } n  | d r d S| d	 r |  j d
 k r d S| d r | d r d Sy# |  j |  d d  \ } } Wn) t	 k
 rAt
 j d d d d SYn X| d rf| rf| d | k rfd S| d ps| } | d p| } | d }	 |  j d k r| d ?r|	 j d  r|	 d d  }	 n  | rd j |	 |  }	 | rQ|  j d k o| d >rQd j |	 |  }	 qQn6 |  j d k rQ| d k rQ| rQd j |	 |  }	 n  |  j rv|  j d k rv|	 d 7}	 n  |	 d 7}	 | |	 k rd St | |	  S)z2Return extension file name if file can be renamed.r,      r
   NZverz%s.%sr   rw   r   Fru   rv   r4   zcannot get soabi/multiarchrr   Tr   r%   z3.2module   z{}.{}z3.3z{}-{}r&   z2.7rx   z.soi)r   r   rsplit
EXTFILE_REr>   r?   minorr   rs   rL   rt   r   r.   r6   r   )
r   rm   r   rl   inforu   rv   Z	tmp_soabiZtmp_multiarchr0   r    r    r!   check_extname  sP     )
#	 
( !
zInterpreter.check_extnamec             C   sc   |  j  d k r d j |  S|  j  d k r1 d n d } d j | |  } |  j r_ | d 7} n  | S)aA  Suggest binary package name with for given library name

        >>> Interpreter('python3.1').suggest_pkg_name('foo')
        'python3-foo'
        >>> Interpreter('python3.4').suggest_pkg_name('foo')
        'python3-foo'
        >>> Interpreter('python2.7-dbg').suggest_pkg_name('bar')
        'python-bar-dbg'
        r#   zpypy-{}r%   r3   r
   zpython{}-{}z-dbg)r   r6   r   )r   r   r   r0   r    r    r!   suggest_pkg_name  s    
	zInterpreter.suggest_pkg_namec             C   s   t  | p |  j  } |  j d k s` |  j j d  ri | d ?rJ | d >s` | d ?s` | d k ri d } n d } | d 7} |  j | |  j d	  } y t j d
 | d <Wn t k
 r Yn X| S)Nr#   rT   z2.6r3   z3.1zimport sysconfig as s;z%from distutils import sysconfig as s;zrprint("__SEP__".join(i or "" for i in s.get_config_vars("SOABI", "MULTIARCH", "INCLUDEPY", "LIBPL", "LDLIBRARY")))Z__SEP__ZDEB_HOST_MULTIARCHr}   )	r   r   r   rF   ro   r   osenvironKeyError)r   r   cmdZ	conf_varsr    r    r!   rs     s    !	
zInterpreter._get_configTc             C   s   t  | p |  j  } d j |  j |  | j d d   } | rb | |  j j k rb |  j j | St |  } | d d k r t j	 | d  t
 d j | | d    n  | d j   } t |  d k r | d } n  | r | |  j j | <n  | S)	Nz
{} -c '{}''
returncoder   stderrz{} failed with status code {}stdoutr}   )r   r   r6   r/   r   ra   rb   executert   r   rL   
splitlineslen)r   Zcommandr   cacheoutputr0   r    r    r!   ro     s    'zInterpreter._execute)(__name__
__module____qualname____doc__r   r   r   r   r   r   rb   r"   r+   r1   r2   r/   r9   propertyr:   r5   staticmethodr   classmethodrK   rP   rY   r\   rf   rn   rq   rk   rv   rw   ru   rz   r|   r   r   rs   ro   r    r    r    r!   r   <   sF   	%
 <r   )r   )r   r;   )Zloggingr   rc   os.pathr   r   r   r   r   r   rd   VERBOSEr=   r   Z	getLoggerrt   r   Zdhpython.toolsr   Zdhpython.versionr   r;   r    r    r    r!   <module>   s    