zmc
2023-08-08 e792e9a60d958b93aef96050644f369feb25d61b
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
U
H=®d„Ëã@sDddlZddlmZddlZddlZddlZddlZddlZz ddlZWne    k
rdddl
ZYnXddl Z ddl m Z ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZddlm Z m!Z!m"Z"ddl#m$Z$m%Z%ddl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/dd    l0m1Z1m2Z2dd
l3m4Z4m5Z5e 6e7¡Z8e 9d ¡Z:e 9d ej;¡Z<e 9d ¡Z=dZ>d-dd„Z?Gdd„deƒZ@Gdd„deAƒZBGdd„deBƒZCGdd„deBƒZDGdd„deAƒZEGdd„deBƒZFGdd„deBƒZGGdd „d eBƒZHGd!d"„d"eBƒZIGd#d$„d$eBƒZJeJeHƒeFd%d&d'd(d)ZKeKjLZLe 9d*¡ZMGd+d,„d,eAƒZNdS).éN)ÚBytesIOé)ÚDistlibException)ÚurljoinÚurlparseÚ
urlunparseÚ url2pathnameÚ pathname2urlÚqueueÚquoteÚunescapeÚ string_typesÚ build_openerÚHTTPRedirectHandlerÚ    text_typeÚRequestÚ    HTTPErrorÚURLError)Ú DistributionÚDistributionPathÚ    make_dist)ÚMetadataÚMetadataInvalidError)    Úcached_propertyÚparse_credentialsÚ ensure_slashÚsplit_filenameÚget_project_dataÚparse_requirementÚparse_name_and_versionÚ ServerProxyÚnormalize_name)Ú
get_schemeÚUnsupportedVersionError)ÚWheelÚ is_compatiblez^(\w+)=([a-f0-9]+)z;\s*charset\s*=\s*(.*)\s*$ztext/html|application/x(ht)?mlzhttps://pypi.org/pypicCs6|dkr t}t|dd}z | ¡W¢S|dƒƒXdS)z•
    Return all distribution names known by an index.
    :param url: The URL of the index.
    :return: A list of all known distribution names.
    Nç@©ÚtimeoutÚclose)Ú DEFAULT_INDEXr Ú list_packages)ÚurlÚclient©r.úSD:\z\workplace\VsCode\pyvenv\venv\Lib\site-packages\pip/_vendor/distlib/locators.pyÚget_all_distribution_names)s   r0c@s$eZdZdZdd„ZeZZZdS)ÚRedirectHandlerzE
    A class to work around a bug in some Python 3.2.x releases.
    c    Cs‚d}dD]}||kr||}q"q|dkr.dSt|ƒ}|jdkrnt| ¡|ƒ}t|dƒrf| ||¡n|||<t ||||||¡S)N)ÚlocationÚuriÚÚreplace_header)rÚschemerÚ get_full_urlÚhasattrr5ÚBaseRedirectHandlerÚhttp_error_302)    ÚselfÚreqÚfpÚcodeÚmsgÚheadersÚnewurlÚkeyÚurlpartsr.r.r/r:@s 
 
ÿzRedirectHandler.http_error_302N)Ú__name__Ú
__module__Ú __qualname__Ú__doc__r:Úhttp_error_301Úhttp_error_303Úhttp_error_307r.r.r.r/r17sr1c@s¶eZdZdZdZdZdZdZedZd)dd    „Z    d
d „Z
d d „Z dd„Z dd„Z dd„Zee eƒZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Zd$d%„Zd*d'd(„ZdS)+ÚLocatorzG
    A base class for locators - things that locate distributions.
    )z.tar.gzz.tar.bz2z.tarz.zipz.tgzz.tbz)z.eggz.exeú.whl)z.pdfN)rLÚdefaultcCs,i|_||_ttƒƒ|_d|_t ¡|_dS)a^
        Initialise an instance.
        :param scheme: Because locators look for most recent versions, they
                       need to know the version scheme to use. This specifies
                       the current PEP-recommended scheme - use ``'legacy'``
                       if you need to support existing distributions on PyPI.
        N)    Ú_cacher6rr1ÚopenerÚmatcherr
ÚQueueÚerrors)r;r6r.r.r/Ú__init__fs
 zLocator.__init__cCsVg}|j ¡sRz|j d¡}| |¡Wn|jjk
rDYqYnX|j ¡q|S)z8
        Return any errors which have occurred.
        F)rRÚemptyÚgetÚappendÚEmptyÚ    task_done)r;ÚresultÚer.r.r/Ú
get_errorsys
 
 zLocator.get_errorscCs | ¡dS)z>
        Clear any errors which may have been logged.
        N)r[©r;r.r.r/Ú clear_errors‡szLocator.clear_errorscCs|j ¡dS©N)rNÚclearr\r.r.r/Ú clear_cacheŽszLocator.clear_cachecCs|jSr^©Ú_schemer\r.r.r/Ú _get_scheme‘szLocator._get_schemecCs
