U
    .c                  	   @  sV  d Z ddlm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 ddddd	d
ZdddddZG dd deZdddddZe dddddZdddddZedkrRddlZe Zedstdede ed ee
j ed!d"d# eed$d%ed&d'd( D ]Z ee d)d# q>dS )*zPEP 656 support.

This module implements logic to detect if the currently running Python is
linked against musl, and what musl version is used.
    )annotationsN)IOIterator
NamedTuplez	IO[bytes]strztuple[int, ...])ffmtreturnc                 C  s   t || t |S N)structunpackreadcalcsize)r   r    r   G/tmp/pip-unpacked-wheel-vud_xk1z/wheel/vendored/packaging/_musllinux.py_read_unpacked   s    r   z
str | None)r   r	   c              	   C  sp  |  d zt| d}W n tjk
r0   Y dS X |dd tdkrJdS |  tdd zdd	d
|d  \}}}W n tk
r   Y dS X tj| }zt| |\}}}}}}}	W n tjk
r   Y dS X t	|	d D ]}
|  |||
   z|t| |\}}}W n tjk
r&   Y  dS X |dkr4q|  | t
| |d}d|krd dS |  S dS )zDetect 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   )ZIIIIHHHZIIIIIIII)r   r   r   )ZQQQIHHHZIIQQQQQQ)r         )r   r       musl)seekr   r   errortupler   KeyErroroperator
itemgetterrangeosfsdecoder   strip)r   identZe_fmtZp_fmtZp_idxZp_get_e_phoffe_phentsizee_phnumiZp_typeZp_offsetZp_fileszinterpreterr   r   r   _parse_ld_musl_from_elf   sF    





r*   c                   @  s   e Zd ZU ded< ded< dS )_MuslVersionintmajorminorN)__name__
__module____qualname____annotations__r   r   r   r   r+   I   s   
r+   z_MuslVersion | None)outputr	   c                 C  sx   dd dd |   D D }t|dk s<|d d d dkr@d S td	|d
 }|sXd S tt|d
t|ddS )Nc                 S  s   g | ]}|r|qS r   r   .0nr   r   r   
<listcomp>O   s      z'_parse_musl_version.<locals>.<listcomp>c                 s  s   | ]}|  V  qd S r
   )r"   r4   r   r   r   	<genexpr>O   s     z&_parse_musl_version.<locals>.<genexpr>r   r   r   r   zVersion (\d+)\.(\d+)r   )r-   r.   )
splitlineslenrematchr+   r,   group)r3   linesmr   r   r   _parse_musl_versionN   s     r@   )
executabler	   c              	   C  sx   t  D}z|t| d}W n  tk
r>   Y W 5 Q R  dS X t|}W 5 Q R X |sZd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text)
contextlib	ExitStackenter_contextopenOSErrorr*   
subprocessrunPIPEr@   rC   )rA   stackr   Zldprocr   r   r   _get_musl_versionX   s    
rO   zIterator[str])archr	   c                 c  sH   t tj}|dkrdS t|jddD ]}d|j d| d|  V  q$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.
    NZ
musllinux_r$   )rO   sysrA   r   r.   r-   )rP   Zsys_muslr.   r   r   r   platform_tagsp   s
    	
rS   __main__zlinux-z	not linuxzplat:zmusl:ztags: )endz[.-]r$   -r   rQ   z
      )!__doc__
__future__r   rE   	functoolsr   r    r;   r   rJ   rR   typingr   r   r   r   r*   r+   r@   	lru_cacherO   rS   r/   	sysconfigget_platformplat
startswithAssertionErrorprintrA   subsplittr   r   r   r   <module>   s4   1


"