o
    {ۓa                  	   @   s~  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 de
e dedeedf fdd	Zde
e dee fd
dZG dd deZdedee fddZe dedee fddZdedee fddZedkrddlZe ZedsJ 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 qdS 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.
    N)IOIterator
NamedTupleOptionalTupleffmtreturn.c                 C   s   t || t |S N)structunpackreadcalcsize)r   r    r   6/usr/lib/python3/dist-packages/packaging/_musllinux.py_read_unpacked   s   r   c              	   C   sb  |  d zt| d}W n tjy   Y dS w |dd tdkr$dS |  tdd zdd	d
|d  \}}}W n
 tyE   Y dS w tj| }zt| |\}}}}}}}	W n tjyd   Y dS w t	|	d D ]C}
|  |||
   z|t| |\}}}W n tjy   Y  dS w |dkrqk|  | t
| |d}d|vr 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   Z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   sN   


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&   outputc                 C   sx   dd dd |   D D }t|dk s|d d d dkr d S td	|d
 }|s,d 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"   r/   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&   r,   group)r.   linesmr   r   r   _parse_musl_versionL   s     r;   
executablec              	   C   s   t  '}z
|t| d}W n ty   Y W d   dS w t|}W d   n1 s.w   Y  |s7d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)stderrZuniversal_newlines)
contextlib	ExitStackenter_contextopenOSErrorr%   
subprocessrunPIPEr;   r>   )r<   stackr   Zldprocr   r   r   _get_musl_versionV   s   


rI   archc                 c   sJ    t tj}|du 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#   )rI   sysr<   r   r(   r'   )rJ   Zsys_muslr(   r   r   r   platform_tagsn   s   
	rM   __main__zlinux-z	not linuxzplat:zmusl:ztags: )endz[.-]r#   -r   rK   z
      )#__doc__r?   	functoolsr   r    r6   r   rD   rL   typingr   r   r   r   r   bytesstrr,   r   r%   r&   r;   	lru_cacherI   rM   r)   Z	sysconfigZget_platformZplat
startswithprintr<   subsplittr   r   r   r   <module>   s8    "1

"	