||_dSr^ra)r;Úvaluer.r.r/Ú _set_scheme”szLocator._set_schemecCs tdƒ‚dS)a=
        For a given project, get a dictionary mapping available versions to Distribution
        instances.
 
        This should be implemented in subclasses.
 
        If called from a locate() request, self.matcher will be set to a
        matcher for the requirement to satisfy, otherwise it will be None.
        ú Please implement in the subclassN©ÚNotImplementedError)r;Únamer.r.r/Ú _get_project™s
zLocator._get_projectcCs tdƒ‚dS)úJ
        Return all the distribution names known to this locator.
        rfNrgr\r.r.r/Úget_distribution_names¥szLocator.get_distribution_namescCsL|jdkr| |¡}n2||jkr,|j|}n| ¡| |¡}||j|<|S)zÖ
        For a given project, get a dictionary mapping available versions to Distribution
        instances.
 
        This calls _get_project to do all the work, and just implements a caching layer on top.
        N)rNrjr])r;rirYr.r.r/Ú get_project«s
 
 
 
zLocator.get_projectcCs^t|ƒ}t |j¡}d}| d¡}| |j¡}|rBtt|ƒ|jƒ}|j    dkd|j
k||||fS)zu
        Give an url a score which can be used to choose preferred URLs
        for a given project release.
        TrLÚhttpszpypi.org) rÚ    posixpathÚbasenameÚpathÚendswithÚdownloadable_extensionsr%r$Ú
wheel_tagsr6Únetloc)r;r,ÚtrpÚ
compatibleÚis_wheelZis_downloadabler.r.r/Ú    score_url¼s 
 ÿzLocator.score_urlcCsR|}|rN| |¡}| |¡}||kr(|}||kr@t d||¡nt d||¡|S)a{
        Choose one of two URLs where both are candidates for distribution
        archives for the same version of a distribution (for example,
        .tar.gz vs. zip).
 
        The current implementation favours https:// URLs over http://, archives
        from PyPI over those from other locations, wheel compatibility (if a
        wheel) and then the archive name.
        zNot replacing %r with %rzReplacing %r with %r)ryÚloggerÚdebug)r;Úurl1Úurl2rYÚs1Ús2r.r.r/Ú
prefer_urlËs
 
 
zLocator.prefer_urlcCs
t||ƒS)zZ
        Attempt to split a filename in project name, version and Python version.
        )r)r;ÚfilenameÚ project_namer.r.r/rászLocator.split_filenamec Csdd„}d}t|ƒ\}}}}}    }
|
 ¡ d¡r<t d||
¡t |
¡} | rX|  ¡\} } nd\} } |}|r€|ddkr€|dd…}| d    ¡r>z~t    |ƒ}t
||j ƒs°t d
|¡nX|dkr¾d }n ||j |ƒ}|r|j |j |jt|||||    d fƒd  dd„|jDƒ¡dœ}Wn0tk
r:}zt d|¡W5d}~XYnXnÄ| |j¡sZt d|¡n¨t |¡}}|jD]’}| |¡rn|dt|ƒ …}| ||¡}|s°t d|¡nH|\}}}|rÌ|||ƒrø|||t|||||    d fƒdœ}|rø||d<qqn|r| r| |d| <|S)a
        See if a URL is a candidate for a download URL for a project (the URL
        has typically been scraped from an HTML page).
 
        If it is, a dictionary is returned with keys "name", "version",
        "filename" and "url"; otherwise, None is returned.
        cSst|ƒt|ƒkSr^)r!)Zname1Zname2r.r.r/Ú same_projectïsz:Locator.convert_url_to_download_info.<locals>.same_projectNzegg=z %s: version hint in fragment: %r)NNéÿÿÿÿú/rLzWheel not compatible: %sTr4z, cSs"g|]}d t|dd…ƒ¡‘qS)Ú.éN)ÚjoinÚlist)Ú.0Úvr.r.r/Ú
<listcomp>sz8Locator.convert_url_to_download_info.<locals>.<listcomp>)riÚversionrr,úpython-versionzinvalid path for wheel: %szNot downloadable: %sz No match for project/version: %s)rirrr,rŽú    %s_digest)rÚlowerÚ
startswithrzr{Ú HASHER_HASHÚmatchÚgroupsrrr$r%rtrirrrrˆÚpyverÚ    ExceptionÚwarningrsrorpÚlenr)r;r,r‚rƒrYr6rurqÚparamsÚqueryÚfragÚmÚalgoÚdigestZorigpathÚwheelÚincluderZrÚextrvrirr•r.r.r/Úconvert_url_to_download_infoçs€ÿ
    ÿÿú
     
 
ÿü
  z$Locator.convert_url_to_download_infocCshd}d|kr6|d}dD]}||kr|||f}q6q|sddD]$}d|}||kr>|||f}qdq>|S)zò
        Get a digest from a dictionary by looking at a "digests" dictionary
        or keys of the form 'algo_digest'.
 
        Returns a 2-tuple (algo, digest) if found, else None. Currently
        looks only for SHA256, then MD5.
        NÚdigests)Úsha256Úmd5rr.)r;ÚinforYr£rrBr.r.r/Ú _get_digest1s  zLocator._get_digestc    Cs®| d¡}| d¡}||kr,||}|j}nt|||jd}|j}| |¡|_}|d}||d|<|j|dkrœ| |j|¡|_|d |t    ƒ¡ 
