hyb
2026-01-30 7657e1b2fa251a2ea372710ad75cb395a3c0e374
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
Ë
ñúh!Uãó0—ddlmZddlZddlZddlZddlZddlZddlZddlZ    ddl
m Z ddl m Z ddlmZmZmZddlmZddlmZddlmZdd    lmZmZmZmZdd
lmZmZerdd l m!Z!ejDe#«Z$d Z%e d ¬«Gd„d««Z&e d ¬«Gd„d««Z'd d„Z(d!d„Z)d!d„Z*ejVdejX«Z-d"d„Z.d#d„Z/d$d„Z0ejbGd„d««Z2Gd„de«Z3d%d„Z4ejjd&d„«Z6y)'é)Ú annotationsN)ÚMapping)Ú    dataclass)Ú TYPE_CHECKINGÚAnyÚ
NamedTuple)Ú
deprecated)ÚWHEEL_EXTENSION)ÚHashes)ÚpairwiseÚredact_auth_from_urlÚsplit_auth_from_netlocÚsplitext)Ú path_to_urlÚ url_to_path)Ú IndexContent)Úsha512Úsha384Úsha256Úsha224Úsha1Úmd5T)Úfrozencóæ—eZdZUdZded<ded<ej djdjd„e    D««¬««Z
dd    „Z e e jdd
„««Zdd „Zdd „Zdd „Zy)ÚLinkHashaµLinks to content may have embedded hash values. This class parses those.
 
    `name` must be any member of `_SUPPORTED_HASHES`.
 
    This class can be converted to and from `ArchiveInfo`. While ArchiveInfo intends to
    be JSON-serializable to conform to PEP 610, this class contains the logic for
    parsing a hash name and value for correctness, and then checking whether that hash
    conforms to a schema with `.is_hash_allowed()`.ÚstrÚnameÚvaluez[#&]({choices})=([^&]*)ú|c#óFK—|]}tj|«–—Œy­w©N)ÚreÚescape)Ú.0Ú    hash_names  úLH:\Change_password\venv_build\Lib\site-packages\pip/_internal/models/link.pyú    <genexpr>zLinkHash.<genexpr>=sèø€ÒU°iœRŸY™Y y×1ÑUùs‚!)Úchoicescó,—|jtvsJ‚yr!)rÚ_SUPPORTED_HASHES©Úselfs r&Ú __post_init__zLinkHash.__post_init__As€Øy‰yÔ-Ñ-Ð-Ñ-ócóx—|jj|«}|€y|j«\}}|||¬«S)zGSearch a string for a checksum algorithm name and encoded output value.N©rr)Ú_hash_url_fragment_reÚsearchÚgroups)ÚclsÚurlÚmatchrrs     r&Úfind_hash_url_fragmentzLinkHash.find_hash_url_fragmentDs>€ð×)Ñ)×0Ñ0°Ó5ˆØ ˆ=ØØ—l‘l“n‰ ˆˆeÙ˜ EÔ*Ð*r.có2—|j|jiSr!r0r+s r&Úas_dictzLinkHash.as_dictNs€Ø—    ‘    ˜4Ÿ:™:Ð&Ð&r.cóF—t|j|jgi«S)z@Return a Hashes instance which checks only for the current hash.)r rrr+s r&Ú    as_hasheszLinkHash.as_hashesQs€ät—y‘y 4§:¡: ,Ð/Ó0Ð0r.cóV—|€y|j|j|j¬«S)zI
        Return True if the current hash is allowed by `hashes`.
        F)Ú
