
>gT-                 @   s  d  d l  Z  d  d l Z d  d l Z d  d l m Z d  d l m Z d  d l m Z d  d l m Z d  d l	 m
 Z
 m Z m Z m Z m Z m Z d  d l m Z m Z e  j d  Z e j d	  Z e j d
  Z d d   Z d d   Z d d   Z d d   Z d d d  Z d d   Z d d   Z d d d  Z d d   Z  d d d d d  Z! Gd d    d   Z" d! d"   Z# d# d$   Z$ d  d% l% m& Z& d  d& l' m( Z( m) Z) m* Z* e j d' e* e j+  Z, e j d( e* e j+  Z- d S))    N)datetime)glob)dumps)rmtree)existsgetsizeisdirislinkjoinsplit)PopenPIPEZdhpythonz/(.*?)(-py\d\.\d(?:-[^.]*)?)?(\.egg-info|\.pth)$zNEEDED.*libpython(\d\.\d)c             C   si   |  j  d  } | j  d  } x& | d | d k rF | d =| d =q! Wd j d g t |  d |  S)z~Return relative path.

    >>> relpath('/usr/share/python-foo/foo.py', '/usr/bin/foo', )
    '../share/python-foo/foo.py'
    /r   z..   )r   r
   len)targetlinktl r   &/usr/share/dh-python/dhpython/tools.pyrelpath%   s
    r   c             C   s   t  j t |  |  |  S)zCreate relative symlink.)ossymlinkr   )r   r   r   r   r   relative_symlink2   s    r   c             C   s   t  |   rX t |   d } x9 t j |   D]% } t t |  |  t | |   q, Wn  t |   r t | t |   d  } t t j |   |  t j	 |   n t j
 |  |  d S)zCMove file to dstdir. Works with symlinks (including relative ones).r   Nr   )r   r   r   listdir	move_filer
   r	   r   readlinkremoverename)fpathdstdirZdnamefnZdstpathr   r   r   r   7   s    &r   c       
      C   s   t  j |  j } x t j |   D]o \ } } } x] | D]U } t | |  } | |  r8 t | | j |   j d   }	 t j | |	  q8 q8 Wq" Wd S)zMove files (preserving path) that match given pattern.

    move_files('foo/bar/', 'foo/baz/', 'spam/.*\.so$')
    will move foo/bar/a/b/c/spam/file.so to foo/baz/a/b/c/spam/file.so
    r   N)recompilesearchr   walkr
   lstriprenames)
srcZdstpatternmatchrootdirs	filenamesr#   Zspathdpathr   r   r   move_matching_filesF   s    !r1   c          %   C   s7  y t  j |   } Wn< t k
 rQ } z t j d |  |  d SWYd d } ~ Xn X| r | j d k r d | _ t |  } n  | r3t j d |   y( t |  d   } | j	   } Wd QXWn& t
 k
 r t j d |   d SYn Xt |  d	  8 } | j d
 | j d   | j | d d   Wd QXn  d S)zmNormalize file's shebang.

    :param replacement: new shebang command (path to interpreter and options)
    zfix_shebang (%s): %sNz	/usr/bin/z/usr/binzreplacing shebang in %srbzcannot open %sFwbz#! %s