|¡||_ |||<dS)zñ
        Update a result dictionary (the final result from _get_project) with a
        dictionary for a specific version, which typically holds information
        gleaned from a filename or URL for an archive for the distribution.
        rir©r6r,r£ÚurlsN) ÚpopÚmetadatarr6r§ržÚ
source_urlr€Ú
setdefaultÚsetÚaddÚlocator)    r;rYr¦rirÚdistÚmdržr,r.r.r/Ú_update_version_dataHs
 
 zLocator._update_version_dataFc    Cs¤d}t|ƒ}|dkr td|ƒ‚t|jƒ}| |j¡|_}t d|t|ƒj    ¡| 
|j ¡}t |ƒdkr2g}|j }    |D]z}
|
dkr†qxzH| |
¡s¢t d||
¡n*|s°|    |
ƒjs¼| |
¡nt d|
|j ¡Wqxtk
rðt d||
¡YqxXqxt |ƒd    krt||jd
}|r2t d |¡|d } || }|rš|jrH|j|_| d i¡ | tƒ¡|_i} | di¡} |jD]}|| krv| || |<qv| |_d|_|S)a
        Find the most recent distribution which matches the given
        requirement.
 
        :param requirement: A requirement of the form 'foo (1.0)' or perhaps
                            'foo (>= 1.0, < 2.0, != 1.3)'
        :param prereleases: If ``True``, allow pre-release versions
                            to be located. Otherwise, pre-release versions
                            are not returned.
        :return: A :class:`Distribution` instance, or ``None`` if no such
                 distribution could be located.
        NzNot a valid requirement: %rzmatcher: %s (%s)r‡©r©r£z%s did not match %rz%skipping pre-release version %s of %szerror matching %s with %rr)rBzsorted list: %sr„r©r£)rrr"r6rPÚ requirementrzr{ÚtyperDrmrir˜Z version_classr“Ú is_prereleaserVr–r—ÚsortedrBÚextrasrUr®Ú download_urlsr£)r;rµÚ prereleasesrYÚrr6rPÚversionsÚslistZvclsÚkrÚdÚsdr,r.r.r/Úlocate_sX  
 
 ÿ  
 
zLocator.locate)rM)F)rDrErFrGÚsource_extensionsÚbinary_extensionsÚexcluded_extensionsrtrsrSr[r]r`rcreÚpropertyr6rjrlrmryr€rr¢r§r³rÂr.r.r.r/rKVs.
 
 JrKcs0eZdZdZ‡fdd„Zdd„Zdd„Z‡ZS)ÚPyPIRPCLocatorz‘
    This locator uses XML-RPC to locate distributions. It therefore
    cannot be used with simple mirrors (that only mirror file content).
    c s*tt|ƒjf|Ž||_t|dd|_dS)z—
        Initialise an instance.
 
        :param url: The URL to use for XML-RPC.
        :param kwargs: Passed to the superclass constructor.
        r&r'N)ÚsuperrÇrSÚbase_urlr r-©r;r,Úkwargs©Ú    __class__r.r/rS szPyPIRPCLocator.__init__cCst|j ¡ƒS©rk)r®r-r+r\r.r.r/rl«sz%PyPIRPCLocator.get_distribution_namesc Csiidœ}|j |d¡}|D]Þ}|j ||¡}|j ||¡}t|jd}|d|_|d|_| d¡|_    | dg¡|_
| d¡|_ t |ƒ}|r|d    }    |    d
|_ | |    ¡|_||_|||<|D]:}    |    d
}
| |    ¡} |d  |tƒ¡ |
¡| |d |
<q¾q|S) Nr´Tr¨rirÚlicenseÚkeywordsÚsummaryrr,r©r£)r-Zpackage_releasesZ release_urlsZ release_datarr6rirrUrÏrÐrÑrr¬r§ržr°r­r®r¯) r;rirYr½r‹r©Údatar«r±r¦r,ržr.r.r/rj±s0
 
 
 
 
zPyPIRPCLocator._get_project©rDrErFrGrSrlrjÚ __classcell__r.r.rÌr/rǛs rÇcs0eZdZdZ‡fdd„Zdd„Zdd„Z‡ZS)ÚPyPIJSONLocatorzw
    This locator uses PyPI's JSON interface. It's very limited in functionality
    and probably not worth using.
    c s tt|ƒjf|Žt|ƒ|_dSr^)rÈrÕrSrrÉrÊrÌr.r/rSÐszPyPIJSONLocator.__init__cCs tdƒ‚dS©rkzNot available from this locatorNrgr\r.r.r/rlÔsz&PyPIJSONLocator.get_distribution_namesc
Cs
iidœ}t|jdt|ƒƒ}z¤|j |¡}| ¡ ¡}t |¡}t    |j
d}|d}|d|_ |d|_ |  d¡|_|  dg¡|_|  d    ¡|_t|ƒ}||_|d
}    |||j <|d
D]T}
|
d }|j |¡| |
¡|j|<|d
 |j tƒ¡ |¡| |
¡|d |<qº|d  ¡D]¤\} } | |j kr4qt    |j
d} |j | _ | | _ t| ƒ}||_||| <| D]T}
|
d }|j |¡| |
¡|j|<|d
 | tƒ¡ |¡| |
¡|d |<qhqWn@tk
r}z |j t|ƒ¡t d|¡W5d}~XYnX|S)Nr´z%s/jsonr¨r¦rirrÏrÐrÑr©r,r£ZreleaseszJSON fetch failed: %s) rrÉr rOÚopenÚreadÚdecodeÚjsonÚloadsrr6rirrUrÏrÐrÑrr°rºr¯r§r£r­r®Úitemsr–rRÚputrrzÚ    exception)r;rirYr,ÚresprÒrÀr²r±r©r¦rÚinfosZomdÚodistrZr.r.r/rjÚsT
 
 
 
 
         zPyPIJSONLocator._get_projectrÓr.r.rÌr/rÕËs rÕc@s`eZdZdZe dejejBejB¡Z    e dejejB¡Z