hex_digest)Úis_hash_allowedrr©r,Úhashess  r&r>zLinkHash.is_hash_allowedUs*€ð ˆ>ØØ×%Ñ% d§i¡i¸D¿J¹JÐ%ÓGÐGr.N©ÚreturnÚNone)r5rrBzLinkHash | None)rBúdict[str, str]©rBr ©r@z Hashes | NonerBÚbool)Ú__name__Ú
__module__Ú __qualname__Ú__doc__Ú__annotations__r"ÚcompileÚformatÚjoinr*r1r-Ú classmethodÚ    functoolsÚcacher7r9r;r>©r.r&rr(s…ñ7ð ƒIØ ƒJà&˜BŸJ™Jð     #×)Ñ)Ø—H‘HÑUÐCTÔUÓUð    *ó    
ó     Ðó.ð؇__ò+óóð+ó'ó1ôHr.rcó$—eZdZUdZded<dd„Zy)Ú MetadataFilezFInformation about a core metadata file associated with a distribution.údict[str, str] | Noner@cóZ—|jtd„|jD««sJ‚yy)Nc3ó,K—|] }|tv–—Œy­wr!)r*)r$rs  r&r'z-MetadataFile.__post_init__.<locals>.<genexpr>fsèø€ÒI°TtÔ0Ô0ÑIùs‚)r@Úallr+s r&r-zMetadataFile.__post_init__ds)€Ø ;‰;Ð "ÜÑI¸T¿[¹[ÔIÔIÐ IÑIð #r.NrA)rHrIrJrKrLr-rSr.r&rUrU^s…áPà !Ó!ôJr.rUcóv—|€y|j«Dcic]\}}|tvsŒ||“Œ}}}|sy|Scc}}wr!)Úitemsr*)r@ÚnÚvs   r&Úsupported_hashesr^isF€ð€~ØØ%Ÿ|™|›~× H‘tq˜!°Ô6GÒ1Gˆa‰dÐ H€FÑ HÙ ØØ €MùóIs—5¨5cóz—tjjtjj|««S)zP
    Clean a "part" of a URL path (i.e. after splitting on "@" characters).
    )ÚurllibÚparseÚquoteÚunquote)Úparts r&Ú_clean_url_path_partrets(€ô
<‰<× Ñ œfŸl™l×2Ñ2°4Ó8Ó 9Ð9r.có—tjjtjj|««}|j    d«r|j d«}|S)z•
    Clean the first part of a URL path that corresponds to a local
    filesystem path (i.e. the first part after splitting on "@" characters).
    z///z//)r`ÚrequestÚ pathname2urlÚ url2pathnameÚ
startswithÚ removeprefix)rdÚrets  r&Ú_clean_file_url_pathrm|sH€ô .‰.×
%¤f§n¡n×&AÑ&AÀ$Ó&GÓ
H€CØ
‡~~eÔà×јtÓ$ˆØ €Jr.z(@|%2F)có,—|rt}nt}tj|«}g}t    t j |dg««D];\}}|j||««|j|j««Œ=dj|«S)z*
    Clean the path portion of a URL.
    Ú)
rmreÚ_reserved_chars_reÚsplitr Ú    itertoolsÚchainÚappendÚupperrO)ÚpathÚ is_local_pathÚ
clean_funcÚpartsÚ cleaned_partsÚto_cleanÚreserveds       r&Ú_clean_url_pathr}‘s‡€ñÜ)‰
ä)ˆ
ô × $Ñ $ TÓ *€Eà€MÜ&¤y§¡°u¸r¸dÓ'CÓDò/ш(Ø×Ñ™Z¨Ó1Ô2à×јXŸ^™^Ó-Õ.ð/ð
7‰7=Ó !Ð!r.có—tjj|«}|j }t    |j
|¬«}tjj |jd|¬««}|j|ddz}|S)z§
    Make sure a link is fully quoted.
    For example, if ' ' occurs in the URL, it will be replaced with "%20",
    and without double-quoting other characters.
    )rwÚfile)ÚschemervéN)    r`raÚurlsplitÚnetlocr}rvÚ
urlunsplitÚ_replacer€)r5Úresultrwrvrls     r&Ú_ensure_quoted_urlr‡§sp€ô\‰\× "Ñ " 3Ó '€FàŸ ™ Ð%€MÜ ˜6Ÿ;™;°mÔ D€Dô ,‰,×
! &§/¡/¸Àd /Ó"KÓ
L€CØ
-‰-˜#˜a˜b˜'Ñ
!€CØ €Jr.cóh—|jd«r|Stjj||«S)zk
    A faster implementation of urllib.parse.urljoin with a shortcut
    for absolute http/https URLs.
    )zhttps://zhttp://)rjr`raÚurljoin)Úbase_urlr5s  r&Ú_absolute_link_urlr‹ºs-€ð
 ‡~~Ð-Ô.؈
