U kf@s*dZddlmZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl mZmZmZmZddlmZd d d d d ZejdddddZeed ddddZdddddZd d dddZd d ddd Zd!d d"d#d$Zd%dd&d'd(Zd)d*d+d,d-Zd d d.d/d0d1Z dS)2z2 Tools for converting old- to new-style metadata. ) annotationsN)Message)Parser) GeneratorIterableIteratorLiteral) Requirementstrzbool | Literal[''])r returncCs|o|d S)N#) startswith)r r>> list(yield_lines('')) [] >>> list(yield_lines(['foo', 'bar'])) ['foo', 'bar'] >>> list(yield_lines('foo\nbar')) ['foo', 'bar'] >>> list(yield_lines('\nfoo\n#bar\nbaz #comment')) ['foo', 'baz #comment'] >>> list(yield_lines(['foo\nbar', 'baz', 'bing\n\n\n'])) ['foo', 'bar', 'baz', 'bing'] ) itertoolschain from_iterablemap yield_lines)rrrrrsr)textr cCsttttj|SN)filterrrr strip splitlines)rrrr_)srzstr | Iterator[str]z3Generator[tuple[str | None, list[str]], None, None])sr ccsvd}g}t|D]V}|dr\|drP|s0|r:||fV|dd}g}qftd|q||q||fVdS)arSplit a string or iterable thereof into (section, content) pairs Each ``section`` is a stripped version of the section header ("[section]") and each ``content`` is a list of stripped lines excluding blank lines and comment-only lines. If there are any such lines before the first section header, they're returned in a first ``section`` of ``None``. N[]r zInvalid section heading)rrendswithr ValueErrorappend)rsectioncontentlinerrrsplit_sections.s       r()extrar cCstdd|S)zConvert an arbitrary string to a standard 'extra' name Any runs of non-alphanumeric characters are replaced with a single '_', and the result is always lowercased. z[^A-Za-z0-9.-]+r)resublower)r)rrr safe_extraIsr-)namer cCstdd|S)zConvert an arbitrary string to a standard distribution name Any runs of non-alphanumeric/. characters are replaced with a single '-'. z[^A-Za-z0-9.]+-)r*r+)r.rrr safe_nameQsr0r ) requirementr cCsP|jrd|jSg}|jD]}||j|jq|rHddt|SdSdS)zFReturn the version specifier for a requirement in PEP 345/566 fashion.z @  ,N)url specifierr$operatorversionjoinsorted)r1Z requires_distspecrrrrequires_to_requires_distXs  r<z list[str]) requirementsr ccs\|D]R}t|}t|}dtdd|jD}|rBd|d}t|j||VqdS)z=Yield Requires-Dist: strings for parsed requirements strings.r3css|]}t|VqdSr)r-).0errr lsz'convert_requirements..rr N)r r<r9r:extrasr0r.)r=reqparsed_requirementr;rArrrconvert_requirementsgs rDzdict[str | None, list[str]]zIterator[tuple[str, str]])extras_requirer ccs|D]\}}d}|pd}d|kr4|dd\}}t|}|rjd|fV|rZd|d}|d|d7}|rvd |}t|D]}tt||}d |fVq~qd S) a, Convert requirements from a setup()-style dictionary to ('Requires-Dist', 'requirement') and ('Provides-Extra', 'extra') tuples. extras_require is a dictionary of {extra: [requirements]} as passed to setup(), using the empty extra {'': [requirements]} to hold install_requires. r4:r Provides-Extra(z) and z extra == ''z ; Requires-DistN)itemssplitr-rDr r )rEr)depends conditionZnew_reqZ canonical_reqrrrgenerate_requirementsss    rOr) egg_info_path pkginfo_pathr c Cs t|dd}t|}W5QRX|dd|d=|d=tj|d}tj|rt|dd}|}W5QRXt t |dd d }|D]6\}} t || iD] \} } | | f| kr| || <qq|d } | r|d  } d | d td | ddd f}|||d =|S)zN Convert .egg-info directory with PKG-INFO to the Metadata 2.1 format zutf-8)encodingzMetadata-Versionz2.1rGrJz requires.txtcSs |dp dS)Nrr4r)xrrrz%pkginfo_to_metadata..)key Description rr N)openrparsereplace_headerospathr9existsreadr:r(rOrKrlstriptextwrapdedent set_payload)rPrQheaderspkg_infoZ requires_pathZ requires_filerequiresZparsed_requirementsr)reqsrVvalue descriptionZdescription_linesZdedented_descriptionrrrpkginfo_to_metadatas4       rj)!__doc__ __future__r functoolsros.pathr\r*ra email.messager email.parserrtypingrrrrZvendored.packaging.requirementsr rsingledispatchrregisterr rr(r-r0r<rDrOrjrrrrs,