dd„Z e dej¡Z e dd„ƒZd    S)
ÚPagez4
    This class represents a scraped HTML page.
    zÝ
(rel\s*=\s*(?:"(?P<rel1>[^"]*)"|'(?P<rel2>[^']*)'|(?P<rel3>[^>\s
]*))\s+)?
href\s*=\s*(?:"(?P<url1>[^"]*)"|'(?P<url2>[^']*)'|(?P<url3>[^>\s
]*))
(\s+rel\s*=\s*(?:"(?P<rel4>[^"]*)"|'(?P<rel5>[^']*)'|(?P<rel6>[^>\s
]*)))?
z!<base\s+href\s*=\s*['"]?([^'">]+)cCs4||_||_|_|j |j¡}|r0| d¡|_dS)zk
        Initialise an instance with the Unicode page contents and the URL they
        came from.
        rN)rÒrÉr,Ú_baseÚsearchÚgroup)r;rÒr,rœr.r.r/rS s
 z Page.__init__z[^a-z0-9$&+,/:;=?@.#%_\\|-]cCs¾dd„}tƒ}|j |j¡D]Š}| d¡}|dpX|dpX|dpX|dpX|dpX|d    }|d
pp|d pp|d }t|j|ƒ}t|ƒ}|j     d d„|¡}| 
||f¡qt |dd„dd}|S)zâ
        Return the URLs of all the links on a page together with information
        about their "rel" attribute, for determining which ones to treat as
        downloads and which ones to queue for further scraping.
        cSs,t|ƒ\}}}}}}t||t|ƒ|||fƒS)zTidy up an URL.)rrr )r,r6rurqr™ršr›r.r.r/Úclean4s  ÿzPage.links.<locals>.cleanr4Zrel1Zrel2Zrel3Zrel4Zrel5Zrel6r|r}Zurl3cSsdt| d¡ƒS)Nz%%%2xr)Úordrå)rœr.r.r/Ú<lambda>BózPage.links.<locals>.<lambda>cSs|dS)Nrr.)rvr.r.r/rèFréT)rBÚreverse) r®Ú_hrefÚfinditerrÒÚ    groupdictrrÉr Ú    _clean_reÚsubr¯r¸)r;rærYr“rÀÚrelr,r.r.r/Úlinks-s$
ÿÿÿ z
Page.linksN)rDrErFrGÚreÚcompileÚIÚSÚXrërãrSrîrrñr.r.r.r/râsü râcs˜eZdZdZejdd„dd„dœZd‡fdd    „    Zd
d „Zd d „Z    dd„Z
e   de j ¡Zdd„Zdd„Zdd„Zdd„Zdd„Ze   d¡Zdd„Z‡ZS)ÚSimpleScrapingLocatorzã
    A locator which scrapes HTML pages to locate downloads for a distribution.
    This runs multiple threads to do the I/O; performance is at least as good
    as pip's PackageFinder, which works in an analogous fashion.
    cCstjttƒd ¡S)N)Úfileobj)ÚgzipÚGzipFilerrÀrØ©Úbr.r.r/rèTrézSimpleScrapingLocator.<lambda>cCs|Sr^r.rûr.r.r/rèUré)ÚdeflaterùÚnoneNé