ä|‰|×#Ñ# H¨cÓ2Ð2r.cóª—eZdZdZgd¢Z                        d'                                                            d(d„Ze                        d)d„«Ze                                d*d„«Zd+d„Z    d+d„Z
d,d    „Z d-d
„Z d-d „Z ed+d „«Zed+d „«Zed+d„«Zed+d„«Zed+d„«Zed+d„«Zed+d„«Zd.d„Zed+d„«Zed+d„«Zej4d«Zej4dej8«Zd/d„Zej4d«Zed/d„«Z d0d„Z!d1d„Z"ed/d„«Z#ed/d„«Z$ed+d„«Z%ed2d „«Z&d2d!„Z'ed2d"„«Z(ed2d#„«Z)ed2d$„«Z*ed2d%„«Z+d3d&„Z,y)4ÚLinkz:Represents a parsed link from a Package Index's simple URL)
Ú _parsed_urlÚ_urlÚ_pathÚ_hashesÚ
comes_fromÚrequires_pythonÚ yanked_reasonÚmetadata_file_dataÚcache_link_parsingÚ egg_fragmentNcóö—|jd«r t|«}tjj    |«|_||_tjj|j
j«|_    tj|«}|€in|j«}    |€|    |_ n i|¥|    ¥|_ ||_|r|nd|_||_||_||_|j'«|_y)aÔ
        :param url: url of the resource pointed to (href of the link)
        :param comes_from: instance of IndexContent where the link was found,
            or string.
        :param requires_python: String containing the `Requires-Python`
            metadata field, specified in PEP 345. This may be specified by
            a data-requires-python attribute in the HTML link tag, as
            described in PEP 503.
        :param yanked_reason: the reason the file has been yanked, if the
            file has been yanked, or None if the file hasn't been yanked.
            This is the value of the "data-yanked" attribute, if present, in
            a simple repository HTML link. If the file has been yanked but
            no reason was provided, this should be the empty string. See
            PEP 592 for more information and the specification.
        :param metadata_file_data: the metadata attached to the file, or None if
            no such metadata is provided. This argument, if not None, indicates
            that a separate metadata file exists, and also optionally supplies
            hashes for that file.
        :param cache_link_parsing: A flag that is used elsewhere to determine
            whether resources retrieved from this link should be cached. PyPI
            URLs should generally have this set to False, for example.
        :param hashes: A mapping of hash names to digests to allow us to
            determine the validity of a download.
        z\\N)rjrr`rar‚rŽrrcrvrrr7r9r‘r’r“r”r•r–Ú _egg_fragmentr—)
r,r5r’r“r”r•r–r@Ú    link_hashÚhashes_from_links
          r&Ú__init__z Link.__init__Ös݀ðP >‰>˜&Ô !ܘcÓ"ˆCä!Ÿ<™<×0Ñ0°Ó5ˆÔðˆŒ    ä—\‘\×)Ñ)¨$×*:Ñ*:×*?Ñ*?Ó@ˆŒ
ä×3Ñ3°CÓ8ˆ    Ø!*Ð!2™2¸    ×8IÑ8IÓ8KÐØ ˆ>Ø+ˆDLà9˜fÐ9Ð(8Ð9ˆDŒLà$ˆŒÙ2A™ÀtˆÔØ*ˆÔØ"4ˆÔà"4ˆÔØ ×.Ñ.Ó0ˆÕr.có¼—|jd«}|€ytt||««}|jd«}|jd«}|jdi«}|jd«}|€|jd«}t|t«rt t |««}    n|r t d«}    nd}    |rt|t«sd}n|sd}|||||||    ¬    «S)
zZ
        Convert an pypi json document from a simple repository page into a Link.
        r5Nzrequires-pythonÚyankedr@z core-metadatazdist-info-metadataro)r’r“r”r@r•)Úgetr‡r‹Ú
isinstanceÚdictrUr^r)
r4Ú    file_dataÚpage_urlÚfile_urlr5Ú    pyrequirer”r@Ú metadata_infor•s
          r&Ú    from_jsonzLink.from_jsonsì€ð—=‘= Ó'ˆØ Ð Øä Ô!3°H¸hÓ!GÓHˆØ—M‘MÐ"3Ó4ˆ    Ø!Ÿ ™  hÓ/ˆ Ø—‘˜x¨Ó,ˆð"Ÿ ™  oÓ6ˆ Ø Ð  Ø%ŸM™MÐ*>Ó?ˆMô m¤TÔ *ä!-Ô.>¸}Ó.MÓ!NÑ Ù ä!-¨dÓ!3Ñ ð"&Ð ñ ¤¨M¼3Ô!?؉MáØ ˆMáØ ØØ%Ø'ØØ1ô 
ð    
r.cóÊ—|jd«}|sytt||««}|jd«}|jd«}|jd«}|€|jd«}|dk(r td«}    nW|€d}    nR|j    d«\}
} } | dk(rtt |
| i««}    n!t jd    |«td«}    ||||||    ¬
«S) z_
        Convert an anchor element's attributes in a simple repository page to a Link.
        ÚhrefNzdata-requires-pythonz data-yankedzdata-core-metadatazdata-dist-info-metadataÚtrueú=z8Index returned invalid data-dist-info-metadata value: %s)r’r“r”r•)rŸr‡r‹rUÚ    partitionr^ÚloggerÚdebug) r4Úanchor_attribsr£rŠr©r5r¥r”r¦r•ÚhashnameÚsepÚhashvals              r&Ú from_elementzLink.from_elementJs €ð×!Ñ! &Ó)ˆÙØä Ô!3°H¸dÓ!CÓDˆØ"×&Ñ&Ð'=Ó>ˆ    Ø&×*Ñ*¨=Ó9ˆ ð'×*Ñ*Ð+?Ó@ˆ Ø Ð  Ø*×.Ñ.Ð/HÓIˆMð ˜FÒ "ä!-¨dÓ!3Ñ Ø Ð "à!%Ñ ð&3×%<Ñ%<¸SÓ%AÑ "ˆHc˜7ؐcŠzÜ%1Ô2BÀHÈgÐCVÓ2WÓ%XÑ"ô— ‘ ØNØ!ôô&2°$Ó%7Ð"áØ ØØ%Ø'Ø1ô 
ð    
r.có¬—|jrd|j›d}nd}|jr|j›d|j›d|›S|jS)Nz (requires-python:ú)roz (from )r“r’Ú redacted_url)r,Úrps  r&Ú__str__z Link.__str__~s[€Ø × Ò Ø% d×&:Ñ&:Ð%;¸1Ð=‰BàˆBØ ?Š?Ø×'Ñ'Ð(¨°·±Ð/@ÀÀ"ÀÐFÐ Fà×$Ñ$Ð $r.có—d|›dS)Nz<Link ú>rSr+s r&Ú__repr__z Link.__repr__ˆs€Ø˜v˜QÐÐr.có,—t|j«Sr!)Úhashr5r+s r&Ú__hash__z Link.__hash__‹s€ÜD—H‘H‹~Ðr.có`—t|t«stS|j|jk(Sr!©r rÚNotImplementedr5©r,Úothers  r&Ú__eq__z Link.__eq__Žs%€Ü˜%¤Ô&Ü!Ð !؏x‰x˜5Ÿ9™9Ñ$Ð$r.có`—t|t«stS|j|jkSr!rÀrÂs  r&Ú__lt__z Link.__lt__“s%€Ü˜%¤Ô&Ü!Ð !؏x‰x˜%Ÿ)™)Ñ#Ð#r.có—|jSr!)rr+s r&r5zLink.url˜s €ày‰yÐr.có,—t|j«Sr!)r r5r+s r&r¶zLink.redacted_urlœs€ä# D§H¡HÓ-Ð-r.có
—|jjd«}tj|«}|st    |j
«\}}|St jj|«}|sJd|j›d«‚|S)Nú/zURL z produced no filename)
rvÚrstripÚ    posixpathÚbasenamerrƒr`rarcr)r,rvrrƒÚ    user_passs     r&Úfilenamez Link.filename sw€ày‰y×Ñ Ó$ˆÜ×!Ñ! $Ó'ˆÙô!7°t·{±{Ó CÑ ˆFI؈Mä|‰|×#Ñ# DÓ)ˆÙÐ>t˜DŸI™I˜=Ð(=Ð>Ó>ˆt؈ r.có,—t|j«Sr!)rr5r+s r&Ú    file_pathzLink.file_path®s€ä˜4Ÿ8™8Ó$Ð$r.có.—|jjSr!)rŽr€r+s r&r€z Link.scheme²s€à×Ñ×&Ñ&Ð&r.có.—|jjS)z4
        This can contain auth information.
        )rŽrƒr+s r&rƒz Link.netloc¶s€ð
