3
ûâde  ã               @   sx  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	m
Z
mZmZmZmZ e
e eeedf dœdd„Ze
e ee dœd	d
„ZG dd„ deƒZeee dœdd„Zejƒ eee dœdd„ƒZeee dœdd„Zedk�rtddlZejƒ Zejdƒ�stdƒ‚edeƒ edeej ƒƒ eddd� x4eej!ddej"d d!ƒd# ƒƒD ]Z#ee#d"d� �q^W dS )$z�PEP 656 support.

This module implements logic to detect if the currently running Python is
linked against musl, and what musl version is used.
é    N)ÚIOÚIteratorÚ
NamedTupleÚOptionalÚTuple.)ÚfÚfmtÚreturnc             C   s   t j|| jt j|ƒƒƒS )N)ÚstructÚunpackÚreadÚcalcsize)r   r   © r   ú?/tmp/pip-build-red6nood/pip/pip/_vendor/packaging/_musllinux.pyÚ_read_unpacked   s    r   )r   r	   c          $   C   sd  | j dƒ yt| dƒ}W n tjk
r.   dS X |dd… tdƒkrHdS | j tjdƒdƒ ydddœ|d  \}}}W n tk
rŠ   dS X tj|Ž }yt| |ƒ\}}}}}}}	W n tjk
rÈ   dS X x”t	|	d ƒD ]„}
| j |||
  ƒ y|t| |ƒƒ\}}}W n tjk
�r   dS X |dk�r,qØ| j |ƒ t
j| j|ƒƒjdƒ}d|k�rZdS |S W dS )záDetect musl libc location by parsing the Python executable.

    Based on: https://gist.github.com/lyssdod/f51579ae8d93c8657a5564aefc2ffbca
    ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
    r   Z16BNé   s   ELFZHHIé   ÚIIIIHHHÚIIIIIIIIÚQQQIHHHÚIIQQQQQQé   é   )r   r   é   ú Úmusl©r   r   r   )r   r   r   ©r   r   r   )r   r   r   )Úseekr   r
   ÚerrorÚtupler   ÚKeyErrorÚoperatorÚ
itemgetterÚrangeÚosÚfsdecoder   Ústrip)r   ÚidentZe_fmtZp_fmtZp_idxZp_getÚ_Ze_phoffZe_phentsizeZe_phnumÚiZp_typeZp_offsetZp_fileszZinterpreterr   r   r   Ú_parse_ld_musl_from_elf   sB    




r+   c               @   s   e Zd ZU eedS )Ú_MuslVersionN)Ú__name__Ú
__module__Ú__qualname__ÚintÚmajorÚminorr   r   r   r   r,   G   s   
r,   )Úoutputr	   c             C   sx   dd„ dd„ | j ƒ D ƒD ƒ}t|ƒdk s<|d d d… dkr@d S tjd	|d
 ƒ}|sXd S tt|jd
ƒƒt|jdƒƒd�S )Nc             S   s   g | ]}|r|‘qS r   r   )Ú.0Únr   r   r   ú
<listcomp>M   s    z'_parse_musl_version.<locals>.<listcomp>c             s   s   | ]}|j ƒ V  qd S )N)r'   )r4   r5   r   r   r   ú	<genexpr>M   s    z&_parse_musl_version.<locals>.<genexpr>r   r   r   r   zVersion (\d+)\.(\d+)r   )r1   r2   )Ú
splitlinesÚlenÚreÚmatchr,   r0   Úgroup)r3   ÚlinesÚmr   r   r   Ú_parse_musl_versionL   s     r?   )Ú
executabler	   c             C   sl   t jƒ �8}y|jt| dƒƒ}W n tk
r2   dS X t|ƒ}W dQ R X |sNdS tj|gtjdd�}t	|j
ƒS )a`  Detect currently-running musl runtime version.

    This is done by checking the specified executable's dynamic linking
    information, and invoking the loader to parse its output for a version
    string. If the loader is musl, the output would be something like::

        musl libc (x86_64)
        Version 1.2.2
        Dynamic Program Loader
    ÚrbNT)ÚstderrÚuniversal_newlines)Ú
contextlibÚ	ExitStackÚenter_contextÚopenÚIOErrorr+   Ú
subprocessÚrunÚPIPEr?   rB   )r@   Ústackr   ÚldÚprocr   r   r   Ú_get_musl_versionV   s    
rO   )Úarchr	   c             c   sL   t tjƒ}|dkrdS x0t|jddƒD ]}d|j› d|› d| › �V  q&W dS )aT  Generate musllinux tags compatible to the current platform.

    :param arch: Should be the part of platform tag after the ``linux_``
        prefix, e.g. ``x86_64``. The ``linux_`` prefix is assumed as a
        prerequisite for the current platform to be musllinux-compatible.

    :returns: An iterator of compatible musllinux tags.
    Nr   Z
musllinux_r)   éÿÿÿÿrQ   )rO   Úsysr@   r$   r2   r1   )rP   Zsys_muslr2   r   r   r   Úplatform_tagsn   s
    	
rS   Ú__main__zlinux-z	not linuxzplat:zmusl:ztags:ú )Úendz[.-]r)   ú-r   z
      rQ   )$Ú__doc__rD   Ú	functoolsr"   r%   r:   r
   rI   rR   Útypingr   r   r   r   r   ÚbytesÚstrr0   r   r+   r,   r?   Ú	lru_cacherO   rS   r-   Ú	sysconfigÚget_platformÚplatÚ
startswithÚAssertionErrorÚprintr@   ÚsubÚsplitÚtr   r   r   r   Ú<module>   s2   1


$