c sltt|ƒjf|Žt|ƒ|_||_i|_tƒ|_t     
¡|_ tƒ|_ d|_ ||_t ¡|_t ¡|_d|_dS)a¤
        Initialise an instance.
        :param url: The root URL to use for scraping.
        :param timeout: The timeout, in seconds, to be applied to requests.
                        This defaults to ``None`` (no timeout specified).
        :param num_workers: The number of worker threads you want to do I/O,
                            This defaults to 10.
        :param kwargs: Passed to the superclass.
        FN)rÈr÷rSrrÉr(Ú _page_cacher®Ú_seenr
rQÚ    _to_fetchÚ
_bad_hostsÚskip_externalsÚ num_workersÚ    threadingÚRLockÚ_lockÚ_gplockÚplatform_check)r;r,r(rrËrÌr.r/rSXs
 
 
 
 
zSimpleScrapingLocator.__init__cCsFg|_t|jƒD]0}tj|jd}| d¡| ¡|j |¡qdS)z¾
        Threads are created only when get_project is called, and terminate
        before it returns. They are there primarily to parallelise I/O (i.e.
        fetching web pages).
        )ÚtargetTN)    Ú_threadsÚrangerrÚThreadÚ_fetchÚ    setDaemonÚstartrV)r;Úirvr.r.r/Ú_prepare_threadsss 
z&SimpleScrapingLocator._prepare_threadscCs6|jD]}|j d¡q|jD] }| ¡qg|_dS)zu
        Tell all the threads to terminate (by sending a sentinel value) and
        wait for them to do so.
        N)r rrÝrˆ)r;rvr.r.r/Ú _wait_threads€s
 
 
 
z#SimpleScrapingLocator._wait_threadsc    Cs’iidœ}|jx||_||_t|jdt|ƒƒ}|j ¡|j ¡|     ¡z&t   d|¡|j  |¡|j  ¡W5| 
¡X|`W5QRX|S)Nr´z%s/z Queueing %s)r    rYr‚rrÉr rr_rrrrzr{rrÝrˆ)r;rirYr,r.r.r/rjs
 
 
 
z"SimpleScrapingLocator._get_projectz<\b(linux_(i\d86|x86_64|arm\w+)|win(32|_amd64)|macosx_?\d+)\bcCs |j |¡S)zD
        Does an URL refer to a platform-specific download?
        )Úplatform_dependenträ)r;r,r.r.r/Ú_is_platform_dependent¢sz,SimpleScrapingLocator._is_platform_dependentc    CsZ|jr| |¡rd}n| ||j¡}t d||¡|rV|j| |j|¡W5QRX|S)a%
        See if an URL is a suitable download for a project.
 
        If it is, register information in the result dictionary (for
        _get_project) about the specific version it's for.
 
        Note that the return value isn't actually used other than as a boolean
        value.
        Nzprocess_download: %s -> %s)    r
rr¢r‚rzr{rr³rY)r;r,r¦r.r.r/Ú_process_download¨s
z'SimpleScrapingLocator._process_downloadc
CsÄt|ƒ\}}}}}}| |j|j|j¡r2d}n||jrJ| |j¡sJd}nd| |j¡s\d}nR|dkrjd}nD|dkrxd}n6| |¡rˆd}n&|     dd¡d}    |     
¡dkrªd}nd}t   d    ||||¡|S)
        Determine whether a link URL from a referring page and with a
        particular "rel" attribute should be queued for scraping.
        F)ZhomepageÚdownload)ÚhttprnÚftpú:rrÚ    localhostTz#should_queue: %s (%s) from %s -> %s) rrrrÃrÄrÅrr‘rÉrÚsplitrrzr{)
r;ÚlinkZreferrerrðr6rurqÚ_rYÚhostr.r.r/Ú _should_queue¼s0ÿ 
 
ÿz#SimpleScrapingLocator._should_queuec
Csð|j ¡}zÌz”|rž| |¡}|dkr,WW¢®q|jD]j\}}||jkr2zB|j |¡| |¡s„| |||¡r„t     
d||¡|j  |¡Wq2t k
ršYq2Xq2Wn2t k
rÒ}z|j  t|ƒ¡W5d}~XYnXW5|j ¡X|sqìqdS)z×
        Get a URL to fetch from the work queue, get the HTML page, examine its
        links for download candidates and candidates for further scraping.
 
        This is a handy method to run in a thread.
        NzQueueing %s from %s)rrUrXÚget_pagerñrr¯rr!rzr{rÝrr–rRr)r;r,ÚpagerrðrZr.r.r/rÙs,
 
 
 
 ÿ & zSimpleScrapingLocator._fetchc CsXt|ƒ\}}}}}}|dkr:tj t|ƒ¡r:tt|ƒdƒ}||jkr`|j|}t     d||¡nô| 
dd¡d}d}||j krt     d||¡nÄt |d    d
id }z¤zât     d |¡|j j||jd }    t     d|¡|     ¡}
|
 dd¡} t | ¡r„|     ¡} |     ¡} |
 d¡}|r"|j|}|| ƒ} d}t | ¡}|r@| d¡}z|  |¡} Wn tk
rn|  d¡} YnXt| | ƒ}||j| <Wn¼tk
rÄ}z|jdkr´t d||¡W5d}~XYn€t k
r}z0t d||¡|j!|j  "|¡W5QRXW5d}~XYn2t#k
rB}zt d||¡W5d}~XYnXW5||j|<X|S)a
        Get the HTML for an URL, possibly from an in-memory cache.
 
        XXX TODO Note: this cache is never actually cleared. It's assumed that
        the data won't get stale over the lifetime of a locator instance (not
        necessarily true for the default_locator).
        Úfilez