×Ñ×&Ñ&Ð&r.có—|jSr!)rr+s r&rvz    Link.path½s €àz‰zÐr.cóp—ttj|jj    d«««S)NrÊ)rrÌrÍrvrËr+s r&rz Link.splitextÁs'€Üœ    ×*Ñ*¨4¯9©9×+;Ñ+;¸CÓ+@ÓAÓBÐBr.có(—|j«dS©Né)rr+s r&ÚextzLink.extÄs€à}‰}‹˜qÑ!Ð!r.cón—|j\}}}}}tjj||||df«S)Nro)rŽr`rar„)r,r€rƒrvÚqueryÚfragments      r&Úurl_without_fragmentzLink.url_without_fragmentÈs8€à04×0@Ñ0@Ñ-ˆ˜˜e X܏|‰|×&Ñ&¨°¸¸eÀRÐ'HÓIÐIr.z[#&]egg=([^&]*)z)^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$cóҗ|jj|j«}|sy|jd«}|jj |«st |›dddd¬«|S)NrØz2 contains an egg fragment with a non-PEP 508 name.z8to use the req @ url syntax, and remove the egg fragmentz25.3ie3)ÚreasonÚ replacementÚgone_inÚissue)Ú_egg_fragment_rer2rÚgroupÚ_project_name_rer6r    )r,r6Ú project_names   r&r™zLink._egg_fragmentÔsi€Ø×%Ñ%×,Ñ,¨T¯Y©YÓ7ˆÙØð—{‘{ 1“~ˆ Ø×$Ñ$×*Ñ*¨<Ô8Ü Ø˜ÐQÐRØVØØõ     ðÐr.z[#&]subdirectory=([^&]*)cót—|jj|j«}|sy|jd«Sr×)Ú_subdirectory_fragment_rer2rrä)r,r6s  r&Úsubdirectory_fragmentzLink.subdirectory_fragmentès0€à×.Ñ.×5Ñ5°d·i±iÓ@ˆÙØØ{‰{˜1‹~Ðr.có¾—|j€y|j›d}|jj€ t|«St||jj¬«S)z<Return a link to the associated core metadata file (if any).Nz    .metadata)r@)r•rÝr@r)r,Ú metadata_urls  r&Ú metadata_linkzLink.metadata_linkïsZ€à × "Ñ "Ð *ØØ×3Ñ3Ð4°IÐ>ˆ Ø × "Ñ "× )Ñ )Ð 1ܘ Ó%Ð %ܐL¨×)@Ñ)@×)GÑ)GÔHÐHr.có~—t|jj«Dcic]    \}}||g“Œ c}}«Scc}}wr!)r r‘r[)r,Úkr]s   r&r;zLink.as_hashesøs2€Ü¨$¯,©,×*<Ñ*<Ó*>×?¡$ ! Qq˜1˜#‘vÓ?Ó@Ð@ùÓ?s£9
có\—tt|jj««d«Sr!)ÚnextÚiterr‘Úvaluesr+s r&r½z    Link.hashûs!€ä”D˜Ÿ™×,Ñ,Ó.Ó/°Ó6Ð6r.có@—tt|j«d«Sr!)rðrñr‘r+s r&r%zLink.hash_nameÿs€ä”D˜Ÿ™Ó&¨Ó-Ð-r.cóŒ—tj|jjdd«djdd«d«S)Nú#rØrú?)rÌrÍrrqr+s r&Úshow_urlz Link.show_urls9€ä×!Ñ! $§)¡)§/¡/°#°qÓ"9¸!Ñ"<×"BÑ"BÀ3ÈÓ"JÈ1Ñ"MÓNÐNr.có —|jdk(S)Nr)r€r+s r&Úis_filez Link.is_files€à{‰{˜fÑ$Ð$r.cóp—|jxr)tjj|j«Sr!)rùÚosrvÚisdirrÑr+s r&Úis_existing_dirzLink.is_existing_dir s"€Ø|‰|Ò=¤§¡§ ¡ ¨d¯n©nÓ =Ð=r.có(—|jtk(Sr!)rÙr
r+s r&Úis_wheelz Link.is_wheels€àx‰xœ?Ñ*Ð*r.có>—ddlm}|j|jvS)Nr)Úvcs)Úpip._internal.vcsrr€Ú all_schemes)r,rs  r&Úis_vcsz Link.is_vcss€å)à{‰{˜cŸo™oÐ-Ð-r.có—|jduSr!)r”r+s r&Ú    is_yankedzLink.is_yankeds€à×!Ñ!¨Ð-Ð-r.có,—t|j«Sr!)rGr‘r+s r&Úhas_hashz Link.has_hashs€äD—L‘LÓ!Ð!r.cób‡—‰€ytˆfd„|jj«D««S)zS
        Return True if the link has a hash and it is allowed by `hashes`.
        Fc3óH•K—|]\}}‰j||«–—Œy­wr!)r>)r$rîr]r@s   €r&r'z'Link.is_hash_allowed.<locals>.<genexpr>&s"øèø€ÒQ±D°A°q6×)Ñ)¨!¨Q×/ÑQùsƒ")Úanyr‘r[r?s `r&r>zLink.is_hash_allowed s+ø€ð ˆ>ØÜÓQ¸D¿L¹L×<NÑ<NÓ<PÔQÓQÐQr.)NNNNTN)r5rr’zstr | IndexContent | Noner“ú
str | Noner”r r•zMetadataFile | Noner–rGr@zMapping[str, str] | NonerBrC)r¢zdict[str, Any]r£rrBú Link | None)r¯zdict[str, str | None]r£rrŠrrBr )rBr)rBÚint)rÃrrBrG)rBztuple[str, str])rBr )rBr rE)rBrGrF)-rHrIrJrKÚ    __slots__rœrPr§r³r¸r»r¾rÄrÆÚpropertyr5r¶rÏrÑr€rƒrvrrÙrÝr"rMrãÚ
IGNORECASErår™rèrérìr;r½r%r÷rùrýrÿrrrr>rSr.r&rrÅsÉ„áDò €Ið 15Ø&*Ø$(Ø26Ø#'Ø+/ð?1à ð?1ð.ð?1ð$ð    ?1ð
"ð ?1ð 0ð ?1ð!ð?1ð)ð?1ð
ó?1ðBð0
à!ð0
ðð0
ð
ò    0
óð0
ðdð1
à-ð1
ðð1
ðð    1
ð
 
ò 1
óð1
óf%ó óó%ó
$ð
òóððò.óð.ðò óð ðò%óð%ðò'óð'ðò'óð'ð òóðóCðò"óð"ðòJóðJð"r—z‘zÐ"4Ó5Ðð"r—z‘zØ4°b·m±móÐóð$!+ §
¡
Ð+FÓ GÐà òóðó IóAðò7óð7ðò.óð.ðòOóðOðò%óð%ó>ðò+óð+ðò.óð.ð
ò.óð.ðò"óð"ôRr.rcó:—eZdZUdZded<ded<ded<ded    <y
) Ú _CleanResulta•Convert link for equivalency check.
 
    This is used in the resolver to check whether two URL-specified requirements
    likely point to the same distribution and can be considered equivalent. This
    equivalency logic avoids comparing URLs literally, which can be too strict
    (e.g. "a=1&b=2" vs "b=2&a=1") and produce conflicts unexpecting to users.
 
    Currently this does three things:
 
    1. Drop the basic auth part. This is technically wrong since a server can
       serve different content based on auth, but if it does that, it is even
       impossible to guarantee two URLs without auth are equivalent, since
       the user can input different auth information when prompted. So the
       practical solution is to assume the auth doesn't affect the response.
    2. Parse the query to avoid the ordering issue. Note that ordering under the
       same key in the query are NOT cleaned; i.e. "a=1&a=2" and "a=2&a=1" are
       still considered different.
    3. Explicitly drop most of the fragment part, except ``subdirectory=`` and
       hash values, since it should have no impact the downloaded content. Note
       that this drops the "egg=" part historically used to denote the requested
       project (and extras), which is wrong in the strictest sense, but too many
       people are supplying it inconsistently to cause superfluous resolution
       conflicts, so we choose to also ignore them.
    zurllib.parse.SplitResultÚparsedzdict[str, list[str]]rÛrÚ subdirectoryrDr@N)rHrIrJrKrLrSr.r&rr)s!…ñð2 %Ó$Ø ÓØÓØ Ôr.rcó—|j}|jjdd«d}|jdk(r|sd}tj
j |j«}d|vrtjd|«    |dd    }tDcic]}||vsŒ|||d    “Œ}}t|j|d
d
¬ «tj
j |j«||¬ «S#ttf$rd
}YŒzwxYwcc}w) Nú@rØéÿÿÿÿrÚ    localhostÚeggzIgnoring egg= fragment in %srrro)rƒrÛrÜ)rrÛrr@)rŽrƒÚrsplitr€r`raÚparse_qsrÜr­r®Ú
IndexErrorÚKeyErrorr*rr…rÛ)ÚlinkrrƒrÜrrîr@s       r&Ú _clean_linkr Is€Ø × Ñ €FØ ]‰]× !Ñ ! # qÓ )¨"Ñ -€Fà ‡}}˜Ò¡v؈܏|‰|×$Ñ$ V§_¡_Ó5€HØ Ñ܏ ‰ Ð3°TÔ:ðð  Ñ/°Ñ2ˆ ô
*;Ö L A¸aÀ8ºmˆa˜!‘˜Q‘ÑÐ L€FÐ LÜ Ø‰ f°BÀˆÓD܏l‰l×#Ñ# F§L¡LÓ1Ø!Øô     ðøô œÐ !òØŠ ðüòMsÂC2    D    Â D    Ã2DÄDcó0—t|«t|«k(Sr!)r )Úlink1Úlink2s  r&Úlinks_equivalentr$cs€ä uÓ ¤¨UÓ!3Ñ 3Ð3r.)r@rVrBrV)rdrrBr)rvrrwrGrBr)r5rrBr)rŠrr5rrBr)rrrBr)r"rr#rrBrG)7Ú
__future__rrQrrÚloggingrûrÌr"Ú urllib.parser`Úcollections.abcrÚ dataclassesrÚtypingrrrÚpip._internal.utils.deprecationr    Úpip._internal.utils.filetypesr
Úpip._internal.utils.hashesr Úpip._internal.utils.miscr r rrÚpip._internal.utils.urlsrrÚpip._internal.index.collectorrÚ    getLoggerrHr­r*rrUr^rermrMrrpr}r‡r‹Útotal_orderingrrr rRr$rSr.r&ú<module>r3s2ðÝ"ãÛÛÛ    ÛÛ    ÛÝ#Ý!÷ñõ 7Ý9Ý-÷ó÷ >áÝ:à    ˆ×    Ñ    ˜8Ó    $€ð
LÐñ $Ô÷2Hð2Hóð2Hñj $Ô÷JðJóðJóó:óð$ R—Z‘Z     ¨2¯=©=Ó9Ðó"ó,ó&3ð ×Ñ÷`Rð`Róð`RôF :ôó@ð4 ‡ò4óñ4r.