U
    Ç½„b  ã                	   @   st  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 ¡ eee dœdd„ƒZeee dœdd„Zedk�rpddlZe ¡ Ze d¡�st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 )$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  ||  t  |¡¡¡S ©N)ÚstructÚunpackÚreadÚcalcsize)r   r   © r   ú8/tmp/pip-unpacked-wheel-sh3cvm4r/packaging/_musllinux.pyÚ_read_unpacked   s    r   )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 )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é   )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 eed< eed< dS )Ú_MuslVersionÚmajorÚminorN)Ú__name__Ú
__module__Ú__qualname__ÚintÚ__annotations__r   r   r   r   r+   G   s   
r+   )Ú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>M   s      z'_parse_musl_version.<locals>.<listcomp>c                 s   s   | ]}|  ¡ V  qd S r
   )r"   r4   r   r   r   Ú	<genexpr>M   s     z&_parse_musl_version.<locals>.<genexpr>r   r   r   r   zVersion (\d+)\.(\d+)r   )r,   r-   )Ú
splitlinesÚlenÚreÚmatchr+   r1   Úgroup)r3   ÚlinesÚmr   r   r   Ú_parse_musl_versionL   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Úuniversal_newlines)Ú
contextlibÚ	ExitStackÚenter_contextÚopenÚOSErrorr*   Ú
subprocessÚrunÚPIPEr@   rC   )rA   Ústackr   ZldÚprocr   r   r   Ú_get_musl_versionV   s    
rO   )Ú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.
    NéÿÿÿÿZ
musllinux_r$   )rO   ÚsysrA   r   r-   r,   )rP   Zsys_muslr-   r   r   r   Úplatform_tagsn   s
    	
rS   Ú__main__zlinux-z	not linuxzplat:zmusl:ztags:ú )Úendz[.-]r$   ú-r   rQ   z
      )$Ú__doc__rE   Ú	functoolsr   r    r;   r   rJ   rR   Útypingr   r   r   r   r   ÚbytesÚstrr1   r   r*   r+   r@   Ú	lru_cacherO   rS   r.   Ú	sysconfigÚget_platformÚplatÚ
startswithÚAssertionErrorÚprintrA   ÚsubÚsplitÚtr   r   r   r   Ú<module>   s2   1


"