index.htmlzReturning %s from cache: %srrrNzSkipping %s due to bad host %szAccept-encodingÚidentity)r@z Fetching %sr'z
Fetched %sz Content-Typer4zContent-Encodingzutf-8zlatin-1i”zFetch failed: %s: %s)$rÚosrqÚisdirrrrrrzr{rrrrOr×r(r¦rUÚHTML_CONTENT_TYPEr“ÚgeturlrØÚdecodersÚCHARSETrärårÙÚ UnicodeErrorrârr>rÞrrr¯r–)r;r,r6rurqrrYr r<rßr@Ú content_typeZ    final_urlrÒÚencodingÚdecoderrœrZr.r.r/r"úsZ    
 
 
 
 
 
 
 
 &$ zSimpleScrapingLocator.get_pagez<a href=[^>]*>([^<]+)<cCsLtƒ}| |j¡}|s$td|jƒ‚|j |j¡D]}| | d¡¡q2|S)rkzUnable to get %sr)    r®r"rÉrÚ _distname_rerìrÒr¯rå)r;rYr#r“r.r.r/rl7s z,SimpleScrapingLocator.get_distribution_names)Nrÿ)rDrErFrGÚzlibÚ
decompressr*rSrrrjròrórôrrrr!rr"r0rlrÔr.r.rÌr/r÷Js&ý  ÿ!;
r÷cs8eZdZdZ‡fdd„Zdd„Zdd„Zdd    „Z‡ZS)
ÚDirectoryLocatorz?
    This class locates distributions in a directory tree.
    c sN| dd¡|_tt|ƒjf|Žtj |¡}tj |¡sDt    d|ƒ‚||_
dS)aŒ
        Initialise an instance.
        :param path: The root of the directory tree to search.
        :param kwargs: Passed to the superclass constructor,
                       except for:
                       * recursive - if True (the default), subdirectories are
                         recursed into. If False, only the top-level directory
                         is searched,
        Ú    recursiveTzNot a directory: %rN) rªr4rÈr3rSr&rqÚabspathr'rÚbase_dir)r;rqrËrÌr.r/rSHs
   zDirectoryLocator.__init__cCs | |j¡S)zá
        Should a filename be considered as a candidate for a distribution
        archive? As well as the filename, the directory which contains it
        is provided, though not used by the current implementation.
        )rrrs)r;rÚparentr.r.r/Úshould_includeYszDirectoryLocator.should_includec        Csiidœ}t |j¡D]t\}}}|D]Z}| ||¡r$tj ||¡}tddttj |¡ƒdddfƒ}|     ||¡}|r$| 
||¡q$|j sqŒq|S)Nr´r$r4) r&Úwalkr6r8rqrˆrr    r5r¢r³r4)    r;rirYÚrootÚdirsÚfilesÚfnr,r¦r.r.r/rjas"
 þ zDirectoryLocator._get_projectc    CsŽtƒ}t |j¡D]v\}}}|D]\}| ||¡r tj ||¡}tddttj     |¡ƒdddfƒ}| 
|d¡}|r |  |d¡q |j sqŠq|S)rkr$r4Nri) r®r&r9r6r8rqrˆrr    r5r¢r¯r4)r;rYr:r;r<r=r,r¦r.r.r/rlqs" þ z'DirectoryLocator.get_distribution_names)    rDrErFrGrSr8rjrlrÔr.r.rÌr/r3Cs
 r3c@s eZdZdZdd„Zdd„ZdS)Ú JSONLocatora
    This locator uses special extended metadata (not available on PyPI) and is
    the basis of performant dependency resolution in distlib. Other locators
    require archive downloads before dependencies can be determined! As you
    might imagine, that can be slow.
    cCs tdƒ‚dSrÖrgr\r.r.r/rl‹sz"JSONLocator.get_distribution_namescCsÚiidœ}t|ƒ}|rÖ| dg¡D]²}|ddks"|ddkr@q"t|d|d| d    d
¡|jd }|j}|d |_d |kr|d rd|d f|_| di¡|_| di¡|_|||j    <|d 
|j    t ƒ¡  |d ¡q"|S)Nr´r<ÚptypeÚsdistZ    pyversionÚsourcerirrÑzPlaceholder for summary)rÑr6r,ržr¥Ú requirementsÚexportsr©) rrUrr6r«r¬ržZ dependenciesrCrr­r®r¯)r;rirYrÒr¦r±r²r.r.r/rj‘s*
ÿý
 
 zJSONLocator._get_projectN)rDrErFrGrlrjr.r.r.r/r>„sr>cs(eZdZdZ‡fdd„Zdd„Z‡ZS)ÚDistPathLocatorz‚
    This locator finds installed distributions in a path. It can be useful for
    adding to an :class:`AggregatingLocator`.
    c s*tt|ƒjf|Žt|tƒs t‚||_dS)zs
        Initialise an instance.
 
        :param distpath: A :class:`DistributionPath` instance to search.
        N)rÈrDrSÚ