zutf-8r   T)InterpreterZ	from_file	Exceptionlogdebugpathreprinfoopen	readlinesIOErrorerrorwriteencode
writelines)r!   ZreplacementinterpretererrfpZfcontentr   r   r   fix_shebangU   s(    		 rE   c             C   sd   d |  } t  | d t d d } t j t | j j   d d  } | r` t | j   d  Sd S)	zhReturn libpython version file is linked to or None.

    :rtype: tuple
    :returns: Python version
    zreadelf -Wd '%s'stdoutshellTencodingzutf-8r   N)	r   r   SHAREDLIB_REr&   strrF   readVersiongroups)r!   cmdprocessr,   r   r   r   so2pyvers   s
    
$rP   c             C   sG   t  j |   } | rC | j d  d k	 rC d j | j d d   S|  S)a  Remove Python version and platform name from Egg files/dirs.

    >>> clean_egg_name('python_pipeline-0.1.3_py3k-py3.1.egg-info')
    'python_pipeline-0.1.3_py3k.egg-info'
    >>> clean_egg_name('Foo-1.2-py2.7-linux-x86_64.egg-info')
    'Foo-1.2.egg-info'
       N r      )
EGGnPTH_REr,   groupr
   )namer,   r   r   r   clean_egg_name   s    rW   c             C   sr   t  | p g   } xY |  D]Q } t | d d d 4 } x* | D]" } | r> | j | j    q> q> WWd QXq W| S)z#Parse namespace_packages.txt files.rrH   zutf-8N)setr;   addstrip)Zfpathsotherresultr!   rD   liner   r   r   parse_ns   s    $r_   c       
      C   s  t  | t  s t |  } n  t   } x | D] } x | D]~ } t |  j | |  | j d   } t | d  } t |  s q; n  t |  d k r; t j d |  | j	 |  Pq; q; Wq. W| | } x | D] } x| | D]t } t |  j | |  | j d   }	 t |	 d  } t |  r t
 j |  t
 j |	  sSt
 j |	  qSq q Wt d | d | j d   }	 t |	 d  } t |  r t
 j |  t
 j |	  st
 j |	  qq q W| S)z8Remove empty __init__.py files for requested namespaces..z__init__.pyr   z)file not empty, cannot share %s namespaceZdebianzusr/share/pyshared)
isinstancerY   r
   sitedirr   r   r   r6   ZwarningrZ   r   r   r   rmdir)
rB   packageZ
namespacesversionsZkeepnsversionr!   r]   r0   r   r   r   	remove_ns   s:    	$
$rh   c       	      C   sk  i d d 6| d 6| d 6} d } | d k r0 n | d k rU | j  d t d t  n | r t | t  r d } t | d	 d
 d } n  | j d j t j   j	     | j d j |    | j
   | j  d | d |  n  t j d |   t |  |  c } | j   \ } } | o&| j   t d | j d | oHt | d  d | o]t | d   SWd QXd S)a<  Execute external shell commad.

    :param cdw: currennt working directory
    :param env: environment
    :param log_output:
        * opened log file or path to this file, or
        * None if output should be included in the returned dict, or
        * False if output should be redirectored to stdout/stderr
    TrG   cwdenvFNrF   stderrarH   zutf-8z
# command executed on {}z
$ {}
zinvoking: %s
returncode)updater   ra   rJ   r;   r?   formatr   ZnowZ	isoformatflushr6   r7   r   Zcommunicateclosedictrm   )	Zcommandri   rj   Z
log_outputargsrq   rO   rF   rk   r   r   r   execute   s*    
"
rt   c               @   s(   e  Z d  Z d d   Z d d   Z d S)memoizec             C   s   | |  _  i  |  _ d  S)N)funccache)selfrv   r   r   r   __init__   s    	zmemoize.__init__c             O   sH   t  | | f  } | |  j k r= |  j | |   |  j | <n  |  j | S)N)r   rw   rv   )rx   rs   kwargskeyr   r   r   __call__   s    zmemoize.__call__N)__name__
__module____qualname__ry   r|   r   r   r   r   ru      s   ru   c             C   s#  d | } t  |  s d S|  j } t | |  } xt | d d D]} | sE | j d  rg qE n  t j |  } | s t d |   n  | j   } | d r | d j	 d d	  | d <n  | t | | d
  @} | s t
 j d | |  qE n  t | d  }	 |	 s%t d | d   n  x |	 D] }
 |
 j d  }
 | d rkt | d t |
  d  } n( |
 j d  r|
 d d  } n |
 } x | D]y } t |  j | |  |  } t |  d } t  |  st j |  n  t  |  rt j |  n  t j |
 |  qWq,WqE Wd S)zDInstall local files listed in pkg.pyinstall files as public modules.z./debian/%s.pyinstallNrH   zutf-8#zunrecognized line: %smoduler`   r   vrangez.%s.pyinstall: no matching versions for line %sr+   zmissing file(s): %sz/.r   zdebian/   r   )r   implget_requested_versionsr;   
startswith
INSTALL_REr,   
ValueError	groupdictreplacer6   r7   r   r(   r
   r   rb   r   makedirsr   r   )rB   rd   r   srcfpathr   re   r^   detailsmyversfilesr!   Zdstnamerg   Zdstfpathr"   r   r   r   	pyinstall   sJ    
	
	

 r   c             C   sx  d | } t  |  s d S|  j } t | |  } x?t | d d D]+} | sE | j d  rg qE n  t j |  } | s t d | | f   n  | j   } | t | | d  @} | s t	 j
 d | |  n  x | D] }	 |  j | |	  }
 |
 j |  j | |	   x] |
 D]U } t | d	 | d
  } x4 | D], } t |  rWt |  q8t j |  q8WqWq WqE Wd S)z2Remove public modules listed in pkg.pyremove file.z./debian/%s.pyremoveNrH   zutf-8r   zunrecognized line: %s: %sr   z-%s.pyremove: no matching versions for line %sr   r+   )r   r   r   r;   r   	REMOVE_REr,   r   r   r6   r7   Zold_sitedirsappendrb   r   r   r   r   r   )rB   rd   r   r   r   re   r^   r   r   rg   Z	site_dirsZsdirr   r!   r   r   r   pyremove  s2    
		r   )r4   )rL   r   RANGE_PATTERNz
    (?P<pattern>.+?)  # file pattern
    (?:\s+  # optional Python module name:
    (?P<module>[A-Za-z][A-Za-z0-9_.]*)?
    )?
    \s*  # optional version range:
    (?P<vrange>%s)?$
z^
    (?P<pattern>.+?)  # file pattern
    \s*  # optional version range:
    (?P<vrange>%s)?$
).Zloggingr   r$   r   r   pickler   Zshutilr   os.pathr   r   r   r	   r
   r   
subprocessr   r   Z	getLoggerr6   r%   rT   rI   r   r   r   r1   rE   rP   rW   r_   rh   rt   ru   r   r   Zdhpython.interpreterr4   Zdhpython.versionrL   r   r   VERBOSEr   r   r   r   r   r   <module>   s<   .&"+