
U](-                 @   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 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   so   |  j  d  } | j  d  } x, | rL | d | d k rL | 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  |   rU t |   d } x6 t j |   D]% } t t |  |  t | |   q, Wt |   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 } xt t j |   D]c \ } } } xQ | D]I } t | |  } | |  r8 t | t | |    }	 t j | |	  q8 Wq" Wd S)zMove files (preserving path) that match given pattern.

    move_matching_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
    N)recompilesearchr   walkr
   r   renames)
srcZdstpatternmatchrootdirs	filenamesr#   Zspathdpathr   r   r   move_matching_filesF   s    r0   c          &   C   s3  y t  j |   } Wn< t k
 rQ } z t j d |  |  d SWYd d } ~ Xn X| r} | j d k r} d | _ t |  } | r/t j d |   y) t |  d   } | j	   } Wd QRXWn& t
 k
 r t j d |   d SYn Xt |  d	  8 } | j d
 | j d   | j | d d   Wd QRXd 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(    		rD   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&   strrE   readVersiongroups)r!   cmdprocessr+   r   r   r   so2pyvers   s
    
$rO   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    rV   c             C   sp   t  | p g   } xW |  D]O } t | d d d 1 } x' | D] } | r> | j | j    q> WWd QRXq W| S)z#Parse namespace_packages.txt files.rrG   zutf-8N)setr:   addstrip)Zfpathsotherresultr!   rC   liner   r   r   parse_ns   s    "r^   c       
      C   s  t  | t  s t |  } t   } x | D] } x | D]x } t |  j | |  | j d   } t | d  } t |  s q8 t |  d k r8 t j d |  | j	 |  Pq8 Wq+ W| | } x | D] } xv | D]n } t |  j | |  | j d   }	 t |	 d  } t |  r t
 j |  t
 j |	  s t
 j |	  q Wt d | d | j d   }	 t |	 d  } t |  r t
 j |  t
 j |	  s t
 j |	  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)
isinstancerX   r
   sitedirr   r   r   r5   ZwarningrY   r   r   r   rmdir)
rA   packageZ
namespacesversionsZkeepnsversionr!   r\   r/   r   r   r   	remove_ns   s:    	$	
$rg   Tc       
      C   sc  d | d | d | i } d } | d k r- n | d k rR | j  d t d t  n | r t | t  r d } t | d	 d
 d } | j d j t j   j	     | j d j |    | j
   | j  d | d |  t j d |   t |  |  c } | j   \ } }	 | o| j   t d | j d | o?t | d  d |	 oTt |	 d   SWd QRXd 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
    rF   cwdenvFNrE   stderrTarG   zutf-8z
# command executed on {}z
$ {}
zinvoking: %s
returncode)updater   r`   rI   r:   r>   formatr   ZnowZ	isoformatflushr5   r6   r   Zcommunicateclosedictrl   )
Zcommandrh   ri   Z
log_outputrF   argsrp   rN   rE   rj   r   r   r   execute   s*    
"
rs   c               @   s(   e  Z d  Z d d   Z d d   Z d S)memoizec             C   s   | |  _  i  |  _ d  S)N)funccache)selfru   r   r   r   __init__   s    	zmemoize.__init__c             O   sE   t  | | f  } | |  j k r: |  j | |   |  j | <|  j | S)N)r   rv   ru   )rw   rr   kwargskeyr   r   r   __call__   s    zmemoize.__call__N)__name__
__module____qualname__rx   r{   r   r   r   r   rt      s   rt   c             C   s  d | } t  |  s d S|  j } t | |  } xt | d d D]} | sE | j d  rd qE t j |  } | s t d |   | j   } | d r | d j	 d d	  | d <| t | | d
  @} | s t
 j d | |  qE t | d  }	 |	 st d | d   x |	 D] }
 |
 j d  }
 | d r\t | d t |
  d  } n( |
 j d  r~|
 d d  } n |
 } x{ | D]s } t |  j | |  |  } t |  d } t  |  st j |  t  |  rt j |  t j |
 |  qWqWqE Wd S)zDInstall local files listed in pkg.pyinstall files as public modules.z./debian/%s.pyinstallNrG   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replacer5   r6   r   lstripr
   r   ra   r   makedirsr   r   )rA   rc   r   srcfpathr   rd   r]   detailsmyversfilesr!   Zdstnamerf   Zdstfpathr"   r   r   r   	pyinstall   sJ    
	
	

 r   c             C   so  d | } t  |  s d S|  j } t | |  } x6t | d d D]"} | sE | j d  rd qE t j |  } | s t d | | f   | j   } | t | | d  @} | s t	 j
 d | |  x | D] }	 |  j | |	  }
 |
 j |  j | |	   x] |
 D]U } t | d	 | d
  } x4 | D], } t |  rNt |  q/t j |  q/Wq
Wq WqE Wd S)z2Remove public modules listed in pkg.pyremove file.z./debian/%s.pyremoveNrG   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   r5   r6   Zold_sitedirsappendra   r   r   r   r   r   )rA   rc   r   r   r   rd   r]   r   r   rf   Z	site_dirsZsdirr   r!   r   r   r   pyremove  s2    
		
r   )r3   )rK   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	getLoggerr5   r%   rS   rH   r   r   r   r0   rD   rO   rV   r^   rg   rs   rt   r   r   Zdhpython.interpreterr3   Zdhpython.versionrK   r   r   VERBOSEr   r   r   r   r   r   <module>   s<   .&"+