isinstancerÚAssertionErrorÚdistpath)r;rGrËrÌr.r/rS¯szDistPathLocator.__init__cCsP|j |¡}|dkr iidœ}n,|j|d|jt|jgƒid|jtdgƒii}|S)Nr´r©r£)rGÚget_distributionrr®r¬)r;rir±rYr.r.r/rj¹s  ýzDistPathLocator._get_project)rDrErFrGrSrjrÔr.r.rÌr/rDªs
rDcsReZdZdZ‡fdd„Z‡fdd„Zdd„Zeej    j
eƒZ    dd    „Z d
d „Z ‡Z S) ÚAggregatingLocatorzI
    This class allows you to chain and/or merge a list of locators.
    cs*| dd¡|_||_tt|ƒjf|ŽdS)aÏ
        Initialise an instance.
 
        :param locators: The list of locators to search.
        :param kwargs: Passed to the superclass constructor,
                       except for:
                       * merge - if False (the default), the first successful
                         search from any of the locators is returned. If True,
                         the results from all locators are merged (this can be
                         slow).
        ÚmergeFN)rªrJÚlocatorsrÈrIrS)r;rKrËrÌr.r/rSÊs zAggregatingLocator.__init__cs&tt|ƒ ¡|jD] }| ¡qdSr^)rÈrIr`rK©r;r°rÌr.r/r`Ús
zAggregatingLocator.clear_cachecCs||_|jD]
}||_q dSr^)rbrKr6)r;rdr°r.r.r/reßs
zAggregatingLocator._set_schemec Csìi}|jD]Ü}| |¡}|r
|jr¨| di¡}| di¡}| |¡| d¡}|rŠ|rŠ| ¡D]*\}}    ||kr€|||    O<q^|    ||<q^| d¡}
|ræ|
ræ|
 |¡q
|jdkr¸d} n"d} |D]}|j |¡rÀd} qÚqÀ| r
|}qèq
|S)Nr©r£TF)rKrmrJrUÚupdaterÜrPr“) r;rirYr°rÀr<r£Zdfr¿r‹ÚddÚfoundr.r.r/rjæs8
 
 
 
 
 
 
 zAggregatingLocator._get_projectc    Cs<tƒ}|jD]*}z|| ¡O}Wq tk
