a lj @stdZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z m Z m Z m Z mZe eeeedfdddZe ee edd d ZGd d d e Zee ed ddZeee edddZee edddZedkrpddlZeZedsJdedeedeejedddee dde!d d!d"D]Z"ee"d#dq\dS)$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)IOIterator NamedTupleOptionalTuple.)ffmtreturncCst||t|SN)structunpackreadcalcsize)rrrD/usr/lib/python3.9/site-packages/pip/_vendor/packaging/_musllinux.py_read_unpackedsr)rr c Csh|dzt|d}Wntjy.YdS0|ddtdkrHdS|tddzdd d |d\}}}WntyYdS0tj|}zt||\}}}}}}} WntjyYdS0t | dD]} |||| z|t||\} } } WntjyYdS0| d kr,q|| t | |  d }d |vr\dS|SdS)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 rZ16BNsELFZHHI)ZIIIIHHHZIIIIIIII)rrr)ZQQQIHHHZIIQQQQQQ)r)rrmusl)seekrr errortuplerKeyErroroperator itemgetterrangeosfsdecoder strip)ridentZe_fmtZp_fmtZp_idxZp_get_Ze_phoffZ e_phentsizeZe_phnumiZp_typeZp_offsetZp_fileszZ interpreterrrr_parse_ld_musl_from_elfsF       r&c@seZdZUeed<eed<dS) _MuslVersionmajorminorN)__name__ __module__ __qualname__int__annotations__rrrrr'Gs r')outputr cCsxdddd|DD}t|dks<|ddddkr@dStd |d }|sXdStt|d t|dd S) NcSsg|] }|r|qSrr.0nrrr Mz'_parse_musl_version..css|]}|VqdSr )r"r0rrr Mr4z&_parse_musl_version..rrrrzVersion (\d+)\.(\d+)r)r(r)) splitlineslenrematchr'r-group)r/linesmrrr_parse_musl_versionLs r=) executabler c CstN}z|t|d}Wn ty>YWddS0t|}Wdn1s\0Y|sndStj|gtjdd}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)stderrZuniversal_newlines) contextlib ExitStack enter_contextopenIOErrorr& subprocessrunPIPEr=r@)r>stackrZldprocrrr_get_musl_versionVs  &rK)archr ccsHttj}|durdSt|jddD]}d|jd|d|Vq$dS)aTGenerate 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$)rKsysr>rr)r()rLZsys_muslr)rrr platform_tagsns rO__main__zlinux-z not linuxzplat:zmusl:ztags: )endz[.-]r$-rrMz )#__doc__rA functoolsrr r8r rFrNtypingrrrrrbytesstrr-rr&r'r= lru_cacherKrOr*Z sysconfigZ get_platformZplat startswithprintr>subsplittrrrrs21    "