r4Yq Xq |SrÎ)r®rKrlrh)r;rYr°r.r.r/rls
z)AggregatingLocator.get_distribution_names)rDrErFrGrSr`rerÆrKr6ÚfgetrjrlrÔr.r.rÌr/rIÆs  ,rIzhttps://pypi.org/simple/r&r'Úlegacyr¨z1(?P<name>[\w-]+)\s*\(\s*(==\s*)?(?P<ver>[^)]+)\)$c@sLeZdZdZddd„Zdd„Zdd„Zd    d
„Zd d „Zd d„Z    ddd„Z
dS)ÚDependencyFinderz0
    Locate dependencies for distributions.
    NcCs|pt|_t|jjƒ|_dS)zf
        Initialise an instance, using the specified locator
        to locate distributions.
        N)Údefault_locatorr°r"r6rLr.r.r/rS1s
zDependencyFinder.__init__cCsrt d|¡|j}||j|<||j||jf<|jD]:}t|ƒ\}}t d|||¡|j     |t
ƒ¡  ||f¡q2dS)z¨
        Add a distribution to the finder. This will update internal information
        about who provides what.
        :param dist: The distribution to add.
        zadding distribution %szAdd to provided: %s, %s, %sN) rzr{rBÚ dists_by_nameÚdistsrÚprovidesrÚprovidedr­r®r¯)r;r±riÚprr.r.r/Úadd_distribution9s 
 
 z!DependencyFinder.add_distributioncCsxt d|¡|j}|j|=|j||jf=|jD]D}t|ƒ\}}t d|||¡|j|}|     ||f¡|s.|j|=q.dS)z°
        Remove a distribution from the finder. This will update internal
        information about who provides what.
        :param dist: The distribution to remove.
        zremoving distribution %sz Remove from provided: %s, %s, %sN)
rzr{rBrTrUrrVrrWÚremove)r;r±rirXrÚsr.r.r/Úremove_distributionHs 
 
z$DependencyFinder.remove_distributioncCsBz|j |¡}Wn,tk
r<| ¡d}|j |¡}YnX|S)zÞ
        Get a version matcher for a requirement.
        :param reqt: The requirement
        :type reqt: str
        :return: A version matcher (an instance of
                 :class:`distlib.version.Matcher`).
        r)r6rPr#r)r;ÚreqtrPrir.r.r/Ú get_matcherZs  zDependencyFinder.get_matcherc        Cst| |¡}|j}tƒ}|j}||krp||D]B\}}z| |¡}Wntk
rZd}YnX|r,| |¡qpq,|S)zÓ
        Find the distributions which can fulfill a requirement.
 
        :param reqt: The requirement.
         :type reqt: str
        :return: A set of distribution which can fulfill the requirement.
        F)r^rBr®rWr“r#r¯)    r;r]rPrirYrWrÚproviderr“r.r.r/Úfind_providersjs
 
 
zDependencyFinder.find_providersc    Csž|j|}tƒ}|D]$}| |¡}| |j¡s| |¡q|rZ| d||t|ƒf¡d}n@| |¡|j|=|D]}|j |tƒ¡ |¡qp|     |¡d}|S)aŠ
        Attempt to replace one provider with another. This is typically used
        when resolving dependencies from multiple sources, e.g. A requires
        (B >= 1.0) while C requires (B >= 1.1).
 
        For successful replacement, ``provider`` must meet all the requirements
        which ``other`` fulfills.
 
        :param provider: The provider we are trying to replace with.
        :param other: The provider we're trying to replace.
        :param problems: If False is returned, this will contain what
                         problems prevented replacement. This is currently
                         a tuple of the literal string 'cantreplace',
                         ``provider``, ``other``  and the set of requirements
                         that ``provider`` couldn't fulfill.
        :return: True if we can replace ``other`` with ``provider``, else
                 False.
        Z cantreplaceFT)
Úreqtsr®r^r“rr¯Ú    frozensetr\r­rY)    r;r_ÚotherÚproblemsZrlistÚ    unmatchedr[rPrYr.r.r/Útry_to_replace‚s$
 
 
ÿ
 
zDependencyFinder.try_to_replaceFcCsòi|_i|_i|_i|_t|p gƒ}d|krH| d¡|tdddgƒO}t|tƒrh|}}t     d|¡n4|j
j ||d}}|dkrt d|ƒ‚t     d    |¡d
|_ tƒ}t|gƒ}t|gƒ}|r¤| ¡}|j}    |    |jkræ| |¡n"|j|    }
|
|kr| ||
|¡|j|jB} |j} tƒ} |r`||kr`d D]*}d |}||kr4| t|d |ƒO} q4| | B| B}|D].}| |¡}|sFt     d|¡|j
j ||d}|dkrÂ|sÂ|j
j |d
d}|dkrèt     d|¡| d|f¡n^|j|j}}||f|jkr| |¡| |¡|| krF||krF| |¡t     d|j¡|D]R}|j}    |    |jkrx|j |tƒ¡ |¡n"|j|    }
|
|krJ| ||
|¡qJqpq¼t|j ¡ƒ}|D]&}||k|_|jr¶t     d|j¡q¶t     d|¡||fS)aŽ
        Find a distribution and all distributions it depends on.
 
        :param requirement: The requirement specifying the distribution to
                            find, or a Distribution instance.
        :param meta_extras: A list of meta extras such as :test:, :build: and
                            so on.
        :param prereleases: If ``True``, allow pre-release versions to be
                            returned - otherwise, don't return prereleases
                            unless they're all that's available.
 
        Return a set of :class:`Distribution` instances and a set of
        problems.
 
        The distributions returned should be such that they have the
        :attr:`required` attribute set to ``True`` if they were
        from the ``requirement`` passed to ``find()``, and they have the
        :attr:`build_time_dependency` attribute set to ``True`` unless they
        are post-installation dependencies of the ``requirement``.
 
        The problems should be a tuple consisting of the string
        ``'unsatisfied'`` and the requirement which couldn't be satisfied
        by any distribution known to the locator.
        z:*:z:test:z:build:z:dev:zpassed %s as requirement)r»NzUnable to locate %rz
located %sT)ÚtestÚbuildÚdevz:%s:z %s_requireszNo providers found for %rzCannot satisfy %rZ unsatisfiedzAdding %s to install_distsz#%s is a build-time dependency only.zfind done for %s)rWrUrTrar®rZrErrzr{r°rÂrÚ    requestedrªrBrYrfZ run_requiresZ meta_requiresZbuild_requiresÚgetattrr`r¯rZname_and_versionr­ÚvaluesZbuild_time_dependency)r;rµZ meta_extrasr»r±rárdÚtodoZ install_distsrircZireqtsZsreqtsZereqtsrBrZZ    all_reqtsr¼Z    providersr_Únr‹rXrUr.r.r/Úfindªs’ 
 
ÿ
 
 
 
 
 
 
 
 
 
 
 
 
ÿ 
 
 
ÿ zDependencyFinder.find)N)NF) rDrErFrGrSrYr\r^r`rfror.r.r.r/rR,s
(rR)N)OrùÚiorrÚÚloggingr&roròrÚ ImportErrorZdummy_threadingr1r4rÚcompatrrrrr    r
r r r rrr9rrrrZdatabaserrrr«rrÚutilrrrrrrrr r!rr"r#rŸr$r%Ú    getLoggerrDrzrór’rôr+r(r*r0r1ÚobjectrKrÇrÕrâr÷r3r>rDrIrSrÂÚNAME_VERSION_RErRr.r.r.r/Ú<module>s^   D,
 
 
 
G0E:zA&[ÿü