Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!1%mm)__pycache__/package_finder.cpython-39.pycnu[a Re@sZdZddlZddlZddlZddlZddlmZmZmZm Z m Z m Z m Z ddl mZddlmZddlmZddlmZddlmZdd lmZmZmZmZdd lmZmZdd lm Z dd l!m"Z"dd l#m$Z$ddl%m&Z&ddl'm(Z(ddl)m*Z*ddl+m,Z,ddl-m.Z.ddl/m0Z0ddl1m2Z2ddl3m4Z4ddl5m6Z6ddl7m8Z8ddl9m:Z:ddl;mZ>gdZ?e0e@ZAe e de eBeCffZDe eBeBeBee eBeDfZEd3e$e eBeBeBfeFeFddd ZGGd!d"d"ZHee e4eCee d#d$d%ZIGd&d'd'ZJGd(d)d)ZKGd*d+d+ZLGd,d-d-ZMeCeCeBd.d/d0ZNeCeCe eCd.d1d2ZOdS)4z!Routines related to PyPI, indexesN) FrozenSetIterableListOptionalSetTupleUnion) specifiers)Tag)canonicalize_name) _BaseVersion)parse)BestVersionAlreadyInstalledDistributionNotFoundInvalidWheelFilenameUnsupportedWheel) LinkCollector parse_links)InstallationCandidate) FormatControl)Link) SearchScope)SelectionPreferences) TargetPython)Wheel)InstallRequirement) getLogger)WHEEL_EXTENSION)Hashes) indent_log) build_netloc)check_requires_python)SUPPORTED_EXTENSIONS) url_to_path)rBestCandidateResult PackageFinderF)link version_infoignore_requires_pythonreturncCs|zt|j|d}Wn$tjy6td|j|YnB0|sxdtt|}|sft d||j|dStd||j|dS)aa Return whether the given Python version is compatible with a link's "Requires-Python" value. :param version_info: A 3-tuple of ints representing the Python major-minor-micro version to check. :param ignore_requires_python: Whether to ignore the "Requires-Python" value if the given Python version isn't compatible. )r(z2Ignoring invalid Requires-Python (%r) for link: %s.z4Link requires a different Python (%s not in: %r): %sFzBIgnoring failed Requires-Python check (%s not in: %r) for link: %sT) r!requires_pythonr InvalidSpecifierloggerdebugjoinmapstrverbose)r'r(r) is_compatibleversionr&r&/builddir/build/BUILDROOT/alt-python39-pip-21.3.1-2.el8.x86_64/opt/alt/python39/lib/python3.9/site-packages/pip/_internal/index/package_finder.py_check_link_requires_python3s8  r7c @sZeZdZdZedZd eeeee e e e ddddZ e ee e efddd ZdS) LinkEvaluatorzD Responsible for evaluating links for a particular project. z-py([123]\.?[0-9]?)$N) project_namecanonical_nameformats target_python allow_yankedr)r*cCs4|dur d}||_||_||_||_||_||_dS)a :param project_name: The user supplied package name. :param canonical_name: The canonical package name. :param formats: The formats allowed for this package. Should be a set with 'binary' or 'source' or both in it. :param target_python: The target Python interpreter to use when evaluating link compatibility. This is used, for example, to check wheel compatibility, as well as when checking the Python version, e.g. the Python version embedded in a link filename (or egg fragment) and against an HTML link's optional PEP 503 "data-requires-python" attribute. :param allow_yanked: Whether files marked as yanked (in the sense of PEP 592) are permitted to be candidates for install. :param ignore_requires_python: Whether to ignore incompatible PEP 503 "data-requires-python" values in HTML links. Defaults to False. NF) _allow_yanked_canonical_name_ignore_requires_python_formats_target_pythonr9)selfr9r:r;r<r=r)r&r&r6__init__nszLinkEvaluator.__init__)r'r*c Csd}|jr(|js(|jpd}dd|fS|jr<|j}|j}n|\}}|sPdS|tvrfdd|fSd|jvr|tkrd |j }d|fSd |j vr|d krd S|tkr0zt |j }WntyYd S0t|j|jkrd |j }d|fS|j}||s*|}d d|}d|fS|j}d|jvrZ|tkrZd|j }d|fS|slt||j}|sd|j }d|fS|j|} | r|d| }| d} | |jjkrdSt||jj|j d} | sdSt!"d||d|fS)aG Determine whether a link is a candidate for installation. :return: A tuple (is_candidate, result), where `result` is (1) a version string if `is_candidate` is True, and (2) if `is_candidate` is False, an optional string to log the reason the link fails to qualify. Nz Fzyanked for reason: )Fz not a filezunsupported archive format: binaryzNo binaries permitted for {}macosx10z.zip)Fz macosx10 one)Fzinvalid wheel filenamezwrong project name (not {})z^none of the wheel's tags ({}) are compatible (run pip debug --verbose to show compatible tags), sourcezNo sources permitted for zMissing project version for )FzPython version is incorrect)r(r))FNzFound link %s, version: %sT)# is_yankedr> yanked_reason egg_fragmentextsplitextr"rArformatr9pathrfilenamerr namer?rBget_tags supportedget_formatted_file_tagsr0r5_extract_version_from_fragment_py_version_researchstartgroup py_versionr7py_version_infor@r.r/) rCr'r5reasonegg_inforMwheelsupported_tags file_tagsmatchr[supports_pythonr&r&r6 evaluate_linksx              zLinkEvaluator.evaluate_link)N)__name__ __module__ __qualname____doc__recompilerWr2rrboolrrDrrrdr&r&r&r6r8bs  %r8) candidateshashesr9r*c Cs|stdt||t|Sg}g}d}|D]>}|j}|js@n"|j|drV|d7}n ||q.||q.|rx|}nt|}t|t|krd} n dt|d dd |D} td t|||j |t||| |S) a Filter out candidates whose hashes aren't allowed, and return a new list of candidates. If at least one candidate has an allowed hash, then all candidates with either an allowed hash or no hash specified are returned. Otherwise, the given candidates are returned. Including the candidates with no hash specified when there is a match allows a warning to be logged if there is a more preferred candidate with no hash specified. Returning all candidates in the case of no matches lets pip report the hash of the candidate that would otherwise have been installed (e.g. permitting the user to more easily update their requirements file with the desired hash). zJGiven no hashes to check %s links for project %r: discarding no candidatesr)rmrIzdiscarding no candidateszdiscarding {} non-matches: {}z css|]}t|jVqdSN)r2r').0 candidater&r&r6 $z*filter_unallowed_hashes..zPChecked %s links for project %r against %s hashes (%s matches, %s no digest): %s) r.r/lenlistr'has_hashis_hash_allowedappendrOr0 digest_count) rlrmr9matches_or_no_digest non_matches match_countrpr'filtereddiscard_messager&r&r6filter_unallowed_hashessL      r~c@s$eZdZdZdeeddddZdS)CandidatePreferenceszk Encapsulates some of the preferences for filtering and sorting InstallationCandidate objects. FN) prefer_binaryallow_all_prereleasesr*cCs||_||_dS)zR :param allow_all_prereleases: Whether to allow all pre-releases. N)rr)rCrrr&r&r6rD<szCandidatePreferences.__init__)FF)rerfrgrhrkrDr&r&r&r6r5src@sTeZdZdZeeeeeeddddZeedddZ eedd d Z dS) r$zA collection of candidates, returned by `PackageFinder.find_best_candidate`. This class is only intended to be instantiated by CandidateEvaluator's `compute_best_candidate()` method. N)rlapplicable_candidatesbest_candidater*cCsHt|t|ksJ|dur&|r2Jn ||vs2J||_||_||_dS)a :param candidates: A sequence of all available candidates found. :param applicable_candidates: The applicable candidates. :param best_candidate: The most preferred candidate found, or None if no applicable candidates were found. N)set_applicable_candidates _candidatesrrCrlrrr&r&r6rDOs   zBestCandidateResult.__init__r*cCs t|jS)zIterate through all candidates.)iterrrCr&r&r6iter_allgszBestCandidateResult.iter_allcCs t|jS)z*Iterate through the applicable candidates.)rrrr&r&r6iter_applicableksz#BestCandidateResult.iter_applicable) rerfrgrhrrrrDrrrr&r&r&r6r$Hs r$c @seZdZdZedeeeeeee j ee ddddZ dee ee j eeee dddd Ze ee ed d d Zeed ddZe eeed ddZe eed ddZdS)CandidateEvaluatorzm Responsible for filtering and sorting candidates for installation based on what tags are valid. NF)r9r<rr specifierrmr*cCs:|durt}|durt}|}|||||||dS)aCreate a CandidateEvaluator object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. :param specifier: An optional object implementing `filter` (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable versions. :param hashes: An optional collection of allowed hashes. N)r9r`rrrrm)rr SpecifierSetrS)clsr9r<rrrrmr`r&r&r6createwszCandidateEvaluator.create)r9r`rrrrmr*cCs<||_||_||_||_||_||_ddt|D|_dS)z :param supported_tags: The PEP 425 tags supported by the target Python in order of preference (most preferred first). cSsi|]\}}||qSr&r&)roidxtagr&r&r6 sz/CandidateEvaluator.__init__..N)_allow_all_prereleases_hashes_prefer_binary _project_name _specifier_supported_tags enumerate_wheel_tag_preferences)rCr9r`rrrrmr&r&r6rDs zCandidateEvaluator.__init__)rlr*csd|jpd}|j}dd|jdd|D|dDfdd|D}t||j|jd }t||jd S) zM Return the applicable candidates from a list of candidates. NcSsh|] }t|qSr&)r2)rovr&r&r6 sz?CandidateEvaluator.get_applicable_candidates..css|]}t|jVqdSrnr2r5rocr&r&r6rqrrz?CandidateEvaluator.get_applicable_candidates..) prereleasescsg|]}t|jvr|qSr&rrversionsr&r6 rrz@CandidateEvaluator.get_applicable_candidates..)rlrmr9key)rrfilterr~rrsorted _sort_key)rCrlallow_prereleasesrrfiltered_applicable_candidatesr&rr6get_applicable_candidatess  z,CandidateEvaluator.get_applicable_candidates)rpr*c Cs|j}t|}d}d}|j}|jrt|j}z|||j }Wn"tybt d |jYn0|j rnd}|j durt d|j } | } t| d| df}n| }t||j} dt|j} | | ||j||fS)a) Function to pass as the `key` argument to a call to sorted() to sort InstallationCandidates by preference. Returns a tuple such that tuples sorting as greater using Python's default comparison operator are more preferred. The preference is as follows: First and foremost, candidates with allowed (matching) hashes are always preferred over candidates without matching hashes. This is because e.g. if the only candidate with an allowed hash is yanked, we still want to use that candidate. Second, excepting hash considerations, candidates that have been yanked (in the sense of PEP 592) are always less preferred than candidates that haven't been yanked. Then: If not finding wheels, they are sorted by version only. If finding wheels, then the sort order is by version, then: 1. existing installs 2. wheels ordered via Wheel.support_index_min(self._supported_tags) 3. source archives If prefer_binary was set, then all wheels are sorted above sources. Note: it was considered to embed this logic into the Link comparison operators, but then different sdist links with the same version, would have to be considered equal r&rzB{} is not a supported wheel for this platform. It can't be sorted.rINz ^(\d+)(.*)$)rrsr'is_wheelrrQfind_most_preferred_tagr ValueErrorrrOr build_tagrirbgroupsintrvrrJr5) rCrp valid_tags support_numrbinary_preferencer'r_prirbbuild_tag_groupshas_allowed_hash yank_valuer&r&r6rsD    zCandidateEvaluator._sort_keycCs|sdSt||jd}|S)zy Return the best candidate per the instance's sort order, or None if no candidate is acceptable. Nr)maxr)rCrlrr&r&r6sort_best_candidatesz&CandidateEvaluator.sort_best_candidatecCs"||}||}t|||dS)zF Compute and return a `BestCandidateResult` instance. )rr)rrr$rr&r&r6compute_best_candidate*s  z)CandidateEvaluator.compute_best_candidate)NFFNN)FFN)rerfrgrh classmethodr2rrrkr BaseSpecifierrrrr rDrrCandidateSortingKeyrrr$rr&r&r&r6rpsL(  $F rc @seZdZdZd;eeeeeee eeddddZ e deee)j*ee+e.d3d6d7Z/e0eee"d8d9d:Z1dS)?r%zThis finds packages. This is meant to match easy_install's technique for looking for packages, by reading pages and looking for appropriate links. N)link_collectorr<r=format_controlcandidate_prefsr)r*cCsP|durt}|pttt}||_||_||_||_||_||_t|_ dS)a This constructor is primarily meant to be used by the create() class method and from tests. :param format_control: A FormatControl object, used to control the selection of source packages / binary packages when consulting the index and links. :param candidate_prefs: Options to use when creating a CandidateEvaluator object. N) rrrr>_candidate_prefsr@_link_collectorrBr _logged_links)rCrr<r=rrr)r&r&r6rDCszPackageFinder.__init__)rselection_prefsr<r*cCs8|durt}t|j|jd}|||||j|j|jdS)afCreate a PackageFinder. :param selection_prefs: The candidate selection preferences, as a SelectionPreferences object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. N)rr)rrr<r=rr))rrrrr=rr))rrrr<rr&r&r6rjszPackageFinder.creatercCs|jSrn)rBrr&r&r6r<szPackageFinder.target_pythoncCs|jjSrnr search_scoperr&r&r6rszPackageFinder.search_scope)rr*cCs ||j_dSrnr)rCrr&r&r6rscCs|jjSrn)r find_linksrr&r&r6rszPackageFinder.find_linkscCs|jjSrn)r index_urlsrr&r&r6rszPackageFinder.index_urlsccs|jjjD]}t|Vq dSrn)rsessionpip_trusted_originsr )rC host_portr&r&r6 trusted_hostsszPackageFinder.trusted_hostscCs|jjSrnrrrr&r&r6rsz#PackageFinder.allow_all_prereleasescCs d|j_dSNTrrr&r&r6set_allow_all_prereleasessz'PackageFinder.set_allow_all_prereleasescCs|jjSrnrrrr&r&r6rszPackageFinder.prefer_binarycCs d|j_dSrrrr&r&r6set_prefer_binaryszPackageFinder.set_prefer_binary)r9r*cCs.t|}|j|}t||||j|j|jdS)N)r9r:r;r<r=r))r rget_allowed_formatsr8rBr>r@)rCr9r:r;r&r&r6make_link_evaluators z!PackageFinder.make_link_evaluator)linksr*cCsPgg}}t}|D]2}||vr|||jr<||q||q||S)z Returns elements of links in order, non-egg links first, egg links second, while eliminating duplicates )raddrLrw)rCreggsno_eggsseenr'r&r&r6 _sort_linkss    zPackageFinder._sort_links)r'r]r*cCs(||jvr$td|||j|dS)NzSkipping link: %s: %s)rr.r/r)rCr'r]r&r&r6_log_skipped_links zPackageFinder._log_skipped_link)link_evaluatorr'r*cCs8||\}}|s(|r$|j||ddSt|j||dS)z If the link is a candidate for install, convert it to an InstallationCandidate and return it. Otherwise, return None. )r]N)rRr'r5)rdrrr9)rCrr' is_candidateresultr&r&r6get_install_candidatesz#PackageFinder.get_install_candidate)rrr*cCs6g}||D]"}|||}|dur||q|S)zU Convert links that are candidates to InstallationCandidate objects. N)rrrw)rCrrrlr'rpr&r&r6evaluate_linkss   zPackageFinder.evaluate_links) project_urlrr*cCshtd||j|}|dur$gStt|}t|j||d}Wdn1sZ0Y|S)Nz-Fetching project page and analyzing links: %s)r)r.r/r fetch_pagertrrr)rCrr html_page page_links package_linksr&r&r6process_project_urls  $z!PackageFinder.process_project_url)maxsizec Cs||}|jj|tj|j|dd}tjdd|D}t |}tjdd|D}| |t |dd}t tjr|rdd |D}t d d |||S) aFind all available InstallationCandidate for project_name This checks index_urls and find_links. All versions found are returned as an InstallationCandidate list. See LinkEvaluator.evaluate_link() for details on which files are accepted. )r)r9candidates_from_pagecss(|] }|D]}|dur |Vq qdSrn)page_candidatesrosourcesrHr&r&r6rqsz4PackageFinder.find_all_candidates..css(|] }|D]}|dur |Vq qdSrn) file_linksrr&r&r6rq'sT)reversecSsg|]}t|jjqSr&)r#r'urlrr&r&r6r3rrz5PackageFinder.find_all_candidates..zLocal files found: %srG)rrcollect_sources functoolspartialr itertoolschain from_iterablertrrr. isEnabledForloggingDEBUGr/r0) rCr9rcollected_sourcespage_candidates_itr file_links_itfile_candidatespathsr&r&r6find_all_candidates s.    z!PackageFinder.find_all_candidates)r9rrmr*cCs"|j}tj||j|j|j||dS)z*Create a CandidateEvaluator object to use.)r9r<rrrrm)rrrrBrr)rCr9rrmrr&r&r6make_candidate_evaluator9sz&PackageFinder.make_candidate_evaluatorcCs$||}|j|||d}||S)aFind matches for the given project and specifier. :param specifier: An optional object implementing `filter` (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable versions. :return: A `BestCandidateResult` instance. )r9rrm)rrr)rCr9rrmrlcandidate_evaluatorr&r&r6find_best_candidateJs z!PackageFinder.find_best_candidate)requpgrader*c Cs|jdd}|j|j|j|d}|j}d}|jdur@t|jj}tt t ddd}|dur|durt d||| td |d}|r|dus|j|krd }|s|dur|rt d |nt d ||jdS|rt d |||tt d|j|||S)zTry to find a Link matching req Expects req, an InstallRequirement and upgrade, a boolean Returns a InstallationCandidate if found, Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise F)trust_internet)rrmN) cand_iterr*cSs dtdd|DtdpdS)NrGcSsh|]}t|jqSr&rrr&r&r6r~rrzKPackageFinder.find_requirement.._format_versions..rnone)r0r parse_version)rr&r&r6_format_versionsvs z8PackageFinder.find_requirement.._format_versionszNCould not find a version that satisfies the requirement %s (from versions: %s)z%No matching distribution found for {}TzLExisting installed version (%s) is most up-to-date and satisfies requirementzUExisting installed version (%s) satisfies requirement (most up-to-date version is %s)z=Installed version (%s) is most up-to-date (past versions: %s)z)Using version %s (newest of versions: %s))rmrrRrr satisfied_byr r5rrr2r.criticalrrrOr/rr) rCrrrmbest_candidate_resultrinstalled_versionr best_installedr&r&r6find_requirementash       zPackageFinder.find_requirement)NNN)N)NN)NN)2rerfrgrhrrrkrrrrDrrrpropertyr<rrsetterrr2rrrrrrrrr8rrrrrrrrr lru_cacherr rrrrr$rrrr&r&r&r6r%<s  '     0  r%)fragmentr:r*cCsNt|D].\}}|dkrqt|d||kr|Sqt|d|dS)aFind the separator's index based on the package's canonical name. :param fragment: A + filename "fragment" (stem) or egg fragment. :param canonical_name: The package's canonical name. This function is needed since the canonicalized name does not necessarily have the same length as the egg info's name part. An example:: >>> fragment = 'foo__bar-1.0' >>> canonical_name = 'foo-bar' >>> _find_name_version_sep(fragment, canonical_name) 8 -Nz does not match )rr r)rr:irr&r&r6_find_name_version_seps  rcCs@zt||d}Wnty&YdS0||d}|s+ filename "fragment" (stem) or egg fragment. :param fragment: The string to parse. E.g. foo-2.1 :param canonical_name: The canonicalized name of the package this belongs to. rIN)rr)rr: version_startr5r&r&r6rVs  rV)F)PrhrrrritypingrrrrrrrZpip._vendor.packagingr Zpip._vendor.packaging.tagsr pip._vendor.packaging.utilsr Zpip._vendor.packaging.versionr r r pip._internal.exceptionsrrrrpip._internal.index.collectorrrpip._internal.models.candidater#pip._internal.models.format_controlrpip._internal.models.linkr!pip._internal.models.search_scoper$pip._internal.models.selection_prefsr"pip._internal.models.target_pythonrpip._internal.models.wheelrpip._internal.reqrZpip._internal.utils._logrpip._internal.utils.filetypesrpip._internal.utils.hashesrpip._internal.utils.loggingrpip._internal.utils.miscr pip._internal.utils.packagingr!pip._internal.utils.unpackingr"pip._internal.utils.urlsr#__all__rer.rr2BuildTagrrkr7r8r~rr$rr%rrVr&r&r&r6sn$                       /  J(M~PK!>k>>"__pycache__/sources.cpython-39.pycnu[a Re @s0ddlZddlZddlZddlZddlmZmZmZmZddl m Z ddl m Z ddl mZmZddlmZeeZee Zee Zee gee fZee gefZGdddZeed d d ZGd d d eZGdddeZGdddeZGdddeZ eeeeeeeeeefdddZ!dS)N)CallableIterableOptionalTuple)InstallationCandidate)Link) path_to_url url_to_path)is_urlc@s>eZdZeeedddZedddZe dddZ dS) LinkSourcereturncCs tdS)z,Returns the underlying link, if there's one.NNotImplementedErrorselfr/builddir/build/BUILDROOT/alt-python39-pip-21.3.1-2.el8.x86_64/opt/alt/python39/lib/python3.9/site-packages/pip/_internal/index/sources.pylinkszLinkSource.linkcCs tdS)z9Candidates found by parsing an archive listing HTML file.Nrrrrrpage_candidatesszLinkSource.page_candidatescCs tdS)z,Links found by specifying archives directly.Nrrrrr file_linksszLinkSource.file_linksN) __name__ __module__ __qualname__propertyrrrFoundCandidatesr FoundLinksrrrrrr sr )file_urlr cCstj|ddddkS)NF)strictrz text/html) mimetypes guess_type)rrrr _is_html_file#sr!c@sTeZdZdZeeddddZeee dddZ e dd d Z e dd d ZdS) _FlatDirectorySourcezLink source specified by ``--find-links=``. This looks the content of the directory, and returns: * ``page_candidates``: Links listed on each HTML file in the directory. * ``file_candidates``: Archives in the directory. N)candidates_from_pagepathr cCs||_ttj||_dSN)_candidates_from_pagepathlibPathosr$realpath_path)rr#r$rrr__init__0sz_FlatDirectorySource.__init__r cCsdSr%rrrrrr8sz_FlatDirectorySource.linkccs>|jD].}tt|}t|s$q |t|EdHq dSr%)r+iterdirrstrr!r&rrr$urlrrrr<s  z$_FlatDirectorySource.page_candidatesccs4|jD]$}tt|}t|r$q t|Vq dSr%)r+r-rr.r!rr/rrrrCs  z_FlatDirectorySource.file_links)rrr__doc__CandidatesFromPager.r,rrrrrrrrrrrrr"'s  r"c@sTeZdZdZeeddddZeeedddZ e dd d Z e dd d Z dS) _LocalFileSourceaC``--find-links=`` or ``--[extra-]index-url=``. If a URL is supplied, it must be a ``file:`` URL. If a path is supplied to the option, it is converted to a URL first. This returns: * ``page_candidates``: Links listed on an HTML file. * ``file_candidates``: The non-HTML file. Nr#rr cCs||_||_dSr%r&_linkrr#rrrrr,Usz_LocalFileSource.__init__r cCs|jSr%r6rrrrr]sz_LocalFileSource.linkccs&t|jjsdS||jEdHdSr%)r!r6r0r&rrrrras z _LocalFileSource.page_candidatesccst|jjrdS|jVdSr%)r!r6r0rrrrrfs z_LocalFileSource.file_linksrrrr1r2rr,rrrrrrrrrrrr3Ks  r3c@sVeZdZdZeeeddddZee edddZ e dd d Z e dd d ZdS) _RemoteFileSourcez``--find-links=`` or ``--[extra-]index-url=``. This returns: * ``page_candidates``: Links listed on an HTML file. * ``file_candidates``: The non-HTML file. N)r#page_validatorrr cCs||_||_||_dSr%)r&_page_validatorr6)rr#r;rrrrr,usz_RemoteFileSource.__init__r cCs|jSr%r8rrrrrsz_RemoteFileSource.linkccs&||jsdS||jEdHdSr%)r<r6r&rrrrrs z!_RemoteFileSource.page_candidatesccs |jVdSr%r8rrrrrsz_RemoteFileSource.file_links)rrrr1r2 PageValidatorrr,rrrrrrrrrrrr:ls  r:c@sTeZdZdZeeddddZeeedddZ e dd d Z e dd d Z dS) _IndexDirectorySourcez``--[extra-]index-url=``. This is treated like a remote URL; ``candidates_from_page`` contains logic for this by appending ``index.html`` to the link. Nr4cCs||_||_dSr%r5r7rrrr,sz_IndexDirectorySource.__init__r cCs|jSr%r8rrrrrsz_IndexDirectorySource.linkccs||jEdHdSr%r5rrrrrsz%_IndexDirectorySource.page_candidatescCsdS)Nrrrrrrrsz _IndexDirectorySource.file_linksr9rrrrr>s r>)locationr#r; expand_dircache_link_parsingr c Csd}d}tj|r"t|}|}n$|dr:|}t|}n t|rF|}|durbd}t||dS|durt ||t ||dd}||fStj |r|rt ||d}nt |t ||dd}||fStj|rt|t ||dd}||fStd||dfS) Nzfile:zVLocation '%s' is ignored: it is either a non-existing path or lacks a specific scheme.)NN)rA)r#r;r)r#r$)r#rz?Location '%s' is ignored: it is neither a file nor a directory.)r)r$existsr startswithr r loggerwarningr:risdirr"r>isfiler3) r?r#r;r@rAr$r0msgsourcerrr build_sourcesX          rJ)"loggingrr)r'typingrrrrpip._internal.models.candidaterpip._internal.models.linkrpip._internal.utils.urlsrr pip._internal.vcsr getLoggerrrDrrr2boolr=r r.r!r"r3r:r>rJrrrrs4    $! PK!Srl  #__pycache__/__init__.cpython-39.pycnu[a Re@sdZdS)zIndex interaction code N)__doc__rr/builddir/build/BUILDROOT/alt-python39-pip-21.3.1-2.el8.x86_64/opt/alt/python39/lib/python3.9/site-packages/pip/_internal/index/__init__.pyPK!/>/>$__pycache__/collector.cpython-39.pycnu[a Re~D@sdZddlZddlZddlZddlZddlZddlZddlZddlZ ddl Z ddl Z ddl mZddlmZmZmZmZmZmZmZmZddlmZmZddlmZddlmZmZddl m!Z!dd l"m#Z#dd l$m%Z%dd l&m'Z'dd l(m)Z)dd l*m+Z+ddl,m-Z-m.Z.ddl/m0Z0ddl1m2Z2m3Z3m4Z4e5e6Z7e j8j9j:Z;eeGddde?Z@eddddZAGddde?ZBed7d7ZSdNe#eeLsr>)rsessionrcCsFtj|\}}}}}|dvr$t|j|dd}t|t|dS)zSend a HEAD request to the URL, and ensure the response contains HTML. Raises `_NotHTTP` if the URL is not available for a HEAD request, or `_NotHTML` if the content type is not text/html. >httphttpsT)allow_redirectsN)urllibparseurlsplitr>headrr=)rr?r#netlocpathqueryfragmentrespr$r$r%_ensure_html_responsePs rLcCsRtt|jrt||dtdt||j|dddd}t|t ||S)aAccess an HTML page with GET, and return the response. This consists of three parts: 1. If the URL looks suspiciously like an archive, send a HEAD first to check the Content-Type is HTML, to avoid downloading a large file. Raise `_NotHTTP` if the content type cannot be determined, or `_NotHTML` if it is not HTML. 2. Actually perform the request. Raise HTTP exceptions on network failures. 3. Check the Content-Type header to make sure we got HTML, and raise `_NotHTML` otherwise. r?zGetting page %sr8z max-age=0)Acceptz Cache-Control)r9) rrfilenamerLloggerdebugrr:rr=)rr?rKr$r$r%_get_html_response`s  rR)r9rcCs2|r.d|vr.t|d\}}d|vr.|dSdS)z=Determine if we have any encoding information in our headers.r6charsetN)cgi parse_header)r9r(paramsr$r$r%_get_encoding_from_headerss  rW)documentpage_urlrcCs.|dD]}|d}|dur |Sq |S)aDetermine the HTML document's base URL. This looks for a ```` tag in the HTML document. If present, its href attribute denotes the base URL of anchor tags in the document. If there is no such tag (or if it does not have a valid href attribute), the HTML file's URL is used as the base URL. :param document: An HTML document representation. The current implementation expects the result of ``html5lib.parse()``. :param page_url: The URL of the HTML document. z.//basehrefN)findallr:)rXrYbaserZr$r$r%_determine_base_urls   r])partrcCstjtj|S)zP Clean a "part" of a URL path (i.e. after splitting on "@" characters). )rCrDquoteunquoter^r$r$r%_clean_url_path_partsrbcCstjtj|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). )rCr; pathname2url url2pathnamerar$r$r%_clean_file_url_paths rez(@|%2F))rH is_local_pathrcCs^|r t}nt}t|}g}tt|dgD]$\}}|||||q.d |S)z* Clean the path portion of a URL. r7) rerb_reserved_chars_resplitr itertoolschainappendupperjoin)rHrf clean_funcparts cleaned_partsto_cleanreservedr$r$r%_clean_url_paths rscCs6tj|}|j }t|j|d}tj|j|dS)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. )rf)rH)rCrDurlparserGrsrH urlunparse_replace)rresultrfrHr$r$r% _clean_links rx)anchorrYbase_urlrcCsL|d}|sdSttj||}|d}|d}t||||d}|S)zJ Convert an anchor element in a simple repository page to a Link. rZNzdata-requires-pythonz data-yanked) comes_fromrequires_python yanked_reason)r:rxrCrDurljoinr)ryrYrzrZr pyrequirer}linkr$r$r%_create_link_from_elements   rc@s:eZdZdddddZeedddZed d d ZdS) CacheablePageContentHTMLPageNpagercCs|js J||_dSr*)cache_link_parsingr)r-rr$r$r%r,s zCacheablePageContent.__init__)otherrcCst|t|o|jj|jjkSr*) isinstancetyperr)r-rr$r$r%__eq__ szCacheablePageContent.__eq__rcCs t|jjSr*)hashrrr-r$r$r%__hash__szCacheablePageContent.__hash__) r0r1r2r,objectboolrintrr$r$r$r%rsrr)fnrcsLtjddtttdfdd tdttdfdd }|S) z Given a function that parses an Iterable[Link] from an HTMLPage, cache the function's result (keyed by CacheablePageContent), unless the HTMLPage `page` has `page.cache_link_parsing == False`. N)maxsize)cacheable_pagercst|jSr*)listr)r)rr$r%wrappersz'with_cached_html_pages..wrapperrrcs|jrt|St|Sr*)rrr)rrrr$r%wrapper_wrappers z/with_cached_html_pages..wrapper_wrapper) functools lru_cacherrrwraps)rrr$rr%with_cached_html_pagess rrccsVtj|j|jdd}|j}t||}|dD]"}t|||d}|durJq.|Vq.dS)zP Parse an HTML document, and yield its anchor elements as Link objects. F)transport_encodingnamespaceHTMLElementsz.//a)rYrzN)r rDcontentencodingrr]r[r)rrXrrzryrr$r$r% parse_links(s  rc@s:eZdZdZd eeeeeddddZeddd Z dS) rz'Represents one page, along with its URLTN)rrrrrcCs||_||_||_||_dS)am :param encoding: the encoding to decode the given content. :param url: the URL from which the HTML was downloaded. :param cache_link_parsing: whether links parsed from this page's url should be cached. PyPI index urls should have this set to False, for example. N)rrrr)r-rrrrr$r$r%r,CszHTMLPage.__init__rcCs t|jSr*)rrrr$r$r%__str__VszHTMLPage.__str__)T) r0r1r2__doc__bytesrr3rr,rr$r$r$r%r@s ).N)rreasonmethrcCs|durtj}|d||dS)Nz%Could not fetch URL %s: %s - skipping)rPrQ)rrrr$r$r%_handle_get_page_failZsrT)r5rrcCst|j}t|j||j|dS)N)rrr)rWr9rrr)r5rrr$r$r%_make_html_pageds r)rr?rc Cs|durtd|jddd}t|}|r@td||dStj|\}}}}}}|dkrt j tj |r|ds|d7}tj|d}td |zt||d }WnNtytd |Yn>ty }z"td ||j|jWYd}~n d}~0ty:}zt||WYd}~nd}~0tyh}zt||WYd}~nd}~0ty}z,d } | t|7} t|| tjdWYd}~nld}~0tjy}zt|d|WYd}~n6d}~0tjyt|dYn0t||j dSdS)Nz?_get_html_page() missing 1 required keyword argument: 'session'#rrzICannot look at %s URL %s because it does not support lookup as web pages.file/z index.htmlz# file: URL is directory, getting %srMz`Skipping page %s because it looks like an archive, and cannot be checked by a HTTP HEAD request.ziSkipping page %s because the %s request got Content-Type: %s.The only supported Content-Type is text/htmlz4There was a problem confirming the ssl certificate: )rzconnection error: z timed out)r)! TypeErrorrrhr&rPwarningrCrDrtosrHisdirr;rdendswithr~rQrRr>r'r)r(rrrrr3infor ConnectionErrorTimeoutrr) rr?r vcs_schemer#_rHrKexcrr$r$r%_get_html_pagens^     $$rc@s.eZdZUeeeed<eeeed<dS)CollectedSources find_links index_urlsN)r0r1r2r rr__annotations__r$r$r$r%rs rc@sxeZdZdZeeddddZedeee dddd Z e e e d d d Zeeed ddZe eedddZdS) LinkCollectorz Responsible for collecting Link objects from all configured locations, making network requests as needed. The class's main method is its collect_sources() method. N)r? search_scopercCs||_||_dSr*)rr?)r-r?rr$r$r%r,szLinkCollector.__init__F)r?optionssuppress_no_indexrcCs`|jg|j}|jr8|s8tdddd|Dg}|jp@g}tj||d}t ||d}|S)z :param session: The Session to use to make requests. :param suppress_no_index: Whether to ignore the --no-index option when constructing the SearchScope object. zIgnoring indexes: %s,css|]}t|VqdSr*)r).0rr$r$r% z'LinkCollector.create..rr)r?r) index_urlextra_index_urlsno_indexrPrQrmrrcreater)clsr?rrrrrlink_collectorr$r$r%rs"   zLinkCollector.creatercCs|jjSr*)rrrr$r$r%rszLinkCollector.find_links)locationrcCst||jdS)z> Fetch an HTML page containing package links. rM)rr?)r-rr$r$r% fetch_pageszLinkCollector.fetch_page) project_namecandidates_from_pagercstfddj|D}tfddjD}ttj rddt ||D}t |d|dg|}t d|tt|t|d S) Nc3s$|]}t|jjdddVqdS)Frpage_validator expand_dirrNrr?is_secure_originrlocrr-r$r%rsz0LinkCollector.collect_sources..c3s$|]}t|jjdddVqdS)TrNrrrr$r%rscSs*g|]"}|dur|jdurd|jqS)Nz* )r)rsr$r$r% sz1LinkCollector.collect_sources..z' location(s) to search for versions of : r) collections OrderedDictrget_index_urls_locationsvaluesrrP isEnabledForloggingDEBUGrirjr"rQrmrr)r-rrindex_url_sourcesfind_links_sourceslinesr$rr%collect_sourcess*    zLinkCollector.collect_sources)F)r0r1r2rrrr, classmethodrrrpropertyrr3rrrrrrrrr$r$r$r%rs(   r)N)T)N)YrrTrrrirrre urllib.parserCurllib.requestxml.etree.ElementTreexmloptparsertypingrrrrrrr r pip._vendorr r Zpip._vendor.requestsr Zpip._vendor.requests.exceptionsrrpip._internal.exceptionsrpip._internal.models.linkr!pip._internal.models.search_scoperpip._internal.network.sessionrpip._internal.network.utilsrpip._internal.utils.filetypesrpip._internal.utils.miscrrpip._internal.vcsrsourcesrrr getLoggerr0rPetree ElementTreeElement HTMLElementr3ResponseHeadersr& Exceptionr'r=r>rLrRrWr]rbrecompile IGNORECASErgrrsrxrrrrrrrrrrr$r$r$r%s (              2         ?PK!+ sources.pynu[import logging import mimetypes import os import pathlib from typing import Callable, Iterable, Optional, Tuple from pip._internal.models.candidate import InstallationCandidate from pip._internal.models.link import Link from pip._internal.utils.urls import path_to_url, url_to_path from pip._internal.vcs import is_url logger = logging.getLogger(__name__) FoundCandidates = Iterable[InstallationCandidate] FoundLinks = Iterable[Link] CandidatesFromPage = Callable[[Link], Iterable[InstallationCandidate]] PageValidator = Callable[[Link], bool] class LinkSource: @property def link(self) -> Optional[Link]: """Returns the underlying link, if there's one.""" raise NotImplementedError() def page_candidates(self) -> FoundCandidates: """Candidates found by parsing an archive listing HTML file.""" raise NotImplementedError() def file_links(self) -> FoundLinks: """Links found by specifying archives directly.""" raise NotImplementedError() def _is_html_file(file_url: str) -> bool: return mimetypes.guess_type(file_url, strict=False)[0] == "text/html" class _FlatDirectorySource(LinkSource): """Link source specified by ``--find-links=``. This looks the content of the directory, and returns: * ``page_candidates``: Links listed on each HTML file in the directory. * ``file_candidates``: Archives in the directory. """ def __init__( self, candidates_from_page: CandidatesFromPage, path: str, ) -> None: self._candidates_from_page = candidates_from_page self._path = pathlib.Path(os.path.realpath(path)) @property def link(self) -> Optional[Link]: return None def page_candidates(self) -> FoundCandidates: for path in self._path.iterdir(): url = path_to_url(str(path)) if not _is_html_file(url): continue yield from self._candidates_from_page(Link(url)) def file_links(self) -> FoundLinks: for path in self._path.iterdir(): url = path_to_url(str(path)) if _is_html_file(url): continue yield Link(url) class _LocalFileSource(LinkSource): """``--find-links=`` or ``--[extra-]index-url=``. If a URL is supplied, it must be a ``file:`` URL. If a path is supplied to the option, it is converted to a URL first. This returns: * ``page_candidates``: Links listed on an HTML file. * ``file_candidates``: The non-HTML file. """ def __init__( self, candidates_from_page: CandidatesFromPage, link: Link, ) -> None: self._candidates_from_page = candidates_from_page self._link = link @property def link(self) -> Optional[Link]: return self._link def page_candidates(self) -> FoundCandidates: if not _is_html_file(self._link.url): return yield from self._candidates_from_page(self._link) def file_links(self) -> FoundLinks: if _is_html_file(self._link.url): return yield self._link class _RemoteFileSource(LinkSource): """``--find-links=`` or ``--[extra-]index-url=``. This returns: * ``page_candidates``: Links listed on an HTML file. * ``file_candidates``: The non-HTML file. """ def __init__( self, candidates_from_page: CandidatesFromPage, page_validator: PageValidator, link: Link, ) -> None: self._candidates_from_page = candidates_from_page self._page_validator = page_validator self._link = link @property def link(self) -> Optional[Link]: return self._link def page_candidates(self) -> FoundCandidates: if not self._page_validator(self._link): return yield from self._candidates_from_page(self._link) def file_links(self) -> FoundLinks: yield self._link class _IndexDirectorySource(LinkSource): """``--[extra-]index-url=``. This is treated like a remote URL; ``candidates_from_page`` contains logic for this by appending ``index.html`` to the link. """ def __init__( self, candidates_from_page: CandidatesFromPage, link: Link, ) -> None: self._candidates_from_page = candidates_from_page self._link = link @property def link(self) -> Optional[Link]: return self._link def page_candidates(self) -> FoundCandidates: yield from self._candidates_from_page(self._link) def file_links(self) -> FoundLinks: return () def build_source( location: str, *, candidates_from_page: CandidatesFromPage, page_validator: PageValidator, expand_dir: bool, cache_link_parsing: bool, ) -> Tuple[Optional[str], Optional[LinkSource]]: path: Optional[str] = None url: Optional[str] = None if os.path.exists(location): # Is a local path. url = path_to_url(location) path = location elif location.startswith("file:"): # A file: URL. url = location path = url_to_path(location) elif is_url(location): url = location if url is None: msg = ( "Location '%s' is ignored: " "it is either a non-existing path or lacks a specific scheme." ) logger.warning(msg, location) return (None, None) if path is None: source: LinkSource = _RemoteFileSource( candidates_from_page=candidates_from_page, page_validator=page_validator, link=Link(url, cache_link_parsing=cache_link_parsing), ) return (url, source) if os.path.isdir(path): if expand_dir: source = _FlatDirectorySource( candidates_from_page=candidates_from_page, path=path, ) else: source = _IndexDirectorySource( candidates_from_page=candidates_from_page, link=Link(url, cache_link_parsing=cache_link_parsing), ) return (url, source) elif os.path.isfile(path): source = _LocalFileSource( candidates_from_page=candidates_from_page, link=Link(url, cache_link_parsing=cache_link_parsing), ) return (url, source) logger.warning( "Location '%s' is ignored: it is neither a file nor a directory.", location, ) return (url, None) PK!I~D~D collector.pynu[""" The main purpose of this module is to expose LinkCollector.collect_sources(). """ import cgi import collections import functools import itertools import logging import os import re import urllib.parse import urllib.request import xml.etree.ElementTree from optparse import Values from typing import ( Callable, Iterable, List, MutableMapping, NamedTuple, Optional, Sequence, Union, ) from pip._vendor import html5lib, requests from pip._vendor.requests import Response from pip._vendor.requests.exceptions import RetryError, SSLError from pip._internal.exceptions import NetworkConnectionError from pip._internal.models.link import Link from pip._internal.models.search_scope import SearchScope from pip._internal.network.session import PipSession from pip._internal.network.utils import raise_for_status from pip._internal.utils.filetypes import is_archive_file from pip._internal.utils.misc import pairwise, redact_auth_from_url from pip._internal.vcs import vcs from .sources import CandidatesFromPage, LinkSource, build_source logger = logging.getLogger(__name__) HTMLElement = xml.etree.ElementTree.Element ResponseHeaders = MutableMapping[str, str] def _match_vcs_scheme(url: str) -> Optional[str]: """Look for VCS schemes in the URL. Returns the matched VCS scheme, or None if there's no match. """ for scheme in vcs.schemes: if url.lower().startswith(scheme) and url[len(scheme)] in "+:": return scheme return None class _NotHTML(Exception): def __init__(self, content_type: str, request_desc: str) -> None: super().__init__(content_type, request_desc) self.content_type = content_type self.request_desc = request_desc def _ensure_html_header(response: Response) -> None: """Check the Content-Type header to ensure the response contains HTML. Raises `_NotHTML` if the content type is not text/html. """ content_type = response.headers.get("Content-Type", "") if not content_type.lower().startswith("text/html"): raise _NotHTML(content_type, response.request.method) class _NotHTTP(Exception): pass def _ensure_html_response(url: str, session: PipSession) -> None: """Send a HEAD request to the URL, and ensure the response contains HTML. Raises `_NotHTTP` if the URL is not available for a HEAD request, or `_NotHTML` if the content type is not text/html. """ scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url) if scheme not in {"http", "https"}: raise _NotHTTP() resp = session.head(url, allow_redirects=True) raise_for_status(resp) _ensure_html_header(resp) def _get_html_response(url: str, session: PipSession) -> Response: """Access an HTML page with GET, and return the response. This consists of three parts: 1. If the URL looks suspiciously like an archive, send a HEAD first to check the Content-Type is HTML, to avoid downloading a large file. Raise `_NotHTTP` if the content type cannot be determined, or `_NotHTML` if it is not HTML. 2. Actually perform the request. Raise HTTP exceptions on network failures. 3. Check the Content-Type header to make sure we got HTML, and raise `_NotHTML` otherwise. """ if is_archive_file(Link(url).filename): _ensure_html_response(url, session=session) logger.debug("Getting page %s", redact_auth_from_url(url)) resp = session.get( url, headers={ "Accept": "text/html", # We don't want to blindly returned cached data for # /simple/, because authors generally expecting that # twine upload && pip install will function, but if # they've done a pip install in the last ~10 minutes # it won't. Thus by setting this to zero we will not # blindly use any cached data, however the benefit of # using max-age=0 instead of no-cache, is that we will # still support conditional requests, so we will still # minimize traffic sent in cases where the page hasn't # changed at all, we will just always incur the round # trip for the conditional GET now instead of only # once per 10 minutes. # For more information, please see pypa/pip#5670. "Cache-Control": "max-age=0", }, ) raise_for_status(resp) # The check for archives above only works if the url ends with # something that looks like an archive. However that is not a # requirement of an url. Unless we issue a HEAD request on every # url we cannot know ahead of time for sure if something is HTML # or not. However we can check after we've downloaded it. _ensure_html_header(resp) return resp def _get_encoding_from_headers(headers: ResponseHeaders) -> Optional[str]: """Determine if we have any encoding information in our headers.""" if headers and "Content-Type" in headers: content_type, params = cgi.parse_header(headers["Content-Type"]) if "charset" in params: return params["charset"] return None def _determine_base_url(document: HTMLElement, page_url: str) -> str: """Determine the HTML document's base URL. This looks for a ```` tag in the HTML document. If present, its href attribute denotes the base URL of anchor tags in the document. If there is no such tag (or if it does not have a valid href attribute), the HTML file's URL is used as the base URL. :param document: An HTML document representation. The current implementation expects the result of ``html5lib.parse()``. :param page_url: The URL of the HTML document. """ for base in document.findall(".//base"): href = base.get("href") if href is not None: return href return page_url def _clean_url_path_part(part: str) -> str: """ Clean a "part" of a URL path (i.e. after splitting on "@" characters). """ # We unquote prior to quoting to make sure nothing is double quoted. return urllib.parse.quote(urllib.parse.unquote(part)) def _clean_file_url_path(part: str) -> str: """ Clean the first part of a URL path that corresponds to a local filesystem path (i.e. the first part after splitting on "@" characters). """ # We unquote prior to quoting to make sure nothing is double quoted. # Also, on Windows the path part might contain a drive letter which # should not be quoted. On Linux where drive letters do not # exist, the colon should be quoted. We rely on urllib.request # to do the right thing here. return urllib.request.pathname2url(urllib.request.url2pathname(part)) # percent-encoded: / _reserved_chars_re = re.compile("(@|%2F)", re.IGNORECASE) def _clean_url_path(path: str, is_local_path: bool) -> str: """ Clean the path portion of a URL. """ if is_local_path: clean_func = _clean_file_url_path else: clean_func = _clean_url_path_part # Split on the reserved characters prior to cleaning so that # revision strings in VCS URLs are properly preserved. parts = _reserved_chars_re.split(path) cleaned_parts = [] for to_clean, reserved in pairwise(itertools.chain(parts, [""])): cleaned_parts.append(clean_func(to_clean)) # Normalize %xx escapes (e.g. %2f -> %2F) cleaned_parts.append(reserved.upper()) return "".join(cleaned_parts) def _clean_link(url: str) -> str: """ 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. """ # Split the URL into parts according to the general structure # `scheme://netloc/path;parameters?query#fragment`. result = urllib.parse.urlparse(url) # If the netloc is empty, then the URL refers to a local filesystem path. is_local_path = not result.netloc path = _clean_url_path(result.path, is_local_path=is_local_path) return urllib.parse.urlunparse(result._replace(path=path)) def _create_link_from_element( anchor: HTMLElement, page_url: str, base_url: str, ) -> Optional[Link]: """ Convert an anchor element in a simple repository page to a Link. """ href = anchor.get("href") if not href: return None url = _clean_link(urllib.parse.urljoin(base_url, href)) pyrequire = anchor.get("data-requires-python") yanked_reason = anchor.get("data-yanked") link = Link( url, comes_from=page_url, requires_python=pyrequire, yanked_reason=yanked_reason, ) return link class CacheablePageContent: def __init__(self, page: "HTMLPage") -> None: assert page.cache_link_parsing self.page = page def __eq__(self, other: object) -> bool: return isinstance(other, type(self)) and self.page.url == other.page.url def __hash__(self) -> int: return hash(self.page.url) def with_cached_html_pages( fn: Callable[["HTMLPage"], Iterable[Link]], ) -> Callable[["HTMLPage"], List[Link]]: """ Given a function that parses an Iterable[Link] from an HTMLPage, cache the function's result (keyed by CacheablePageContent), unless the HTMLPage `page` has `page.cache_link_parsing == False`. """ @functools.lru_cache(maxsize=None) def wrapper(cacheable_page: CacheablePageContent) -> List[Link]: return list(fn(cacheable_page.page)) @functools.wraps(fn) def wrapper_wrapper(page: "HTMLPage") -> List[Link]: if page.cache_link_parsing: return wrapper(CacheablePageContent(page)) return list(fn(page)) return wrapper_wrapper @with_cached_html_pages def parse_links(page: "HTMLPage") -> Iterable[Link]: """ Parse an HTML document, and yield its anchor elements as Link objects. """ document = html5lib.parse( page.content, transport_encoding=page.encoding, namespaceHTMLElements=False, ) url = page.url base_url = _determine_base_url(document, url) for anchor in document.findall(".//a"): link = _create_link_from_element( anchor, page_url=url, base_url=base_url, ) if link is None: continue yield link class HTMLPage: """Represents one page, along with its URL""" def __init__( self, content: bytes, encoding: Optional[str], url: str, cache_link_parsing: bool = True, ) -> None: """ :param encoding: the encoding to decode the given content. :param url: the URL from which the HTML was downloaded. :param cache_link_parsing: whether links parsed from this page's url should be cached. PyPI index urls should have this set to False, for example. """ self.content = content self.encoding = encoding self.url = url self.cache_link_parsing = cache_link_parsing def __str__(self) -> str: return redact_auth_from_url(self.url) def _handle_get_page_fail( link: Link, reason: Union[str, Exception], meth: Optional[Callable[..., None]] = None, ) -> None: if meth is None: meth = logger.debug meth("Could not fetch URL %s: %s - skipping", link, reason) def _make_html_page(response: Response, cache_link_parsing: bool = True) -> HTMLPage: encoding = _get_encoding_from_headers(response.headers) return HTMLPage( response.content, encoding=encoding, url=response.url, cache_link_parsing=cache_link_parsing, ) def _get_html_page( link: Link, session: Optional[PipSession] = None ) -> Optional["HTMLPage"]: if session is None: raise TypeError( "_get_html_page() missing 1 required keyword argument: 'session'" ) url = link.url.split("#", 1)[0] # Check for VCS schemes that do not support lookup as web pages. vcs_scheme = _match_vcs_scheme(url) if vcs_scheme: logger.warning( "Cannot look at %s URL %s because it does not support lookup as web pages.", vcs_scheme, link, ) return None # Tack index.html onto file:// URLs that point to directories scheme, _, path, _, _, _ = urllib.parse.urlparse(url) if scheme == "file" and os.path.isdir(urllib.request.url2pathname(path)): # add trailing slash if not present so urljoin doesn't trim # final segment if not url.endswith("/"): url += "/" url = urllib.parse.urljoin(url, "index.html") logger.debug(" file: URL is directory, getting %s", url) try: resp = _get_html_response(url, session=session) except _NotHTTP: logger.warning( "Skipping page %s because it looks like an archive, and cannot " "be checked by a HTTP HEAD request.", link, ) except _NotHTML as exc: logger.warning( "Skipping page %s because the %s request got Content-Type: %s." "The only supported Content-Type is text/html", link, exc.request_desc, exc.content_type, ) except NetworkConnectionError as exc: _handle_get_page_fail(link, exc) except RetryError as exc: _handle_get_page_fail(link, exc) except SSLError as exc: reason = "There was a problem confirming the ssl certificate: " reason += str(exc) _handle_get_page_fail(link, reason, meth=logger.info) except requests.ConnectionError as exc: _handle_get_page_fail(link, f"connection error: {exc}") except requests.Timeout: _handle_get_page_fail(link, "timed out") else: return _make_html_page(resp, cache_link_parsing=link.cache_link_parsing) return None class CollectedSources(NamedTuple): find_links: Sequence[Optional[LinkSource]] index_urls: Sequence[Optional[LinkSource]] class LinkCollector: """ Responsible for collecting Link objects from all configured locations, making network requests as needed. The class's main method is its collect_sources() method. """ def __init__( self, session: PipSession, search_scope: SearchScope, ) -> None: self.search_scope = search_scope self.session = session @classmethod def create( cls, session: PipSession, options: Values, suppress_no_index: bool = False, ) -> "LinkCollector": """ :param session: The Session to use to make requests. :param suppress_no_index: Whether to ignore the --no-index option when constructing the SearchScope object. """ index_urls = [options.index_url] + options.extra_index_urls if options.no_index and not suppress_no_index: logger.debug( "Ignoring indexes: %s", ",".join(redact_auth_from_url(url) for url in index_urls), ) index_urls = [] # Make sure find_links is a list before passing to create(). find_links = options.find_links or [] search_scope = SearchScope.create( find_links=find_links, index_urls=index_urls, ) link_collector = LinkCollector( session=session, search_scope=search_scope, ) return link_collector @property def find_links(self) -> List[str]: return self.search_scope.find_links def fetch_page(self, location: Link) -> Optional[HTMLPage]: """ Fetch an HTML page containing package links. """ return _get_html_page(location, session=self.session) def collect_sources( self, project_name: str, candidates_from_page: CandidatesFromPage, ) -> CollectedSources: # The OrderedDict calls deduplicate sources by URL. index_url_sources = collections.OrderedDict( build_source( loc, candidates_from_page=candidates_from_page, page_validator=self.session.is_secure_origin, expand_dir=False, cache_link_parsing=False, ) for loc in self.search_scope.get_index_urls_locations(project_name) ).values() find_links_sources = collections.OrderedDict( build_source( loc, candidates_from_page=candidates_from_page, page_validator=self.session.is_secure_origin, expand_dir=True, cache_link_parsing=True, ) for loc in self.find_links ).values() if logger.isEnabledFor(logging.DEBUG): lines = [ f"* {s.link}" for s in itertools.chain(find_links_sources, index_url_sources) if s is not None and s.link is not None ] lines = [ f"{len(lines)} location(s) to search " f"for versions of {project_name}:" ] + lines logger.debug("\n".join(lines)) return CollectedSources( find_links=list(find_links_sources), index_urls=list(index_url_sources), ) PK!C?K __init__.pynu["""Index interaction code """ PK!Wpackage_finder.pynu["""Routines related to PyPI, indexes""" # The following comment should be removed at some point in the future. # mypy: strict-optional=False import functools import itertools import logging import re from typing import FrozenSet, Iterable, List, Optional, Set, Tuple, Union from pip._vendor.packaging import specifiers from pip._vendor.packaging.tags import Tag from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.packaging.version import _BaseVersion from pip._vendor.packaging.version import parse as parse_version from pip._internal.exceptions import ( BestVersionAlreadyInstalled, DistributionNotFound, InvalidWheelFilename, UnsupportedWheel, ) from pip._internal.index.collector import LinkCollector, parse_links from pip._internal.models.candidate import InstallationCandidate from pip._internal.models.format_control import FormatControl from pip._internal.models.link import Link from pip._internal.models.search_scope import SearchScope from pip._internal.models.selection_prefs import SelectionPreferences from pip._internal.models.target_python import TargetPython from pip._internal.models.wheel import Wheel from pip._internal.req import InstallRequirement from pip._internal.utils._log import getLogger from pip._internal.utils.filetypes import WHEEL_EXTENSION from pip._internal.utils.hashes import Hashes from pip._internal.utils.logging import indent_log from pip._internal.utils.misc import build_netloc from pip._internal.utils.packaging import check_requires_python from pip._internal.utils.unpacking import SUPPORTED_EXTENSIONS from pip._internal.utils.urls import url_to_path __all__ = ["FormatControl", "BestCandidateResult", "PackageFinder"] logger = getLogger(__name__) BuildTag = Union[Tuple[()], Tuple[int, str]] CandidateSortingKey = Tuple[int, int, int, _BaseVersion, Optional[int], BuildTag] def _check_link_requires_python( link: Link, version_info: Tuple[int, int, int], ignore_requires_python: bool = False, ) -> bool: """ Return whether the given Python version is compatible with a link's "Requires-Python" value. :param version_info: A 3-tuple of ints representing the Python major-minor-micro version to check. :param ignore_requires_python: Whether to ignore the "Requires-Python" value if the given Python version isn't compatible. """ try: is_compatible = check_requires_python( link.requires_python, version_info=version_info, ) except specifiers.InvalidSpecifier: logger.debug( "Ignoring invalid Requires-Python (%r) for link: %s", link.requires_python, link, ) else: if not is_compatible: version = ".".join(map(str, version_info)) if not ignore_requires_python: logger.verbose( "Link requires a different Python (%s not in: %r): %s", version, link.requires_python, link, ) return False logger.debug( "Ignoring failed Requires-Python check (%s not in: %r) for link: %s", version, link.requires_python, link, ) return True class LinkEvaluator: """ Responsible for evaluating links for a particular project. """ _py_version_re = re.compile(r"-py([123]\.?[0-9]?)$") # Don't include an allow_yanked default value to make sure each call # site considers whether yanked releases are allowed. This also causes # that decision to be made explicit in the calling code, which helps # people when reading the code. def __init__( self, project_name: str, canonical_name: str, formats: FrozenSet[str], target_python: TargetPython, allow_yanked: bool, ignore_requires_python: Optional[bool] = None, ) -> None: """ :param project_name: The user supplied package name. :param canonical_name: The canonical package name. :param formats: The formats allowed for this package. Should be a set with 'binary' or 'source' or both in it. :param target_python: The target Python interpreter to use when evaluating link compatibility. This is used, for example, to check wheel compatibility, as well as when checking the Python version, e.g. the Python version embedded in a link filename (or egg fragment) and against an HTML link's optional PEP 503 "data-requires-python" attribute. :param allow_yanked: Whether files marked as yanked (in the sense of PEP 592) are permitted to be candidates for install. :param ignore_requires_python: Whether to ignore incompatible PEP 503 "data-requires-python" values in HTML links. Defaults to False. """ if ignore_requires_python is None: ignore_requires_python = False self._allow_yanked = allow_yanked self._canonical_name = canonical_name self._ignore_requires_python = ignore_requires_python self._formats = formats self._target_python = target_python self.project_name = project_name def evaluate_link(self, link: Link) -> Tuple[bool, Optional[str]]: """ Determine whether a link is a candidate for installation. :return: A tuple (is_candidate, result), where `result` is (1) a version string if `is_candidate` is True, and (2) if `is_candidate` is False, an optional string to log the reason the link fails to qualify. """ version = None if link.is_yanked and not self._allow_yanked: reason = link.yanked_reason or "" return (False, f"yanked for reason: {reason}") if link.egg_fragment: egg_info = link.egg_fragment ext = link.ext else: egg_info, ext = link.splitext() if not ext: return (False, "not a file") if ext not in SUPPORTED_EXTENSIONS: return (False, f"unsupported archive format: {ext}") if "binary" not in self._formats and ext == WHEEL_EXTENSION: reason = "No binaries permitted for {}".format(self.project_name) return (False, reason) if "macosx10" in link.path and ext == ".zip": return (False, "macosx10 one") if ext == WHEEL_EXTENSION: try: wheel = Wheel(link.filename) except InvalidWheelFilename: return (False, "invalid wheel filename") if canonicalize_name(wheel.name) != self._canonical_name: reason = "wrong project name (not {})".format(self.project_name) return (False, reason) supported_tags = self._target_python.get_tags() if not wheel.supported(supported_tags): # Include the wheel's tags in the reason string to # simplify troubleshooting compatibility issues. file_tags = wheel.get_formatted_file_tags() reason = ( "none of the wheel's tags ({}) are compatible " "(run pip debug --verbose to show compatible tags)".format( ", ".join(file_tags) ) ) return (False, reason) version = wheel.version # This should be up by the self.ok_binary check, but see issue 2700. if "source" not in self._formats and ext != WHEEL_EXTENSION: reason = f"No sources permitted for {self.project_name}" return (False, reason) if not version: version = _extract_version_from_fragment( egg_info, self._canonical_name, ) if not version: reason = f"Missing project version for {self.project_name}" return (False, reason) match = self._py_version_re.search(version) if match: version = version[: match.start()] py_version = match.group(1) if py_version != self._target_python.py_version: return (False, "Python version is incorrect") supports_python = _check_link_requires_python( link, version_info=self._target_python.py_version_info, ignore_requires_python=self._ignore_requires_python, ) if not supports_python: # Return None for the reason text to suppress calling # _log_skipped_link(). return (False, None) logger.debug("Found link %s, version: %s", link, version) return (True, version) def filter_unallowed_hashes( candidates: List[InstallationCandidate], hashes: Hashes, project_name: str, ) -> List[InstallationCandidate]: """ Filter out candidates whose hashes aren't allowed, and return a new list of candidates. If at least one candidate has an allowed hash, then all candidates with either an allowed hash or no hash specified are returned. Otherwise, the given candidates are returned. Including the candidates with no hash specified when there is a match allows a warning to be logged if there is a more preferred candidate with no hash specified. Returning all candidates in the case of no matches lets pip report the hash of the candidate that would otherwise have been installed (e.g. permitting the user to more easily update their requirements file with the desired hash). """ if not hashes: logger.debug( "Given no hashes to check %s links for project %r: " "discarding no candidates", len(candidates), project_name, ) # Make sure we're not returning back the given value. return list(candidates) matches_or_no_digest = [] # Collect the non-matches for logging purposes. non_matches = [] match_count = 0 for candidate in candidates: link = candidate.link if not link.has_hash: pass elif link.is_hash_allowed(hashes=hashes): match_count += 1 else: non_matches.append(candidate) continue matches_or_no_digest.append(candidate) if match_count: filtered = matches_or_no_digest else: # Make sure we're not returning back the given value. filtered = list(candidates) if len(filtered) == len(candidates): discard_message = "discarding no candidates" else: discard_message = "discarding {} non-matches:\n {}".format( len(non_matches), "\n ".join(str(candidate.link) for candidate in non_matches), ) logger.debug( "Checked %s links for project %r against %s hashes " "(%s matches, %s no digest): %s", len(candidates), project_name, hashes.digest_count, match_count, len(matches_or_no_digest) - match_count, discard_message, ) return filtered class CandidatePreferences: """ Encapsulates some of the preferences for filtering and sorting InstallationCandidate objects. """ def __init__( self, prefer_binary: bool = False, allow_all_prereleases: bool = False, ) -> None: """ :param allow_all_prereleases: Whether to allow all pre-releases. """ self.allow_all_prereleases = allow_all_prereleases self.prefer_binary = prefer_binary class BestCandidateResult: """A collection of candidates, returned by `PackageFinder.find_best_candidate`. This class is only intended to be instantiated by CandidateEvaluator's `compute_best_candidate()` method. """ def __init__( self, candidates: List[InstallationCandidate], applicable_candidates: List[InstallationCandidate], best_candidate: Optional[InstallationCandidate], ) -> None: """ :param candidates: A sequence of all available candidates found. :param applicable_candidates: The applicable candidates. :param best_candidate: The most preferred candidate found, or None if no applicable candidates were found. """ assert set(applicable_candidates) <= set(candidates) if best_candidate is None: assert not applicable_candidates else: assert best_candidate in applicable_candidates self._applicable_candidates = applicable_candidates self._candidates = candidates self.best_candidate = best_candidate def iter_all(self) -> Iterable[InstallationCandidate]: """Iterate through all candidates.""" return iter(self._candidates) def iter_applicable(self) -> Iterable[InstallationCandidate]: """Iterate through the applicable candidates.""" return iter(self._applicable_candidates) class CandidateEvaluator: """ Responsible for filtering and sorting candidates for installation based on what tags are valid. """ @classmethod def create( cls, project_name: str, target_python: Optional[TargetPython] = None, prefer_binary: bool = False, allow_all_prereleases: bool = False, specifier: Optional[specifiers.BaseSpecifier] = None, hashes: Optional[Hashes] = None, ) -> "CandidateEvaluator": """Create a CandidateEvaluator object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. :param specifier: An optional object implementing `filter` (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable versions. :param hashes: An optional collection of allowed hashes. """ if target_python is None: target_python = TargetPython() if specifier is None: specifier = specifiers.SpecifierSet() supported_tags = target_python.get_tags() return cls( project_name=project_name, supported_tags=supported_tags, specifier=specifier, prefer_binary=prefer_binary, allow_all_prereleases=allow_all_prereleases, hashes=hashes, ) def __init__( self, project_name: str, supported_tags: List[Tag], specifier: specifiers.BaseSpecifier, prefer_binary: bool = False, allow_all_prereleases: bool = False, hashes: Optional[Hashes] = None, ) -> None: """ :param supported_tags: The PEP 425 tags supported by the target Python in order of preference (most preferred first). """ self._allow_all_prereleases = allow_all_prereleases self._hashes = hashes self._prefer_binary = prefer_binary self._project_name = project_name self._specifier = specifier self._supported_tags = supported_tags # Since the index of the tag in the _supported_tags list is used # as a priority, precompute a map from tag to index/priority to be # used in wheel.find_most_preferred_tag. self._wheel_tag_preferences = { tag: idx for idx, tag in enumerate(supported_tags) } def get_applicable_candidates( self, candidates: List[InstallationCandidate], ) -> List[InstallationCandidate]: """ Return the applicable candidates from a list of candidates. """ # Using None infers from the specifier instead. allow_prereleases = self._allow_all_prereleases or None specifier = self._specifier versions = { str(v) for v in specifier.filter( # We turn the version object into a str here because otherwise # when we're debundled but setuptools isn't, Python will see # packaging.version.Version and # pkg_resources._vendor.packaging.version.Version as different # types. This way we'll use a str as a common data interchange # format. If we stop using the pkg_resources provided specifier # and start using our own, we can drop the cast to str(). (str(c.version) for c in candidates), prereleases=allow_prereleases, ) } # Again, converting version to str to deal with debundling. applicable_candidates = [c for c in candidates if str(c.version) in versions] filtered_applicable_candidates = filter_unallowed_hashes( candidates=applicable_candidates, hashes=self._hashes, project_name=self._project_name, ) return sorted(filtered_applicable_candidates, key=self._sort_key) def _sort_key(self, candidate: InstallationCandidate) -> CandidateSortingKey: """ Function to pass as the `key` argument to a call to sorted() to sort InstallationCandidates by preference. Returns a tuple such that tuples sorting as greater using Python's default comparison operator are more preferred. The preference is as follows: First and foremost, candidates with allowed (matching) hashes are always preferred over candidates without matching hashes. This is because e.g. if the only candidate with an allowed hash is yanked, we still want to use that candidate. Second, excepting hash considerations, candidates that have been yanked (in the sense of PEP 592) are always less preferred than candidates that haven't been yanked. Then: If not finding wheels, they are sorted by version only. If finding wheels, then the sort order is by version, then: 1. existing installs 2. wheels ordered via Wheel.support_index_min(self._supported_tags) 3. source archives If prefer_binary was set, then all wheels are sorted above sources. Note: it was considered to embed this logic into the Link comparison operators, but then different sdist links with the same version, would have to be considered equal """ valid_tags = self._supported_tags support_num = len(valid_tags) build_tag: BuildTag = () binary_preference = 0 link = candidate.link if link.is_wheel: # can raise InvalidWheelFilename wheel = Wheel(link.filename) try: pri = -( wheel.find_most_preferred_tag( valid_tags, self._wheel_tag_preferences ) ) except ValueError: raise UnsupportedWheel( "{} is not a supported wheel for this platform. It " "can't be sorted.".format(wheel.filename) ) if self._prefer_binary: binary_preference = 1 if wheel.build_tag is not None: match = re.match(r"^(\d+)(.*)$", wheel.build_tag) build_tag_groups = match.groups() build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) else: # sdist pri = -(support_num) has_allowed_hash = int(link.is_hash_allowed(self._hashes)) yank_value = -1 * int(link.is_yanked) # -1 for yanked. return ( has_allowed_hash, yank_value, binary_preference, candidate.version, pri, build_tag, ) def sort_best_candidate( self, candidates: List[InstallationCandidate], ) -> Optional[InstallationCandidate]: """ Return the best candidate per the instance's sort order, or None if no candidate is acceptable. """ if not candidates: return None best_candidate = max(candidates, key=self._sort_key) return best_candidate def compute_best_candidate( self, candidates: List[InstallationCandidate], ) -> BestCandidateResult: """ Compute and return a `BestCandidateResult` instance. """ applicable_candidates = self.get_applicable_candidates(candidates) best_candidate = self.sort_best_candidate(applicable_candidates) return BestCandidateResult( candidates, applicable_candidates=applicable_candidates, best_candidate=best_candidate, ) class PackageFinder: """This finds packages. This is meant to match easy_install's technique for looking for packages, by reading pages and looking for appropriate links. """ def __init__( self, link_collector: LinkCollector, target_python: TargetPython, allow_yanked: bool, format_control: Optional[FormatControl] = None, candidate_prefs: Optional[CandidatePreferences] = None, ignore_requires_python: Optional[bool] = None, ) -> None: """ This constructor is primarily meant to be used by the create() class method and from tests. :param format_control: A FormatControl object, used to control the selection of source packages / binary packages when consulting the index and links. :param candidate_prefs: Options to use when creating a CandidateEvaluator object. """ if candidate_prefs is None: candidate_prefs = CandidatePreferences() format_control = format_control or FormatControl(set(), set()) self._allow_yanked = allow_yanked self._candidate_prefs = candidate_prefs self._ignore_requires_python = ignore_requires_python self._link_collector = link_collector self._target_python = target_python self.format_control = format_control # These are boring links that have already been logged somehow. self._logged_links: Set[Link] = set() # Don't include an allow_yanked default value to make sure each call # site considers whether yanked releases are allowed. This also causes # that decision to be made explicit in the calling code, which helps # people when reading the code. @classmethod def create( cls, link_collector: LinkCollector, selection_prefs: SelectionPreferences, target_python: Optional[TargetPython] = None, ) -> "PackageFinder": """Create a PackageFinder. :param selection_prefs: The candidate selection preferences, as a SelectionPreferences object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. """ if target_python is None: target_python = TargetPython() candidate_prefs = CandidatePreferences( prefer_binary=selection_prefs.prefer_binary, allow_all_prereleases=selection_prefs.allow_all_prereleases, ) return cls( candidate_prefs=candidate_prefs, link_collector=link_collector, target_python=target_python, allow_yanked=selection_prefs.allow_yanked, format_control=selection_prefs.format_control, ignore_requires_python=selection_prefs.ignore_requires_python, ) @property def target_python(self) -> TargetPython: return self._target_python @property def search_scope(self) -> SearchScope: return self._link_collector.search_scope @search_scope.setter def search_scope(self, search_scope: SearchScope) -> None: self._link_collector.search_scope = search_scope @property def find_links(self) -> List[str]: return self._link_collector.find_links @property def index_urls(self) -> List[str]: return self.search_scope.index_urls @property def trusted_hosts(self) -> Iterable[str]: for host_port in self._link_collector.session.pip_trusted_origins: yield build_netloc(*host_port) @property def allow_all_prereleases(self) -> bool: return self._candidate_prefs.allow_all_prereleases def set_allow_all_prereleases(self) -> None: self._candidate_prefs.allow_all_prereleases = True @property def prefer_binary(self) -> bool: return self._candidate_prefs.prefer_binary def set_prefer_binary(self) -> None: self._candidate_prefs.prefer_binary = True def make_link_evaluator(self, project_name: str) -> LinkEvaluator: canonical_name = canonicalize_name(project_name) formats = self.format_control.get_allowed_formats(canonical_name) return LinkEvaluator( project_name=project_name, canonical_name=canonical_name, formats=formats, target_python=self._target_python, allow_yanked=self._allow_yanked, ignore_requires_python=self._ignore_requires_python, ) def _sort_links(self, links: Iterable[Link]) -> List[Link]: """ Returns elements of links in order, non-egg links first, egg links second, while eliminating duplicates """ eggs, no_eggs = [], [] seen: Set[Link] = set() for link in links: if link not in seen: seen.add(link) if link.egg_fragment: eggs.append(link) else: no_eggs.append(link) return no_eggs + eggs def _log_skipped_link(self, link: Link, reason: str) -> None: if link not in self._logged_links: # Put the link at the end so the reason is more visible and because # the link string is usually very long. logger.debug("Skipping link: %s: %s", reason, link) self._logged_links.add(link) def get_install_candidate( self, link_evaluator: LinkEvaluator, link: Link ) -> Optional[InstallationCandidate]: """ If the link is a candidate for install, convert it to an InstallationCandidate and return it. Otherwise, return None. """ is_candidate, result = link_evaluator.evaluate_link(link) if not is_candidate: if result: self._log_skipped_link(link, reason=result) return None return InstallationCandidate( name=link_evaluator.project_name, link=link, version=result, ) def evaluate_links( self, link_evaluator: LinkEvaluator, links: Iterable[Link] ) -> List[InstallationCandidate]: """ Convert links that are candidates to InstallationCandidate objects. """ candidates = [] for link in self._sort_links(links): candidate = self.get_install_candidate(link_evaluator, link) if candidate is not None: candidates.append(candidate) return candidates def process_project_url( self, project_url: Link, link_evaluator: LinkEvaluator ) -> List[InstallationCandidate]: logger.debug( "Fetching project page and analyzing links: %s", project_url, ) html_page = self._link_collector.fetch_page(project_url) if html_page is None: return [] page_links = list(parse_links(html_page)) with indent_log(): package_links = self.evaluate_links( link_evaluator, links=page_links, ) return package_links @functools.lru_cache(maxsize=None) def find_all_candidates(self, project_name: str) -> List[InstallationCandidate]: """Find all available InstallationCandidate for project_name This checks index_urls and find_links. All versions found are returned as an InstallationCandidate list. See LinkEvaluator.evaluate_link() for details on which files are accepted. """ link_evaluator = self.make_link_evaluator(project_name) collected_sources = self._link_collector.collect_sources( project_name=project_name, candidates_from_page=functools.partial( self.process_project_url, link_evaluator=link_evaluator, ), ) page_candidates_it = itertools.chain.from_iterable( source.page_candidates() for sources in collected_sources for source in sources if source is not None ) page_candidates = list(page_candidates_it) file_links_it = itertools.chain.from_iterable( source.file_links() for sources in collected_sources for source in sources if source is not None ) file_candidates = self.evaluate_links( link_evaluator, sorted(file_links_it, reverse=True), ) if logger.isEnabledFor(logging.DEBUG) and file_candidates: paths = [url_to_path(c.link.url) for c in file_candidates] logger.debug("Local files found: %s", ", ".join(paths)) # This is an intentional priority ordering return file_candidates + page_candidates def make_candidate_evaluator( self, project_name: str, specifier: Optional[specifiers.BaseSpecifier] = None, hashes: Optional[Hashes] = None, ) -> CandidateEvaluator: """Create a CandidateEvaluator object to use.""" candidate_prefs = self._candidate_prefs return CandidateEvaluator.create( project_name=project_name, target_python=self._target_python, prefer_binary=candidate_prefs.prefer_binary, allow_all_prereleases=candidate_prefs.allow_all_prereleases, specifier=specifier, hashes=hashes, ) @functools.lru_cache(maxsize=None) def find_best_candidate( self, project_name: str, specifier: Optional[specifiers.BaseSpecifier] = None, hashes: Optional[Hashes] = None, ) -> BestCandidateResult: """Find matches for the given project and specifier. :param specifier: An optional object implementing `filter` (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable versions. :return: A `BestCandidateResult` instance. """ candidates = self.find_all_candidates(project_name) candidate_evaluator = self.make_candidate_evaluator( project_name=project_name, specifier=specifier, hashes=hashes, ) return candidate_evaluator.compute_best_candidate(candidates) def find_requirement( self, req: InstallRequirement, upgrade: bool ) -> Optional[InstallationCandidate]: """Try to find a Link matching req Expects req, an InstallRequirement and upgrade, a boolean Returns a InstallationCandidate if found, Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise """ hashes = req.hashes(trust_internet=False) best_candidate_result = self.find_best_candidate( req.name, specifier=req.specifier, hashes=hashes, ) best_candidate = best_candidate_result.best_candidate installed_version: Optional[_BaseVersion] = None if req.satisfied_by is not None: installed_version = parse_version(req.satisfied_by.version) def _format_versions(cand_iter: Iterable[InstallationCandidate]) -> str: # This repeated parse_version and str() conversion is needed to # handle different vendoring sources from pip and pkg_resources. # If we stop using the pkg_resources provided specifier and start # using our own, we can drop the cast to str(). return ( ", ".join( sorted( {str(c.version) for c in cand_iter}, key=parse_version, ) ) or "none" ) if installed_version is None and best_candidate is None: logger.critical( "Could not find a version that satisfies the requirement %s " "(from versions: %s)", req, _format_versions(best_candidate_result.iter_all()), ) raise DistributionNotFound( "No matching distribution found for {}".format(req) ) best_installed = False if installed_version and ( best_candidate is None or best_candidate.version <= installed_version ): best_installed = True if not upgrade and installed_version is not None: if best_installed: logger.debug( "Existing installed version (%s) is most up-to-date and " "satisfies requirement", installed_version, ) else: logger.debug( "Existing installed version (%s) satisfies requirement " "(most up-to-date version is %s)", installed_version, best_candidate.version, ) return None if best_installed: # We have an existing version, and its the best version logger.debug( "Installed version (%s) is most up-to-date (past versions: %s)", installed_version, _format_versions(best_candidate_result.iter_applicable()), ) raise BestVersionAlreadyInstalled logger.debug( "Using version %s (newest of versions: %s)", best_candidate.version, _format_versions(best_candidate_result.iter_applicable()), ) return best_candidate def _find_name_version_sep(fragment: str, canonical_name: str) -> int: """Find the separator's index based on the package's canonical name. :param fragment: A + filename "fragment" (stem) or egg fragment. :param canonical_name: The package's canonical name. This function is needed since the canonicalized name does not necessarily have the same length as the egg info's name part. An example:: >>> fragment = 'foo__bar-1.0' >>> canonical_name = 'foo-bar' >>> _find_name_version_sep(fragment, canonical_name) 8 """ # Project name and version must be separated by one single dash. Find all # occurrences of dashes; if the string in front of it matches the canonical # name, this is the one separating the name and version parts. for i, c in enumerate(fragment): if c != "-": continue if canonicalize_name(fragment[:i]) == canonical_name: return i raise ValueError(f"{fragment} does not match {canonical_name}") def _extract_version_from_fragment(fragment: str, canonical_name: str) -> Optional[str]: """Parse the version string from a + filename "fragment" (stem) or egg fragment. :param fragment: The string to parse. E.g. foo-2.1 :param canonical_name: The canonicalized name of the package this belongs to. """ try: version_start = _find_name_version_sep(fragment, canonical_name) + 1 except ValueError: return None version = fragment[version_start:] if not version: return None return version PK!9  $__pycache__/__init__.cpython-311.pycnu[ i dZdS)zIndex interaction codeN)__doc__|/builddir/build/BUILD/imunify360-venv-2.6.2/opt/imunify360/venv/lib/python3.11/site-packages/pip/_internal/index/__init__.pyrsrPK!{ `n44*__pycache__/package_finder.cpython-311.pycnu[ i08dZddlmZddlZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl mZmZmZddlmZddlmZdd lmZmZdd lmZmZmZdd lmZdd lmZm Z m!Z!m"Z"m#Z#dd l$m%Z%m&Z&ddl'm(Z(ddl)m*Z*ddl+m,Z,ddl-m.Z.ddl/m0Z0ddl1m2Z2ddl3m4Z4ddl5m6Z6ddl7m8Z8ddl9m:Z:ddl;mZ>ddl?m@Z@ddlAmBZBddlCmDZDddlEmFZFddlGmHZHerddlImJZJgd ZKed?Z[dIdCZ\dJdEZ]dS)Kz!Routines related to PyPI, indexes) annotationsN)Iterable) dataclass) TYPE_CHECKINGOptionalUnion) specifiers)Tag)NormalizedNamecanonicalize_name)InvalidVersionVersion _BaseVersion)parse)BestVersionAlreadyInstalledDistributionNotFoundInstallationErrorInvalidWheelFilenameUnsupportedWheel) LinkCollector parse_links)select_backend)InstallationCandidate) FormatControl)Link)ReleaseControl) SearchScope)SelectionPreferences) TargetPython)Wheel)InstallRequirement) getLogger)WHEEL_EXTENSION)Hashes) indent_log) build_netloc)check_requires_python)SUPPORTED_EXTENSIONS) TypeGuard)rBestCandidateResult PackageFinderFlinkr version_infotuple[int, int, int]ignore_requires_pythonboolreturnc t|j|}|spdtt|}|s$t d||j|dSt d||j|n6#tj $r$t d|j|YnwxYwdS)aa Return whether the given Python version is compatible with a link's "Requires-Python" value. :param version_info: A 3-tuple of ints representing the Python major-minor-micro version to check. :param ignore_requires_python: Whether to ignore the "Requires-Python" value if the given Python version isn't compatible. )r..z4Link requires a different Python (%s not in: %r): %sFzBIgnoring failed Requires-Python check (%s not in: %r) for link: %sz2Ignoring invalid Requires-Python (%r) for link: %sT) r'requires_pythonjoinmapstrloggerverbosedebugr InvalidSpecifier)r-r.r0 is_compatibleversions /builddir/build/BUILD/imunify360-venv-2.6.2/opt/imunify360/venv/lib/python3.11/site-packages/pip/_internal/index/package_finder.py_check_link_requires_pythonr@?s-  %    hhs3 5566G) J(  u LLT$    %  &    @        2 4sB 0B>=B>ceZdZejZejZejZejZejZ ejZ ejZ ejZ ejZ dS)LinkTypeN)__name__ __module__ __qualname__enumauto candidatedifferent_projectyankedformat_unsupportedformat_invalidplatform_mismatchrequires_python_mismatchupload_too_lateupload_time_missingr,r?rBrBns I!  TY[[F"TY[[N! (ty{{dikkO#$)++rQrBcHeZdZdZejdZ dddZddZdS) LinkEvaluatorzD Responsible for evaluating links for a particular project. z-py([123]\.?[0-9]?)$N project_namer8canonical_namer formatsfrozenset[str] target_pythonr allow_yankedr1r0 bool | Noneuploaded_prior_todatetime.datetime | Noner2Nonecp|d}||_||_||_||_||_||_||_dS)aB :param project_name: The user supplied package name. :param canonical_name: The canonical package name. :param formats: The formats allowed for this package. Should be a set with 'binary' or 'source' or both in it. :param target_python: The target Python interpreter to use when evaluating link compatibility. This is used, for example, to check wheel compatibility, as well as when checking the Python version, e.g. the Python version embedded in a link filename (or egg fragment) and against an HTML link's optional PEP 503 "data-requires-python" attribute. :param allow_yanked: Whether files marked as yanked (in the sense of PEP 592) are permitted to be candidates for install. :param ignore_requires_python: Whether to ignore incompatible PEP 503 "data-requires-python" values in HTML links. Defaults to False. :param uploaded_prior_to: If set, only allow links uploaded prior to the given datetime. NF) _allow_yanked_canonical_name_ignore_requires_python_formats_target_python_uploaded_prior_torT)selfrTrUrVrXrYr0r[s r?__init__zLinkEvaluator.__init__sM: " )%* ")-'=$ +"3(rQr-rtuple[LinkType, str]cd}|jr!|js|jpd}tjd|fS|jr|j}|j}nb|\}}|stjdfS|tvrtjd|fSd|j vr#|tkrd|j }tj|fSd|j vr|d krtjd fS|tkr t|j}n#t $rtjd fcYSwxYw|j|jkrd |j d }tj|fS|j}||s;d|}d|d}tj|fS|j}|ja|jsZ|j%|jr d|j} nd} tj | dfS|j|jkrtj!d|jd|jfSd|j vr#|tkrd|j }tj|fS|stE||j}|sd|j }tj|fS|j#$|} | rO|d| %}| &d} | |jj'krtjdfStQ||jj)|j*} | sb|j+} | rDd&d }d!tYd"t[j.| D|#} |d$| }tj/|fSt`1d%||tj2|fS)'a Determine whether a link is a candidate for installation. :return: A tuple (result, detail), where *result* is an enum representing whether the evaluation found a candidate, or the reason why one is not found. If a candidate is found, *detail* will be the candidate's version string; if one is not found, it contains the reason the link fails to qualify. Nz zyanked for reason: z not a filezunsupported archive format: binaryzNo binaries permitted for macosx10z.zipz macosx10 onezinvalid wheel filenamezwrong project name (not ), znone of the wheel's tags (zB) are compatible (run pip debug --verbose to show compatible tags)zIndex Indexz' does not provide upload-time metadata.z Upload time z not prior to sourcezNo sources permitted for zMissing project version for zPython version is incorrect)r.r0vr8r2tuple[int, ...]cZtd|dDS)Nc3\K|]'}|t|V(dSN)isdigitint.0ss r? zLLinkEvaluator.evaluate_link..get_version_sort_key..s5 M MA MQ M M M M M MrQr4)tuplesplit)rps r?get_version_sort_keyz9LinkEvaluator.evaluate_link..get_version_sort_keys) M M M M MMMMrQ,c34K|]}t|VdSrt)r8rws r?rzz.LinkEvaluator.evaluate_link.."s(RRAQRRRRRRrQkeyz Requires-Python zFound link %s, version: %s)rpr8r2rq)3 is_yankedr_ yanked_reasonrBrJ egg_fragmentextsplitextrKr(rbr#rTpathr filenamerrLnamer`rIrcget_unsorted_tags supportedr6get_formatted_file_tagsrMr>rdis_file upload_time comes_fromrPrO_extract_version_from_fragment_py_version_researchstartgroup py_versionr@py_version_inforar5sortedr SpecifierSetrNr9r;rH)rer-r>reasonegg_inforwheelsupported_tags file_tags index_infomatchrsupports_pythonr5r}s r? evaluate_linkzLinkEvaluator.evaluate_links > E$"4 E'9>FO%C6%C%CD D  ( ((H(CC MMOOMHc C 3\BB.../8388t},,1G1GId6GII 3V<<TY&&3&== 3^DDo%%!$-00EE+ /0 :!555L8ILLLF$6??!%!4!F!F!H!H~66@!% %*G*G*I*I J JIMYMMM%6??-  " .t| .'?)!;$/!;!;JJ!(J0!JJJ!T%<<<,:4#3:: $ 7:: 4= ( (SO-C-CD1BDDF/8 8 4$G 5GD4EGGF+V4 4#**733  o o.GQJT0;;;.1 6 ,<#'#?     ?"2O NNNN#&((RR)@)Q)QRRR0##  CC/CCF5v> > 14AAA"G,,sC--DDNN)rTr8rUr rVrWrXrrYr1r0rZr[r\r2r])r-rr2rg) rCrDrE__doc__recompilerrfrr,rQr?rSrSzsn RZ 788N/36:')')')')')R}-}-}-}-}-}-rQrS candidateslist[InstallationCandidate]hashes Hashes | NonerTr8c |s8tdt||t|Sg}g}d}|D]X}|j}|jsn2||r|dz }n||C||Y|r|}nt|}t|t|krd} n@dt|d d|D} td t|||j |t||z | |S) a Filter out candidates whose hashes aren't allowed, and return a new list of candidates. If at least one candidate has an allowed hash, then all candidates with either an allowed hash or no hash specified are returned. Otherwise, the given candidates are returned. Including the candidates with no hash specified when there is a match allows a warning to be logged if there is a more preferred candidate with no hash specified. Returning all candidates in the case of no matches lets pip report the hash of the candidate that would otherwise have been installed (e.g. permitting the user to more easily update their requirements file with the desired hash). zJGiven no hashes to check %s links for project %r: discarding no candidatesr)rrozdiscarding no candidateszdiscarding {} non-matches: {}z c3>K|]}t|jVdSrt)r8r-)rxrHs r?rzz*filter_unallowed_hashes..gs,II IN++IIIIIIrQzPChecked %s links for project %r against %s hashes (%s matches, %s no digest): %s) r9r;lenlistr-has_hashis_hash_allowedappendformatr6 digest_count) rrrTmatches_or_no_digest non_matches match_countrHr-filtereddiscard_messages r?filter_unallowed_hashesr.s(    '  OO     JKK / / ~}    ! ! ! 0 0  1 KK   y ) ) ) ##I....$' ## 8}}J''4<CC    KKII[III I I    LL ) J !!K/    OrQc0eZdZUdZdZded<dZded<dS)CandidatePreferenceszk Encapsulates some of the preferences for filtering and sorting InstallationCandidate objects. Fr1 prefer_binaryNReleaseControl | Nonerelease_control)rCrDrErr__annotations__rr,rQr?rrxs@  M-1O111111rQrT)frozenc:eZdZUdZded<ded<ded<d d Zd S) r*aA collection of candidates, returned by `PackageFinder.find_best_candidate`. This class is only intended to be instantiated by CandidateEvaluator's `compute_best_candidate()` method. :param all_candidates: A sequence of all available candidates found. :param applicable_candidates: The applicable candidates. :param best_candidate: The most preferred candidate found, or None if no applicable candidates were found. rall_candidatesapplicable_candidatesInstallationCandidate | Nonebest_candidater2r]ct|jt|jksJ|j |jrJdS|j|jvsJdSrt)setrrrres r? __post_init__z!BestCandidateResult.__post_init__sd4-..#d6I2J2JJJJJ   &1 1 11 1 1&$*DDDDDDDrQNr2r])rCrDrErrrr,rQr?r*r*s`  0///66660000EEEEEErQr*cfeZdZdZe d"d#dZ d$d%dZd&dZd'dZd(dZ d)d!Z dS)*CandidateEvaluatorzm Responsible for filtering and sorting candidates for installation based on what tags are valid. NFrTr8rXTargetPython | Nonerr1rr specifierspecifiers.BaseSpecifier | Nonerrr2c|t}|tj}|}|||||||S)aCreate a CandidateEvaluator object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. :param specifier: An optional object implementing `filter` (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable versions. :param hashes: An optional collection of allowed hashes. N)rTrrrrr)rr rget_sorted_tags)clsrTrXrrrrrs r?createzCandidateEvaluator.createsc(  (NNM  "/11I&6688s%)'+     rQr list[Tag]specifiers.BaseSpecifierr]c||_||_||_||_||_||_dt |D|_dS)z :param supported_tags: The PEP 425 tags supported by the target Python in order of preference (most preferred first). ci|]\}}|| Sr,r,)rxidxtags r? z/CandidateEvaluator.__init__..s+' ' ' !cC' ' ' rQN)_release_control_hashes_prefer_binary _project_name _specifier_supported_tags enumerate_wheel_tag_preferences)rerTrrrrrs r?rfzCandidateEvaluator.__init__sa!0 +)#-' ' %.~%>%>' ' ' ###rQrrc|j-|jt|j}nd}|j}t jdkr d|D}n d|D}t|d|D|fd|D}t||j |j}t||j S) zM Return the applicable candidates from a list of candidates. N pkg_resourcesc:g|]}|t|jfSr,r8r>rxcs r? z@CandidateEvaluator.get_applicable_candidates..s%999!S^^$999rQc g|] }||jf Sr,r>rs r?rz@CandidateEvaluator.get_applicable_candidates..s&J&J&J!19~&J&J&JrQc3 K|] \}}|V dSrtr,)rx_rps r?rzz?CandidateEvaluator.get_applicable_candidates..s&77tq!777777rQ) prereleasesc"g|] \}}|v | Sr,r,)rxrrpversionss r?rz@CandidateEvaluator.get_applicable_candidates..s" X X Xtq!!x-----rQ)rrrTr) rallows_prereleasesr rrrNAMErfilterrrr _sort_key)rerallow_prereleasesrcandidates_and_versionsrfiltered_applicable_candidatesrs @r?get_applicable_candidatesz,CandidateEvaluator.get_applicable_candidatess$  , $ 5 H H!$"455!!  !% O     O 3 3:9j999 $ #'K&Jz&J&J&J #   776777-     !Y X X X/F X X X)@,<+* * * & 4$.IIIIrQrHrCandidateSortingKeyc|j}t|}d}d}|j}|jrht |j} |||j }n%#t$rt|jdwxYw|j rd}|j }n| }t| |j} dt|jz} | | ||j||fS)a) Function to pass as the `key` argument to a call to sorted() to sort InstallationCandidates by preference. Returns a tuple such that tuples sorting as greater using Python's default comparison operator are more preferred. The preference is as follows: First and foremost, candidates with allowed (matching) hashes are always preferred over candidates without matching hashes. This is because e.g. if the only candidate with an allowed hash is yanked, we still want to use that candidate. Second, excepting hash considerations, candidates that have been yanked (in the sense of PEP 592) are always less preferred than candidates that haven't been yanked. Then: If not finding wheels, they are sorted by version only. If finding wheels, then the sort order is by version, then: 1. existing installs 2. wheels ordered via Wheel.support_index_min(self._supported_tags) 3. source archives If prefer_binary was set, then all wheels are sorted above sources. Note: it was considered to embed this logic into the Link comparison operators, but then different sdist links with the same version, would have to be considered equal r,rz@ is not a supported wheel for this platform. It can't be sorted.ro)rrr-is_wheelr rfind_most_preferred_tagr ValueErrorrr build_tagrvrrrr>) rerH valid_tags support_numrbinary_preferencer-rprihas_allowed_hash yank_values r?rzCandidateEvaluator._sort_keys"<) *oo  ~ = !$-((E 11"D$?    &~'''  " &$%!II.Ct33DLAABB#dn---          s A"A=rc:|sdSt||j}|S)zy Return the best candidate per the instance's sort order, or None if no candidate is acceptable. Nr)maxr)rerrs r?sort_best_candidatez&CandidateEvaluator.sort_best_candidateOs+ 4ZT^<<<rQr*cz||}||}t|||S)zF Compute and return a `BestCandidateResult` instance. )rr)rrr*)rerrrs r?compute_best_candidatez)CandidateEvaluator.compute_best_candidate\sL!% > >z J J112GHH" "7)    rQ)NFNNN)rTr8rXrrr1rrrrrrr2r)FNN)rTr8rrrrrr1rrrrr2r])rrr2r)rHrr2r)rrr2r)rrr2r*) rCrDrEr classmethodrrfrrrr r,rQr?rrs .2#1559 $! ! ! ! [! P$15 $     4+J+J+J+JZ? ? ? ? B          rQrceZdZdZ dQdRdZe dSdTdZedUdZedVdZ e j dWdZ edXdZ edXdZ edYd!Z edZd#ZedYd$ZedYd%Zed[d'Zd\d*Zed]d+Zd^d,Zed_d-ZdXd.Zd`d2Zdad6Zdbd<Zdcd?ZdddAZdedCZdfdDZ dSdgdJZ dSdhdLZdidPZ dS)jr+zThis finds packages. This is meant to match easy_install's technique for looking for packages, by reading pages and looking for appropriate links. Nlink_collectorrrXrrYr1format_controlFormatControl | Nonecandidate_prefsCandidatePreferences | Noner0rZr[r\r2r]c|t}|p'ttt}||_||_||_||_||_||_||_ t|_ i|_ i|_ dS)a This constructor is primarily meant to be used by the create() class method and from tests. :param format_control: A FormatControl object, used to control the selection of source packages / binary packages when consulting the index and links. :param candidate_prefs: Options to use when creating a CandidateEvaluator object. N) rrrr__candidate_prefsra_link_collectorrcrdr  _logged_links_all_candidates_best_candidates)rer rXrYr rr0r[s r?rfzPackageFinder.__init__us(  "244O'F=+F+F) /'=$-+"3,?BeeHJ  rQselection_prefsrrc |t}t|j|j}|||||j|j|j|S)aCreate a PackageFinder. :param selection_prefs: The candidate selection preferences, as a SelectionPreferences object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. :param uploaded_prior_to: If set, only find links uploaded prior to the given datetime. N)rr)rr rXrYr r0r[)rrrrrYr r0)rr rrXr[rs r?rzPackageFinder.createsl$  (NNM.)7+;    s+)'(5*9#2#I/    rQc|jSrt)rcrs r?rXzPackageFinder.target_pythons ""rQrc|jjSrtr search_scopers r?rzPackageFinder.search_scopes#00rQrc||j_dSrtr)rers r?rzPackageFinder.search_scopes,8)))rQ list[str]c|jjSrt)r find_linksrs r?r zPackageFinder.find_linkss#..rQc|jjSrt)r index_urlsrs r?r"zPackageFinder.index_urlss ++rQ str | Nonec$|jjjSrt)rsession pip_proxyrs r?proxyzPackageFinder.proxys#+55rQ Iterable[str]c#HK|jjjD] }t|VdSrt)rr%pip_trusted_originsr&)re host_ports r? trusted_hostszPackageFinder.trusted_hostss<-5I + +I * * * * * + +rQcV|jjj}t|tr|ndSrt)rr%verify isinstancer8)rer.s r? custom_certzPackageFinder.custom_certs+ %-4#FC00:vvd:rQcf|jjj}t|tr Jd|S)Nz"pip only supports PEM client certs)rr%certr/r{)rer2s r? client_certzPackageFinder.client_certs4#+0dE**PP,PPP* rQrc|jjSrtrrrs r?rzPackageFinder.release_controls$44rQrrc||j_dSrtr5)rers r?set_release_controlz!PackageFinder.set_release_controls0?---rQc|jjSrtrrrs r?rzPackageFinder.prefer_binarys$22rQcd|j_dS)NTr9rs r?set_prefer_binaryzPackageFinder.set_prefer_binarys.2+++rQc|jSrt)rdrs r?r[zPackageFinder.uploaded_prior_tos &&rQcBd|jD}t|S)Nc:h|]\}}}|tjk|Sr,)rBrN)rxrresultdetails r? z@PackageFinder.requires_python_skipped_reasons..s6   !66::: :::rQ)rr)rereasonss r?requires_python_skipped_reasonsz-PackageFinder.requires_python_skipped_reasonss1  %)%7    grQrTr8rSc t|}|j|}t||||j|j|j|jS)N)rTrUrVrXrYr0r[)r r get_allowed_formatsrSrcr_rard)rerTrUrVs r?make_link_evaluatorz!PackageFinder.make_link_evaluators]*<88%99.II%)-+#'#?"5    rQlinksIterable[Link] list[Link]cgg}}t}|D]M}||vrG|||jr||8||N||zS)z Returns elements of links in order, non-egg links first, egg links second, while eliminating duplicates )raddrr)rerGeggsno_eggsseenr-s r? _sort_linkszPackageFinder._sort_linkss| Bg%% ) )D4$)KK%%%%NN4(((~rQr-rr?rBr@c|||f}||jvr8td|||j|dSdS)NzSkipping link: %s: %s)rr9r;rK)rer-r?r@entrys r?_log_skipped_linkzPackageFinder._log_skipped_link,sZvv& * * * LL0&$ ? ? ?   " "5 ) ) ) ) ) + *rQlink_evaluatorrc||\}}|tjkrt||tjkr||||dS t |j||S#t$rYdSwxYw)z If the link is a candidate for install, convert it to an InstallationCandidate and return it. Otherwise, return None. N)rr-r>) rrBrPrrHrRrrTr )rerSr-r?r@s r?get_install_candidatez#PackageFinder.get_install_candidate4s(55d;; X1 1 1$F++ + X' ' '  " "4 8 8 84 (#0     44 s"A99 BBrcg}||D]/}|||}|||0|S)zU Convert links that are candidates to InstallationCandidate objects. )rOrUr)rerSrGrr-rHs r?evaluate_linkszPackageFinder.evaluate_linksMs\  $$U++ - -D22>4HHI$!!),,,rQ project_urlc*td||j|}|gSt t |}t 5|||}dddn #1swxYwY|S)Nz-Fetching project page and analyzing links: %s)rG)r9r;rfetch_responserrr%rW)rerXrSindex_response page_links package_linkss r?process_project_urlz!PackageFinder.process_project_url[s  ;    -<<[II  !I+n5566 \\   // 0M                s$BB B cr||jvr |j|S||}|j|t j|j|}tj d|D}t|}tj d|D}| |t|d}ttjr|rg}|D]_} | jjsJ || jj1#t*$r"|| jjY\wxYwtdd|||z|j|<|j|S) aFind all available InstallationCandidate for project_name This checks index_urls and find_links. All versions found are returned as an InstallationCandidate list. See LinkEvaluator.evaluate_link() for details on which files are accepted. )rS)rTcandidates_from_pagec3LK|]}|D]}||V dSrt)page_candidatesrxsourcesrns r?rzz4PackageFinder.find_all_candidates..sW; ; !; ; !  " " $ $"!!!! ; ; rQc3LK|]}|D]}||V dSrt) file_linksrcs r?rzz4PackageFinder.find_all_candidates..sW6 6 !6 6 !     "!!!! 6 6 rQT)reversezLocal files found: %srl)rrFrcollect_sources functoolspartialr^ itertoolschain from_iterablerrWrr9 isEnabledForloggingDEBUGr-urlr file_path Exceptionr;r6) rerTrScollected_sourcespage_candidates_itrb file_links_itfile_candidatespathsrHs r?find_all_candidatesz!PackageFinder.find_all_candidatesps 4/ / /' 5 511,?? 0@@%!*!2(-"""A  '_::; ; ,; ; ;    122!556 6 ,6 6 6   --  =$ / / /     w} - - D/ DE, 5 5  ~))))5LL!9:::: 555LL!3444445 LL0$))E2B2B C C C.=-N\*#L11s"E)E.-E.rrrrrcn|j}t||j|j|j||S)z*Create a CandidateEvaluator object to use.)rTrXrrrr)rrrrcrr)rerTrrrs r?make_candidate_evaluatorz&PackageFinder.make_candidate_evaluatorsD/!((%-)7+; )   rQr*c|||f|jvr|j|||fS||}||||}|||j|||f<|j|||fS)aFind matches for the given project and specifier. :param specifier: An optional object implementing `filter` (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable versions. :return: A `BestCandidateResult` instance. )rTrr)rryr{r )rerTrrrcandidate_evaluators r?find_best_candidatez!PackageFinder.find_best_candidates )V ,0E E E(y&)HI I--l;; ";;%<   6 6z B B lIv=>$\9f%DEErQreqr!upgradecD |j}| Jd|d}|||j|}|j d |j |jj dd } u sd }|j-|jt|}|durd }t d ||||j td|d fd } |sL J| r"td jntd dS| r1td j||j Std ||jt )zTry to find a Link matching req Expects req, an InstallRequirement and upgrade, a boolean Returns a InstallationCandidate if found, Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise Nz&find_requirement() called with no nameF)trust_internet)rr cand_iterIterable[InstallationCandidate]r2r8cldtd|DtpdS)Nrlc6h|]}t|jSr,rrs r?rAzKPackageFinder.find_requirement.._format_versions..s ;;;AQY;;;rQrnone)r6r parse_version)rs r?_format_versionsz8PackageFinder.find_requirement.._format_versionssJ  ;;;;;)  rQr>z final versionzICould not find a %s that satisfies the requirement %s (from versions: %s)z#No matching distribution found for rHr TypeGuard[InstallationCandidate]c*dSdSjkS)NTFr)rHrinstalled_versions r?_should_install_candidatezAPackageFinder.find_requirement.._should_install_candidates*!(t%u!),== =rQzUExisting installed version (%s) satisfies requirement (most up-to-date version is %s)zLExisting installed version (%s) is most up-to-date and satisfies requirementz)Using version %s (newest of versions: %s)z=Installed version (%s) is most up-to-date (past versions: %s))rrr2r8)rHrr2r)rrr~rr satisfied_byr>rrr r9criticalrrr;rr) rerrrrbest_candidate_resultr version_type allows_prerrrs @@r?find_requirementzPackageFinder.find_requirementsJx!I511 $ 8 8 m!9! !  /=15   ' # 0 8       $)?$L#/!1DD%d++ &L OO&  !6!EFF    ''RS'R'RSS S > > > > > > > ,8((88  6%"*  ,% 4 $ $^ 4 4 " LL;&  !6!LMM    " !  K   2H I I   *)rQ)NNNN)r rrXrrYr1r rrrr0rZr[r\r2r]r) r rrrrXrr[r\r2r+)r2r)r2r)rrr2r])r2r)r2r#)r2r()r2r)rrr2r])r2r1r)r2r\)rTr8r2rS)rGrHr2rI)r-rr?rBr@r8r2r])rSrSr-rr2r)rSrSrGrHr2r)rXrrSrSr2r)rTr8r2r)rTr8rrrrr2r)rTr8rrrrr2r*)rr!rr1r2r)!rCrDrErrfr rpropertyrXrsetterr r"r'r,r0r3rr7rr;r[rCrFrOrRrUrWr^ryr{r~rr,rQr?r+r+ns&047;.26:*****` .26: ! ! ! ! [! F###X#111X19999///X/,,,X,666X6+++X+;;;X;X 555X5@@@@333X33333'''X'      ****2    *72727272x6: $      (6: $ FFFFF:b*b*b*b*b*b*rQr+fragmentrUrvct|D]+\}}|dkr t|d||kr|cS,t|d|)aFind the separator's index based on the package's canonical name. :param fragment: A + filename "fragment" (stem) or egg fragment. :param canonical_name: The package's canonical name. This function is needed since the canonicalized name does not necessarily have the same length as the egg info's name part. An example:: >>> fragment = 'foo__bar-1.0' >>> canonical_name = 'foo-bar' >>> _find_name_version_sep(fragment, canonical_name) 8 -Nz does not match )rr r)rrUirs r?_find_name_version_sepr<sp$(##1 88  Xbqb\ * *n < <HHH = BB.BB C CCrQr#cn t||dz}n#t$rYdSwxYw||d}|sdS|S)zParse the version string from a + filename "fragment" (stem) or egg fragment. :param fragment: The string to parse. E.g. foo-2.1 :param canonical_name: The canonicalized name of the package this belongs to. roN)rr)rrU version_startr>s r?rrVs_.xHH1L tt}~~&G t Ns  $$)F)r-rr.r/r0r1r2r1)rrrrrTr8r2r)rr8rUr8r2rv)rr8rUr8r2r#)^r __future__rdatetimerFrirkrorcollections.abcr dataclassesrtypingrrrpip._vendor.packagingr pip._vendor.packaging.tagsr pip._vendor.packaging.utilsr r pip._vendor.packaging.versionr rrrrpip._internal.exceptionsrrrrrpip._internal.index.collectorrrpip._internal.metadatarpip._internal.models.candidater#pip._internal.models.format_controlrpip._internal.models.linkr$pip._internal.models.release_controlr!pip._internal.models.search_scoper$pip._internal.models.selection_prefsr"pip._internal.models.target_pythonrpip._internal.models.wheelr pip._internal.reqr!pip._internal.utils._logr"pip._internal.utils.filetypesr#pip._internal.utils.hashesr$pip._internal.utils.loggingr%pip._internal.utils.miscr&pip._internal.utils.packagingr'pip._internal.utils.unpackingr(typing_extensionsr)__all__rCr9r{rvr8BuildTagrr@EnumrBrSrrr*rr+rrr,rQr?rs''""""""  $$$$$$!!!!!! -,,,,,******IIIIIIIIOOOOOOOOOO@@@@@@EDDDDDDD111111@@@@@@======******??????999999EEEEEE;;;;;;,,,,,,000000......999999------222222111111??????>>>>>>,++++++ C C C 8   rE#s(O+ ,Cc<#PQ $),,,,,^ & & & & &ty & & &q-q-q-q-q-q-q-q-hGGGGT 2222222 2 $EEEEEEEE2N N N N N N N N bK*K*K*K*K*K*K*K*\DDDD4rQPK!FX5X5#__pycache__/sources.cpython-311.pycnu[ i!ddlmZddlZddlZddlZddlmZddlmZddl m Z ddl m Z m Z mZmZmZddlmZddlmZdd lmZmZdd lmZejeZeeZeeZe egeefZe ege fZ!Gd d Z"d&dZ#GddZ$Gdde"Z%Gdde"Z&Gdde"Z'Gdde"Z(d'd%Z)dS)() annotationsN) defaultdict)Iterable)Callable)InvalidSdistFilenameInvalidWheelFilenamecanonicalize_nameparse_sdist_filenameparse_wheel_filename)InstallationCandidate)Link) path_to_url url_to_path)is_urlc6eZdZed dZd dZd dZdS) LinkSourcereturn Link | Nonect)z,Returns the underlying link, if there's one.NotImplementedErrorselfs {/builddir/build/BUILD/imunify360-venv-2.6.2/opt/imunify360/venv/lib/python3.11/site-packages/pip/_internal/index/sources.pylinkzLinkSource.link s"###FoundCandidatesct)z9Candidates found by parsing an archive listing HTML file.rrs rpage_candidateszLinkSource.page_candidates%!###r FoundLinksct)z,Links found by specifying archives directly.rrs r file_linkszLinkSource.file_links)r rNrrrrrr!)__name__ __module__ __qualname__propertyrrr#rrrrsZ $$$X$$$$$$$$$$$rrfile_urlstrrboolcBtj|dddkS)NF)strictrz text/html) mimetypes guess_type)r,s r _is_html_filer3.s"   7 7 7 :k IIrcReZdZdZd dZddZedd Zedd Zd S)_FlatDirectoryToUrlsz"Scans directory and caches resultspathr-rNonecb||_g|_tt|_d|_dS)NF)_path_page_candidatesrlist_project_name_to_urls_scanned_directory)rr6s r__init__z_FlatDirectoryToUrls.__init__5s/ +-;Ft;L;L""'rctj|jD]}t|j}t |r|j|@ t|j d}n=#t$r0 t|j d}n#t$rYYwxYwYnwxYw|j ||d|_dS)zrScans directory once and populates both page_candidates and project_name_to_urls at the same time rTN)osscandirr9rr6r3r:appendr namerr rr<r=)rentryurlproject_filenames r_scan_directoryz$_FlatDirectoryToUrls._scan_directory;s Z ++ E EEej))CS!! %,,S111 #7 #C#CA#F  '   ';EJ'G'G'J$$+HH%$   &'7 8 ? ? D D D D"&s6A66 B0BB0 B*&B0)B**B0/B0 list[str]cF|js||jSN)r=rGr:rs rrz$_FlatDirectoryToUrls.page_candidatesRs(& #  " " "$$rdict[str, list[str]]cF|js||jSrJ)r=rGr<rs rproject_name_to_urlsz)_FlatDirectoryToUrls.project_name_to_urlsYs(& #  " " "))rN)r6r-rr7)rr7)rrH)rrK) r'r(r)__doc__r>rGr*rrMr+rrr5r52s,,(((( ''''.%%%X% ***X***rr5cReZdZUdZiZded<dd Zedd ZddZ ddZ dS)_FlatDirectorySourcezLink source specified by ``--find-links=``. This looks the content of the directory, and returns: * ``page_candidates``: Links listed on each HTML file in the directory. * ``file_candidates``: Archives in the directory. zdict[str, _FlatDirectoryToUrls]_paths_to_urlscandidates_from_pageCandidatesFromPager6r- project_namerr7c||_t||_||jvr|j||_dSt ||_|j|j|<dS)N)r6)_candidates_from_pager _project_namerQ _path_to_urlsr5)rrRr6rTs rr>z_FlatDirectorySource.__init__lsk &:".|<< 4& & &!%!4T!:D   !54!@!@!@D (,(:D  % % %rrcdSrJr+rs rrz_FlatDirectorySource.link|strrc#xK|jjD]*}|t|Ed{V+dSrJ)rXrrVr rrEs rrz$_FlatDirectorySource.page_candidatessT%5 = =C11$s))<< < < < < < < < < = =rr!c#`K|jj|jD]}t|VdSrJ)rXrMrWr r[s rr#z_FlatDirectorySource.file_linkss>%:4;MN  Cs))OOOO  rN)rRrSr6r-rTr-rr7r$r%r&) r'r(r)rNrQ__annotations__r>r*rrr#r+rrrPrPas79N8888;;;; X====rrPcBeZdZdZddZedd Zdd ZddZdS)_LocalFileSourceaC``--find-links=`` or ``--[extra-]index-url=``. If a URL is supplied, it must be a ``file:`` URL. If a path is supplied to the option, it is converted to a URL first. This returns: * ``page_candidates``: Links listed on an HTML file. * ``file_candidates``: The non-HTML file. rRrSrr rr7c"||_||_dSrJrV_linkrrRrs rr>z_LocalFileSource.__init__ &:" rrc|jSrJrbrs rrz_LocalFileSource.link zrrc#Kt|jjsdS||jEd{VdSrJ)r3rbrErVrs rrz _LocalFileSource.page_candidatessMTZ^,,  F--dj99999999999rr!c#RKt|jjrdS|jVdSrJ)r3rbrErs rr#z_LocalFileSource.file_linkss3  ( (  FjrNrRrSrr rr7r$r%r& r'r(r)rNr>r*rrr#r+rrr_r_szX:::: rr_cBeZdZdZdd Zedd ZddZddZdS)_RemoteFileSourcez``--find-links=`` or ``--[extra-]index-url=``. This returns: * ``page_candidates``: Links listed on an HTML file. * ``file_candidates``: The non-HTML file. rRrSpage_validator PageValidatorrr rr7c0||_||_||_dSrJ)rV_page_validatorrb)rrRrnrs rr>z_RemoteFileSource.__init__s &:"- rrc|jSrJrfrs rrz_RemoteFileSource.linkrgrrc#K||jsdS||jEd{VdSrJ)rqrbrVrs rrz!_RemoteFileSource.page_candidatessQ##DJ//  F--dj99999999999rr!c#K|jVdSrJrfrs rr#z_RemoteFileSource.file_linkssjrN)rRrSrnrorr rr7r$r%r&rkr+rrrmrmszX:::: rrmcBeZdZdZddZedd Zdd ZddZdS)_IndexDirectorySourcez``--[extra-]index-url=``. This is treated like a remote URL; ``candidates_from_page`` contains logic for this by appending ``index.html`` to the link. rRrSrr rr7c"||_||_dSrJrarcs rr>z_IndexDirectorySource.__init__rdrrc|jSrJrfrs rrz_IndexDirectorySource.linkrgrrc#JK||jEd{VdSrJrars rrz%_IndexDirectorySource.page_candidatess4--dj99999999999rr!cdS)Nr+r+rs rr#z _IndexDirectorySource.file_linkssrrNrjr$r%r&rkr+rrrvrvsz X::::rrvlocationrRrSrnro expand_dircache_link_parsingrT$tuple[str | None, LinkSource | None]cd}d}tj|rt|}|}n8|dr|}t |}nt |r|}|d}t||dS|%t||t||} || fStj |r9|rt|||} n t|t||} || fStj|r$t|t||} || fStd||dfS) Nzfile:zVLocation '%s' is ignored: it is either a non-existing path or lacks a specific scheme.)NN)r})rRrnr)rRr6rT)rRrz?Location '%s' is ignored: it is neither a file nor a directory.)r@r6existsr startswithrrloggerwarningrmr isdirrPrvisfiler_) r{rRrnr|r}rTr6rEmsgsources r build_sourcersDC w~~h(##   W % %8$$    { K  sH%%%| |.!5)c.@AAA    V} w}}T  )%9)FF +%9#2DEEEFV}   !!5c.@AAA   V} NNI ;r)r,r-rr.)r{r-rRrSrnror|r.r}r.rTr-rr~)* __future__rloggingr1r@ collectionsrcollections.abcrtypingrpip._vendor.packaging.utilsrrr r r pip._internal.models.candidater pip._internal.models.linkr pip._internal.utils.urlsrrpip._internal.vcsr getLoggerr'rrr!rSr.rorr3r5rPr_rmrvrr+rrrs"""""" ######$$$$$$A@@@@@******========$$$$$$  8 $ $01 d^ tfh/D&EEF$&  $ $ $ $ $ $ $ $JJJJ,*,*,*,*,*,*,*,*^%%%%%:%%%PzB @J4;;;;;;rPK!#]]%__pycache__/collector.cpython-311.pycnu[ i?dZddlmZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl mZmZmZddlmZddlmZddlmZddlmZmZmZdd lmZdd lmZdd lm Z m!Z!dd l"m#Z#dd l$m%Z%ddl&m'Z'ddl(m)Z)ddl*m+Z+ddl,m-Z-ddl.m/Z/ddl0m1Z1ddl2m3Z3ddl4m5Z5m6Z6m7Z7e j8e9Z:ee;e;fZZ?dKd!Z@Gd"d#e>ZAdLd&ZBdMd'ZCdNd*ZDGd+d,ZEGd-d.eZFdOd0ZGeGdPd4ZHed56Gd7d2ZIGd8d9eZJ dQdRd@ZK dSdTdCZLdUdEZMGdFdGeZNGdHdIZOdS)VzO The main purpose of this module is to expose LinkCollector.collect_sources(). ) annotationsN)IterableMutableMappingSequence) dataclass) HTMLParser)Values)Callable NamedTupleProtocol)requests)Response) RetryErrorSSLError)NetworkConnectionError)Link) SearchScope) PipSession)raise_for_status)is_archive_fileredact_auth_from_url) url_to_path)vcs)CandidatesFromPage LinkSource build_sourceurlstrreturn str | NonectjD]D}||r|t |dvr|cSEdS)zgLook for VCS schemes in the URL. Returns the matched VCS scheme, or None if there's no match. z+:N)rschemeslower startswithlen)rschemes }/builddir/build/BUILD/imunify360-venv-2.6.2/opt/imunify360/venv/lib/python3.11/site-packages/pip/_internal/index/collector.py_match_vcs_schemer*.sW + 99;; ! !& ) ) c#f++.>$.F.FMMM 4c eZdZdfd ZxZS)_NotAPIContent content_typer request_descr!Nonecht||||_||_dSN)super__init__r.r/)selfr.r/ __class__s r)r4z_NotAPIContent.__init__:s3 |444((r+)r.r r/r r!r0)__name__ __module__ __qualname__r4 __classcell__r6s@r)r-r-9s=))))))))))r+r-responserr0c|jdd}|}|drdSt ||jj)z Check the Content-Type header to ensure the response contains a Simple API Response. Raises `_NotAPIContent` if the content type is not a valid content-type. Content-TypeUnknown)z text/htmlz#application/vnd.pypi.simple.v1+html#application/vnd.pypi.simple.v1+jsonN)headersgetr%r&r-requestmethod)r<r.content_type_ls r)_ensure_api_headerrF@sg#'' BBL!''))N     x'7'> ? ??r+ceZdZdS)_NotHTTPN)r7r8r9r+r)rHrHVsDr+rHsessionrctj|\}}}}}|dvrt||d}t |t |dS)z Send a HEAD request to the URL, and ensure the response contains a simple API Response. Raises `_NotHTTP` if the URL is not available for a HEAD request, or `_NotAPIContent` if the content type is not a valid content type. >httphttpsT)allow_redirectsN)urllibparseurlsplitrHheadrrF)rrJr(netlocpathqueryfragmentresps r)_ensure_api_responserXZsq-3L,A,A#,F,F)FFD% &&&jj <<T< 2 2DTtr+ctt|jrt||tdt |||dgddd}t|t|tdt ||j d d |S) aYAccess an Simple API response with GET, and return the response. This consists of three parts: 1. If the URL looks suspiciously like an archive, send a HEAD first to check the Content-Type is HTML or Simple API, to avoid downloading a large file. Raise `_NotHTTP` if the content type cannot be determined, or `_NotAPIContent` if it is not HTML or a Simple API. 2. Actually perform the request. Raise HTTP exceptions on network failures. 3. Check the Content-Type header to make sure we got a Simple API response, and raise `_NotAPIContent` otherwise. rJzGetting page %sz, )r@z*application/vnd.pypi.simple.v1+html; q=0.1ztext/html; q=0.01z max-age=0)Acceptz Cache-Control)rAzFetched page %s as %sr>r?) rrfilenamerXloggerdebugrrBjoinrrFrA)rrJrWs r)_get_simple_responser`lstCyy)**3S'2222 LL"$8$=$=>>> ;; ii()+     D4Tt LLS!! 33 Kr+rAResponseHeadersc|rSd|vrOtj}|d|d<|d}|rt |SdS)z=Determine if we have any encoding information in our headers.r>z content-typecharsetN)emailmessageMessage get_paramr )rAmrcs r)_get_encoding_from_headersris` >W,, M ! ! # ##N3.++i((  w<<  4r+c&eZdZd dZdd Zdd Zd S)CacheablePageContentpage IndexContentr!r0c&|jsJ||_dSr2)cache_link_parsingrlr5rls r)r4zCacheablePageContent.__init__s&&&& r+otherobjectboolcpt|t|o|jj|jjkSr2) isinstancetyperlr)r5rqs r)__eq__zCacheablePageContent.__eq__s*%d,,P%*.1PPr+intc4t|jjSr2)hashrlrr5s r)__hash__zCacheablePageContent.__hash__sDIM"""r+N)rlrmr!r0)rqrrr!rs)r!rx)r7r8r9r4rwr|rIr+r)rkrksTQQQQ######r+rkceZdZddZdS) ParseLinksrlrmr!Iterable[Link]cdSr2rIrps r)__call__zParseLinks.__call__sr+Nrlrmr!r)r7r8r9rrIr+r)r~r~sAAAAAAr+r~fnc|tjd fd tjd fd }|S) z Given a function that parses an Iterable[Link] from an IndexContent, cache the function's result (keyed by CacheablePageContent), unless the IndexContent `page` has `page.cache_link_parsing == False`. cacheable_pagerkr! list[Link]c>t|jSr2)listrl)rrs r)wrapperz*with_cached_index_content..wrappersBB~*++,,,r+rlrmcr|jrt|St|Sr2)rorkr)rlrrs r)wrapper_wrapperz2with_cached_index_content..wrapper_wrappers;  " 77/5566 6BBtHH~~r+)rrkr!r)rlrmr!r) functoolscachewraps)rrrs` @r)with_cached_index_contentrsr_-----_-_R r+rlrmrc#K|j}|drUtj|j}|dgD]#}tj||j }||V$dSt|j }|j pd}| |j ||j }|jp|}|jD] } tj| ||}||V!dS)z\ Parse a Simple API's Index Content, and yield its anchor elements as Link objects. r@filesNzutf-8)page_urlbase_url)r.r%r&jsonloadscontentrBr from_jsonrHTMLLinkParserencodingfeeddecoderanchors from_element) rlrEdatafilelinkparserrrranchors r) parse_linksrs! &,,..N  !FGGz$,''HHWb))  D>$11D|JJJJ DH % %F}'H KK ##H--... (C%#H. #III <  r+T)frozencReZdZUdZded<ded<ded<ded<d Zd ed <dd ZdS)rmaRepresents one response (or page), along with its URL. :param encoding: the encoding to decode the given content. :param url: the URL from which the HTML was downloaded. :param cache_link_parsing: whether links parsed from this page's url should be cached. PyPI index urls should have this set to False, for example. bytesrr r.r"rrTrsror!c*t|jSr2)rrr{s r)__str__zIndexContent.__str__s#DH---r+N)r!r )r7r8r9__doc____annotations__rorrIr+r)rmrmsrNNN HHH#####......r+c4eZdZdZd fd Zdd Zdd ZxZS)rzf HTMLParser that keeps the first base HREF and a list of all anchor elements' attributes. rr r!r0cvtd||_d|_g|_dS)NT)convert_charrefs)r3r4rrr)r5rr6s r)r4zHTMLLinkParser.__init__s7 $///$( 46 r+tagattrslist[tuple[str, str | None]]c|dkr)|j"||}| ||_dSdS|dkr)|jt |dSdS)Nbasea)rget_hrefrappenddict)r5rrhrefs r)handle_starttagzHTMLLinkParser.handle_starttagsn &==T]2==''D $   CZZ L  U , , , , ,Zr+r"c*|D]\}}|dkr|cSdS)NrrI)r5rnamevalues r)rzHTMLLinkParser.get_href!s1   KD%v~~ tr+)rr r!r0)rr rrr!r0)rrr!r")r7r8r9rr4rrr:r;s@r)rr so 777777----r+rrrreasonstr | ExceptionmethCallable[..., None] | Nonec<| tj}|d||dS)Nz%Could not fetch URL %s: %s - skipping)r]r^)rrrs r)_handle_get_simple_failr(s+  ||D 0$?????r+rorsc|t|j}t|j|jd||j|S)Nr>)rrro)rirArmrr)r<rors r)_make_index_contentr2sG*(*:;;H ( L-    r+IndexContent | Nonec|jddd}t|}|rtd||dS|drt jt|rU| ds|dz }tj |d}td| t|| }t!||j S#t$$rtd |Yn t&$r1}td ||j|jYd}~nd}~wt,$r}t/||Yd}~nd}~wt0$r}t/||Yd}~nd}~wt2$r:}d }|t5|z }t/||tjYd}~nRd}~wt8j$r}t/|d|Yd}~n(d}~wt8j$rt/|dYnwxYwdS)N#rrzICannot look at %s URL %s because it does not support lookup as web pages.zfile:/z index.htmlz# file: URL is directory, getting %srZ)roz`Skipping page %s because it looks like an archive, and cannot be checked by a HTTP HEAD request.zSkipping page %s because the %s request got Content-Type: %s. The only supported Content-Types are application/vnd.pypi.simple.v1+json, application/vnd.pypi.simple.v1+html, and text/htmlz4There was a problem confirming the ssl certificate: )rzconnection error: z timed out)rsplitr*r]warningr&osrTisdirrendswithrOrPurljoinr^r`rrorHr-r/r.rrrrr infor ConnectionErrorTimeout)rrJr vcs_schemerWexcrs r)_get_index_contentr?s (..a  #C#3''J W     t ~~g A27==S1A1A#B#B A||C    3JC l""3 55 :C@@@U#C999:#4Dz'LinkCollector.create..s+IIs-c22IIIIIIr+)rrno_index)rJr) index_urlextra_index_urlsrr]r^r_rrcreater)clsrJrrrrrlink_collectors r)rzLinkCollector.creates'(7+CC   $5  LL&IIjIIIII   J'-2 ")!!%   '%   r+ list[str]c|jjSr2)rrr{s r)rzLinkCollector.find_linkss ++r+locationrrc.t||jS)z> Fetch an HTML page containing package links. rZ)rrJ)r5rs r)fetch_responsezLinkCollector.fetch_responses"(DLAAAAr+ project_namer candidates_from_pagerrcztjfdjD}tjfdjD}t tj redtj ||D}t|ddg|z}t d|tt!|t!|S)Nc 3VK|]#}t|jjddV$dS)Frpage_validator expand_dirrorNrrJis_secure_originrlocrrr5s r)rz0LinkCollector.collect_sources..s_ 4 4  %9#|< #()     4 4 4 4 4 4 r+c 3VK|]#}t|jjddV$dS)TrNrrs r)rz0LinkCollector.collect_sources..s_ 5 5  %9#|<#')     5 5 5 5 5 5 r+c4g|]}||j d|jS)Nz* )r)rss r) z1LinkCollector.collect_sources..s6=QV%7QV %7%7%7r+z' location(s) to search for versions of : )rr) collections OrderedDictrget_index_urls_locationsvaluesrr] isEnabledForloggingDEBUG itertoolschainr'r^r_rr)r5rrindex_url_sourcesfind_links_sourcesliness``` r)collect_sourceszLinkCollector.collect_sourcess (3 4 4 4 4 4 4 (AA,OO 4 4 4    &(( )4 5 5 5 5 5 5  5 5 5    &((    w} - - +");=NOOE u::33#/333E LL5)) * * *.//-..    r+N)rJrrrr!r0)F)rJrrr rrsr!r)r!r)rrr!r)rr rrr!r) r7r8r9rr4 classmethodrpropertyrrr rIr+r)rrs #( [B,,,X,BBBB , , , , , , r+r)rr r!r")r<rr!r0)rr rJrr!r0)rr rJrr!r)rArar!r")rr~r!r~rr2)rrrrrrr!r0)T)r<rrorsr!rm)rrrJrr!r)Pr __future__rr email.messagerdrrrrr urllib.parserOcollections.abcrrr dataclassesr html.parserroptparser typingr r r pip._vendorr pip._vendor.requestsrpip._vendor.requests.exceptionsrrpip._internal.exceptionsrpip._internal.models.linkr!pip._internal.models.search_scoperpip._internal.network.sessionrpip._internal.network.utilsrpip._internal.utils.filetypesrpip._internal.utils.miscrpip._internal.utils.urlsrpip._internal.vcsrsourcesrrr getLoggerr7r]r rar* Exceptionr-rFrHrXr`rirkr~rrrmrrrrrrrIr+r)r%s#"""""  >>>>>>>>>>!!!!!!"""""" ! ))))))@@@@@@@@;;;;;;******999999444444888888999999999999000000!!!!!!AAAAAAAAAA  8 $ $ c*)))))Y)))@@@@,     y   $<<<<~ # # # # # # # #BBBBBBBB(8 $........(Z>(,@@@@@48     9999x,,,,,z,,, h h h h h h h h h h r+PK!L))*__pycache__/package_finder.cpython-312.pycnu[ -r*jdZddlmZddlZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl mZmZmZddlmZddlmZdd lmZmZdd lmZmZdd lmZdd lmZmZm Z m!Z!m"Z"dd l#m$Z$m%Z%ddl&m'Z'ddl(m)Z)ddl*m+Z+ddl,m-Z-ddl.m/Z/ddl0m1Z1ddl2m3Z3ddl4m5Z5ddl6m7Z7ddl8m9Z9ddl:m;Z;ddlm?Z?ddl@mAZAddlBmCZCddlDmEZEddlFmGZGerddlHmIZIgd ZJe;eKZLeeMd!eMeNeOffZPeMeNeNeNeeeNePfZQ d4 d5d"ZRGd#d$ejZTGd%d&ZU d6d'ZVe Gd(d)ZWe d*+Gd,d-ZXGd.d/ZYGd0d1ZZd7d2Z[d8d3Z\y)9z!Routines related to PyPI, indexes) annotationsN)Iterable) dataclass) TYPE_CHECKINGOptionalUnion) specifiers)Tag)NormalizedNamecanonicalize_name)InvalidVersion _BaseVersion)parse)BestVersionAlreadyInstalledDistributionNotFoundInstallationErrorInvalidWheelFilenameUnsupportedWheel) LinkCollector parse_links)select_backend)InstallationCandidate) FormatControl)Link)ReleaseControl) SearchScope)SelectionPreferences) TargetPython)Wheel)InstallRequirement) getLogger)WHEEL_EXTENSION)Hashes) indent_log) build_netloc)check_requires_python)SUPPORTED_EXTENSIONS) TypeGuard)rBestCandidateResult PackageFindercx t|j|}|sfdjtt|}|s#t j d||j|yt jd||j|y#tj$r$t jd|j|YywxYw)aa Return whether the given Python version is compatible with a link's "Requires-Python" value. :param version_info: A 3-tuple of ints representing the Python major-minor-micro version to check. :param ignore_requires_python: Whether to ignore the "Requires-Python" value if the given Python version isn't compatible. ) version_info.z4Link requires a different Python (%s not in: %r): %sFzBIgnoring failed Requires-Python check (%s not in: %r) for link: %sz2Ignoring invalid Requires-Python (%r) for link: %sT) r&requires_pythonjoinmapstrloggerverbosedebugr InvalidSpecifier)linkr-ignore_requires_python is_compatibleversions Q/opt/hc_python/lib/python3.12/site-packages/pip/_internal/index/package_finder.py_check_link_requires_pythonr<?s-  % hhs3 56G)J((   LLT$$   3  & &  @   0 3 sB4B98B9c>eZdZejZejZejZejZejZ ejZ ejZ ejZ ejZ y)LinkTypeN)__name__ __module__ __qualname__enumauto candidatedifferent_projectyankedformat_unsupportedformat_invalidplatform_mismatchrequires_python_mismatchupload_too_lateupload_time_missingr+r;r>r>ns| I!  TYY[F"TYY[N! (tyy{diikO#$))+rMr>cheZdZdZej dZ d ddZddZy) LinkEvaluatorzD Responsible for evaluating links for a particular project. z-py([123]\.?[0-9]?)$Ncf||_||_||_||_||_||_||_y)aB :param project_name: The user supplied package name. :param canonical_name: The canonical package name. :param formats: The formats allowed for this package. Should be a set with 'binary' or 'source' or both in it. :param target_python: The target Python interpreter to use when evaluating link compatibility. This is used, for example, to check wheel compatibility, as well as when checking the Python version, e.g. the Python version embedded in a link filename (or egg fragment) and against an HTML link's optional PEP 503 "data-requires-python" attribute. :param allow_yanked: Whether files marked as yanked (in the sense of PEP 592) are permitted to be candidates for install. :param ignore_requires_python: Whether to ignore incompatible PEP 503 "data-requires-python" values in HTML links. Defaults to False. :param uploaded_prior_to: If set, only allow links uploaded prior to the given datetime. N) _allow_yanked_canonical_name_ignore_requires_python_formats_target_python_uploaded_prior_to project_name)selfrWcanonical_nameformats target_python allow_yankedr8uploaded_prior_tos r;__init__zLinkEvaluator.__init__s;<*-'=$ +"3(rMcFd}|jr1|js%|jxsd}tjd|fS|j r|j }|j }ni|j\}}|stjdfS|tvrtjd|fSd|jvr*|tk(r!d|j}tj|fSd|jvr|d k(rtjd fS|tk(r t|j}|j$|j&k7r"d |jd }tj(|fS|j*j-}|j/|s7dj1|j3}d|d}tj4|fS|j6}|j8|j:s|j<3|j>rd|j>} nd} tj@| dfS|j<|j8k\r,tjBd|j<d|j8fSd|jvr*|tk7r!d|j}tj|fS|stE||j&}|s!d|j}tj"|fS|jFjI|} | rO|d| jK}| jMd} | |j*jNk7rtj4dfStQ||j*jR|jT} | sa|jV} | r:d"d}dj1tYdt[j\| D|} |d | }tj^|fSt`jcd!||tjd|fS#t $rtj"d fcYSwxYw)#a Determine whether a link is a candidate for installation. :return: A tuple (result, detail), where *result* is an enum representing whether the evaluation found a candidate, or the reason why one is not found. If a candidate is found, *detail* will be the candidate's version string; if one is not found, it contains the reason the link fails to qualify. Nz zyanked for reason: z not a filezunsupported archive format: binaryzNo binaries permitted for macosx10z.zipz macosx10 onezinvalid wheel filenamezwrong project name (not ), znone of the wheel's tags (zB) are compatible (run pip debug --verbose to show compatible tags)zIndex Indexz' does not provide upload-time metadata.z Upload time z not prior to sourcezNo sources permitted for zMissing project version for zPython version is incorrect)r-r8cDtd|jdDS)Nc3TK|] }|jst|"ywN)isdigitint.0ss r; zLLinkEvaluator.evaluate_link..get_version_sort_key..s MAQs((r.)tuplesplit)vs r;get_version_sort_keyz9LinkEvaluator.evaluate_link..get_version_sort_keys M MMMrM,c32K|]}t|ywri)r2rls r;roz.LinkEvaluator.evaluate_link.. sR)QAQ)Qskeyz Requires-Python zFound link %s, version: %s)rrr2returnztuple[int, ...])3 is_yankedrQ yanked_reasonr>rF egg_fragmentextsplitextrGr'rTr"rWpathrfilenamerrHnamerRrErUget_unsorted_tags supportedr0get_formatted_file_tagsrIr:rVis_file upload_time comes_fromrLrK_extract_version_from_fragment_py_version_researchstartgroup py_versionr<py_version_inforSr/sortedr SpecifierSetrJr3r5rD)rXr7r:reasonegg_infor|wheelsupported_tags file_tags index_infomatchrsupports_pythonr/rss r; evaluate_linkzLinkEvaluator.evaluate_links( >>$"4"4''9>FOO':6(%CD D   ((H((C MMOMHc 33\BB..//23%8t}},1G5d6G6G5HI 33V<<TYY&3&= 33^DDo%!$--0E ::!5!5578I8I7J!LF$66??!%!4!4!F!F!H~6!% %*G*G*I JI4YK@LM%66??--  " " .t||'??#)$//):!;J!(J00!l"IJ!!T%<%<<,,"4#3#3"45 $ 7 78: 4== (SO-C01B1B0CDF//8 84$$G3D4E4E3FGF++V4 4##**73 o .GQJT00;;;..1 6 ,,<<#'#?#?  "22ON#&((R)@)@)QR0#  y 1/1BCF55v> > 14A""G,,u, //0sPP P )FN)rWr2rYr rZzfrozenset[str]r[rr\boolr8rr]datetime.datetime | NonerxNone)r7rrxztuple[LinkType, str]) r?r@rA__doc__recompilerr^rr+rMr;rOrOzs| RZZ 78N(-6:%)%)'%) %) $ %)  %)!%%)4%) %)N}-rMrOc L|s+tjdt||t|Sg}g}d}|D]V}|j}|j sn*|j |r|dz }n|j|F|j|X|r|}n t|}t|t|k(rd} n1djt|djd|D} tjd t|||j|t||z | |S) a Filter out candidates whose hashes aren't allowed, and return a new list of candidates. If at least one candidate has an allowed hash, then all candidates with either an allowed hash or no hash specified are returned. Otherwise, the given candidates are returned. Including the candidates with no hash specified when there is a match allows a warning to be logged if there is a more preferred candidate with no hash specified. Returning all candidates in the case of no matches lets pip report the hash of the candidate that would otherwise have been installed (e.g. permitting the user to more easily update their requirements file with the desired hash). zJGiven no hashes to check %s links for project %r: discarding no candidatesr)hashesrfzdiscarding no candidateszdiscarding {} non-matches: {}z c3FK|]}t|jywri)r2r7)rmrDs r;roz*filter_unallowed_hashes..esI[ INN+[s!zPChecked %s links for project %r against %s hashes (%s matches, %s no digest): %s) r3r5lenlistr7has_hashis_hash_allowedappendformatr0 digest_count) candidatesrrWmatches_or_no_digest non_matches match_countrDr7filtereddiscard_messages r;filter_unallowed_hashesr,s,(   '  O   JKK ~~}}   ! ! ! 0 1 K   y ) ##I. ' # 8}J'4<CC   KKI[I I   LL ) J !K/  OrMc.eZdZUdZdZded<dZded<y)CandidatePreferenceszk Encapsulates some of the preferences for filtering and sorting InstallationCandidate objects. Fr prefer_binaryNReleaseControl | Nonerelease_control)r?r@rArr__annotations__rr+rMr;rrvs  M4-1O*1rMrT)frozenc8eZdZUdZded<ded<ded<d dZy) r)aA collection of candidates, returned by `PackageFinder.find_best_candidate`. This class is only intended to be instantiated by CandidateEvaluator's `compute_best_candidate()` method. :param all_candidates: A sequence of all available candidates found. :param applicable_candidates: The applicable candidates. :param best_candidate: The most preferred candidate found, or None if no applicable candidates were found. list[InstallationCandidate]all_candidatesapplicable_candidatesInstallationCandidate | Nonebest_candidatect|jt|jksJ|j|jrJy|j|jvsJyri)setrrrrXs r; __post_init__z!BestCandidateResult.__post_init__s^4--.#d6I6I2JJJJ    &11 111&&$*D*DD DDrMNrxr)r?r@rArrrr+rMr;r)r)s! 0/6600ErMr)ceZdZdZe d d dZ d d dZ d dZddZ ddZ ddZ y)CandidateEvaluatorzm Responsible for filtering and sorting candidates for installation based on what tags are valid. Nc| t}|tj}|j}|||||||S)aCreate a CandidateEvaluator object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. :param specifier: An optional object implementing `filter` (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable versions. :param hashes: An optional collection of allowed hashes. )rWr specifierrrr)rr rget_sorted_tags)clsrWr[rrrrrs r;createzCandidateEvaluator.createsR(  (NM  "//1I&668%)'+   rMc||_||_||_||_||_||_t |Dcic]\}}|| c}}|_ycc}}w)z :param supported_tags: The PEP 425 tags supported by the target Python in order of preference (most preferred first). N)_release_control_hashes_prefer_binary _project_name _specifier_supported_tags enumerate_wheel_tag_preferences) rXrWrrrrridxtags r;r^zCandidateEvaluator.__init__sc!0 +)#- &/~%>' %>cCH%>' #' s AcB|j/|jjt|j}nd}|j}|j ||d}t t||j|j}t||jS)zM Return the applicable candidates from a list of candidates. Ncrtjdk(rt|jS|jS)N pkg_resources)rNAMEr2r:)cs r;z>CandidateEvaluator.get_applicable_candidates..s1!#((O;AIIYYrM) prereleasesrw)rrrWrv) rallows_prereleasesr rrfilterrrrr _sort_key)rXrallow_prereleasesrrfiltered_applicable_candidatess r;get_applicable_candidatesz,CandidateEvaluator.get_applicable_candidatess  , $ 5 5 H H!$"4"45! !% OO !* 0 0 )!1! *A12<<++* & 4$..IIrMc|j}t|}d}d}|j}|jrNt |j } |j ||j }|jrd}|j}n| }t|j|j} dt|jz} | | ||j ||fS#t$rt|j dwxYw)a) Function to pass as the `key` argument to a call to sorted() to sort InstallationCandidates by preference. Returns a tuple such that tuples sorting as greater using Python's default comparison operator are more preferred. The preference is as follows: First and foremost, candidates with allowed (matching) hashes are always preferred over candidates without matching hashes. This is because e.g. if the only candidate with an allowed hash is yanked, we still want to use that candidate. Second, excepting hash considerations, candidates that have been yanked (in the sense of PEP 592) are always less preferred than candidates that haven't been yanked. Then: If not finding wheels, they are sorted by version only. If finding wheels, then the sort order is by version, then: 1. existing installs 2. wheels ordered via Wheel.support_index_min(self._supported_tags) 3. source archives If prefer_binary was set, then all wheels are sorted above sources. Note: it was considered to embed this logic into the Link comparison operators, but then different sdist links with the same version, would have to be considered equal r+rz@ is not a supported wheel for this platform. It can't be sorted.rf)rrr7is_wheelrrfind_most_preferred_tagr ValueErrorrr build_tagrkrrryr:) rXrD valid_tags support_numrbinary_preferencer7rprihas_allowed_hash yank_values r;rzCandidateEvaluator._sort_keys<)) *o  ~~ ==$--(E 11"D$?$?""$%!I.Ct33DLLAB#dnn--            &~~&''' s C"C5c:|syt||j}|S)zy Return the best candidate per the instance's sort order, or None if no candidate is acceptable. Nrv)maxr)rXrrs r;sort_best_candidatez&CandidateEvaluator.sort_best_candidateGs ZT^^<rMcb|j|}|j|}t|||S)zF Compute and return a `BestCandidateResult` instance. )rr)rrr))rXrrrs r;compute_best_candidatez)CandidateEvaluator.compute_best_candidateTs<!% > >z J112GH" "7)  rM)NFNNN)rWr2r[TargetPython | Nonerrrrrspecifiers.BaseSpecifier | Noner Hashes | Nonerxr)FNN)rWr2rz list[Tag]rzspecifiers.BaseSpecifierrrrrrrrxr)rrrxr)rDrrxCandidateSortingKey)rrrxr)rrrxr)) r?r@rAr classmethodrr^rrrrr+rMr;rrs .2#1559 $! ! +!  ! / ! 3 ! !  ! ! P$15 $  " ,    /     4%J/%J %%JN? B /  &  /   rMrceZdZdZ d ddZe d d!dZed"dZed#dZ e jd$dZ ed%dZ ed%d Z ed&d Z ed'd Zed&d Zed&d Zed(dZd)dZed*dZd+dZed,dZd%dZd-dZd.dZd/dZ d0dZ d1dZ d2dZd3dZ d d4dZ d d5dZ d6dZ y)7r*zThis finds packages. This is meant to match easy_install's technique for looking for packages, by reading pages and looking for appropriate links. Nc| t}|xsttt}||_||_||_||_||_||_||_ t|_ i|_ i|_ y)a This constructor is primarily meant to be used by the create() class method and from tests. :param format_control: A FormatControl object, used to control the selection of source packages / binary packages when consulting the index and links. :param candidate_prefs: Options to use when creating a CandidateEvaluator object. N) rrrrQ_candidate_prefsrS_link_collectorrUrVformat_control_requires_python_skipped_all_candidates_best_candidates)rXlink_collectorr[r\rcandidate_prefsr8r]s r;r^zPackageFinder.__init__ms(  "24O'F=+F) /'=$-+"3, 36%%HJ  rMc | t}t|j|j}|||||j|j |j |S)aCreate a PackageFinder. :param selection_prefs: The candidate selection preferences, as a SelectionPreferences object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. :param uploaded_prior_to: If set, only find links uploaded prior to the given datetime. )rr)rrr[r\rr8r])rrrrr\rr8)rrselection_prefsr[r]rs r;rzPackageFinder.createsc$  (NM.)77+;;  +)'(55*99#2#I#I/  rMc|jSri)rUrs r;r[zPackageFinder.target_pythons"""rMc.|jjSrir search_scopers r;rzPackageFinder.search_scopes##000rMc&||j_yrir)rXrs r;rzPackageFinder.search_scopes,8)rMc.|jjSri)r find_linksrs r;r zPackageFinder.find_linkss##...rMc.|jjSri)r index_urlsrs r;r zPackageFinder.index_urlss  +++rMcB|jjjSri)rsession pip_proxyrs r;proxyzPackageFinder.proxys##++555rMc#jK|jjjD] }t|ywri)rr pip_trusted_originsr%)rX host_ports r; trusted_hostszPackageFinder.trusted_hostss.--55III * *Js13cj|jjj}t|tr|SdSri)rr verify isinstancer2)rXrs r; custom_certzPackageFinder.custom_certs/ %%--44#FC0v:d:rMct|jjj}t|trJd|S)Nz"pip only supports PEM client certs)rr certrrp)rXrs r; client_certzPackageFinder.client_certs4##++00dE*P,PP* rMc.|jjSrirrrs r;rzPackageFinder.release_controls$$444rMc&||j_yrir)rXrs r;set_release_controlz!PackageFinder.set_release_controls0?-rMc.|jjSrirrrs r;rzPackageFinder.prefer_binarys$$222rMc&d|j_y)NTr rs r;set_prefer_binaryzPackageFinder.set_prefer_binarys.2+rMc|jSri)rVrs r;r]zPackageFinder.uploaded_prior_tos&&&rMc,t|jSri)rrrs r;requires_python_skipped_reasonsz-PackageFinder.requires_python_skipped_reasonssd3344rMc t|}|jj|}t||||j|j |j |jS)N)rWrYrZr[r\r8r])r rget_allowed_formatsrOrUrQrSrV)rXrWrYrZs r;make_link_evaluatorz!PackageFinder.make_link_evaluators\*<8%%99.I%)--++#'#?#?"55  rMcgg}}t}|D]G}||vs|j||jr|j|7|j|I||zS)z Returns elements of links in order, non-egg links first, egg links second, while eliminating duplicates )raddr{r)rXlinkseggsno_eggsseenr7s r; _sort_linkszPackageFinder._sort_linkss^ Bg%D4$$KK%NN4( ~rMctjd|||tjk(r|jj |yy)NzSkipping link: %s: %s)r3r5r>rJrr*)rXr7resultdetails r;_log_skipped_linkzPackageFinder._log_skipped_link!s<  ,fd; X66 6  ) ) - -f 5 7rMc|j|\}}|tjk(r t||tjk7r|j |||y t |j||S#t$rYywxYw)z If the link is a candidate for install, convert it to an InstallationCandidate and return it. Otherwise, return None. N)rr7r:) rr>rLrrDr3rrWr )rXlink_evaluatorr7r1r2s r;get_install_candidatez#PackageFinder.get_install_candidate(s(55d; X11 1$F+ + X'' '  " "4 8 (#00    sA33 A?>A?cg}|j|D](}|j||}||j|*|S)zU Convert links that are candidates to InstallationCandidate objects. )r/r6r)rXr5r+rr7rDs r;evaluate_linkszPackageFinder.evaluate_linksAsL  $$U+D22>4HI$!!),, rMctjd||jj|}|gSt t |}t 5|j||}ddd|S#1swYSxYw)Nz-Fetching project page and analyzing links: %s)r+)r3r5rfetch_responserrr$r8)rX project_urlr5index_response page_links package_linkss r;process_project_urlz!PackageFinder.process_project_urlOs  ;  --<<[I  !I+n56 \ // 0M   s A22A<c||jvr|j|S|j|}|jj|t j |j |}tjjd|D}t|}tjjd|D}|j|t|d}tjtj rn|rlg}|D]@} | j"j$sJ |j'| j"j(Btj-ddj/|||z|j|<|j|S#t*$r(|j'| j"j$YwxYw) aFind all available InstallationCandidate for project_name This checks index_urls and find_links. All versions found are returned as an InstallationCandidate list. See LinkEvaluator.evaluate_link() for details on which files are accepted. )r5)rWcandidates_from_pagec3NK|]}|D]}||jywri)page_candidatesrmsourcesres r;roz4PackageFinder.find_all_candidates..zs4; ,!!  " " $! %,#%c3NK|]}|D]}||jywri) file_linksrDs r;roz4PackageFinder.find_all_candidates..s46 ,!!    ! ,rFT)reversezLocal files found: %src)rr(rcollect_sources functoolspartialr? itertoolschain from_iterablerr8rr3 isEnabledForloggingDEBUGr7urlr file_path Exceptionr5r0) rXrWr5collected_sourcespage_candidates_itrC file_links_itfile_candidatespathsrDs r;find_all_candidatesz!PackageFinder.find_all_candidatesds 4// /'' 5 511,? 00@@%!*!2!2((-"A '__::; ,;   12!556 ,6  --  =$ /    w}} -/E,  ~~))))5LL!9!9:- LL0$))E2B C.=-N\*##L11!5LL!3!345s$%F.GGc|j}tj||j|j|j ||S)z*Create a CandidateEvaluator object to use.)rWr[rrrr)rrrrUrr)rXrWrrrs r;make_candidate_evaluatorz&PackageFinder.make_candidate_evaluatorsK//!((%--)77+;; )  rMc|||f|jvr|j|||fS|j|}|j|||}|j||j|||f<|j|||fS)aFind matches for the given project and specifier. :param specifier: An optional object implementing `filter` (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable versions. :return: A `BestCandidateResult` instance. )rWrr)rr[r]r)rXrWrrrcandidate_evaluators r;find_best_candidatez!PackageFinder.find_best_candidates )V ,0E0E E((y&)HI I--l; ";;%<  6 6z B lIv=>$$\9f%DEErMcL |j}|Jd|jd}|j||j|}|j d |j |j j dd} p nd}|j*|jjt|}|durd}tjd ||||jtd | d fd } |sC A| r"tjd j ytjd y| r3tjd j ||j Stjd ||jt )zTry to find a Link matching req Expects req, an InstallRequirement and upgrade, a boolean Returns a InstallationCandidate if found, Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise Nz&find_requirement() called with no nameF)trust_internet)rrc djt|Dchc]}t|jc}txsdScc}w)Nrcrvnone)r0rr2r: parse_version) cand_iterrs r;_format_versionsz8PackageFinder.find_requirement.._format_versionssI  1:;AQYY;)  ._should_install_candidates)!(%!)),== =rMzUExisting installed version (%s) satisfies requirement (most up-to-date version is %s)zLExisting installed version (%s) is most up-to-date and satisfies requirementz)Using version %s (newest of versions: %s)z=Installed version (%s) is most up-to-date (past versions: %s))rfzIterable[InstallationCandidate]rxr2)rDrrxz TypeGuard[InstallationCandidate])rrr`rr satisfied_byr:rrr r3criticalrrr5rr) rXrequpgraderrbest_candidate_resultrg version_type allows_prerjrris @@r;find_requirementzPackageFinder.find_requirementsxxI!II51 $ 8 8 mm!9!  /==15    ' # 0 0 8 8    $)?$L##/!11DD%d+ L OO& !6!E!EF  ')LSE'RS S >3 > - >,8(8 6%"**   ,%  $^ 4 LL;&& !6!L!LM  " !  K  2HH I *)rM)NNFN)rrr[rr\rrzFormatControl | NonerzCandidatePreferences | Noner8rr]rrxr)NN) rrrrr[rr]rrxr*)rxr)rxr)rrrxr)rxz list[str])rx str | None)rxz Iterable[str])rxr)rrrxr)rxrr)rxr)rWr2rxrO)r+Iterable[Link]rxz list[Link])r7rr1r>r2r2rxr)r5rOr7rrxr)r5rOr+rtrxr)r;rr5rOrxr)rWr2rxr)rWr2rrrrrxr)rWr2rrrrrxr))rmr rnrrxr)!r?r@rArr^rrpropertyr[rsetterr r rrrrrrrr"r]r%r(r/r3r6r8r?r[r]r`rrr+rMr;r*r*fs047;',6:,%,$, , - , 5 ,!%,4, ,d .26: ! %! .! + ! 4 !  ! ! F##1199//,,66++;; 55@333''5   6+37 %2 + 4B  $ 1> $*72x6: $   3     (6: $ FF3F F  F:b*%b*04b* %b*rMr*c~t|D] \}}|dk7r t|d||k(s|cSt|d|)aFind the separator's index based on the package's canonical name. :param fragment: A + filename "fragment" (stem) or egg fragment. :param canonical_name: The package's canonical name. This function is needed since the canonicalized name does not necessarily have the same length as the egg info's name part. An example:: >>> fragment = 'foo__bar-1.0' >>> canonical_name = 'foo-bar' >>> _find_name_version_sep(fragment, canonical_name) 8 -Nz does not match )rr r)fragmentrYirs r;_find_name_version_sepr{0sS$(#1 8  Xbq\ *n <H $ z!1.1AB CCrMcT t||dz}||d}|sy|S#t$rYywxYw)zParse the version string from a + filename "fragment" (stem) or egg fragment. :param fragment: The string to parse. E.g. foo-2.1 :param canonical_name: The canonicalized name of the package this belongs to. rfN)r{r)ryrY version_startr:s r;rrJsE.xH1L }~&G  N s  '')F)r7rr-ztuple[int, int, int]r8rrxr)rrrrrWr2rxr)ryr2rYr2rxrk)ryr2rYr2rxrs)]r __future__rdatetimerBrKrMrQrcollections.abcr dataclassesrtypingrrrpip._vendor.packagingr pip._vendor.packaging.tagsr pip._vendor.packaging.utilsr r pip._vendor.packaging.versionr rrrepip._internal.exceptionsrrrrrpip._internal.index.collectorrrpip._internal.metadatarpip._internal.models.candidater#pip._internal.models.format_controlrpip._internal.models.linkr$pip._internal.models.release_controlr!pip._internal.models.search_scoper$pip._internal.models.selection_prefsr"pip._internal.models.target_pythonrpip._internal.models.wheelrpip._internal.reqr pip._internal.utils._logr!pip._internal.utils.filetypesr"pip._internal.utils.hashesr#pip._internal.utils.loggingr$pip._internal.utils.miscr%pip._internal.utils.packagingr&pip._internal.utils.unpackingr'typing_extensionsr(__all__r?r3rprkr2BuildTagrr<Enumr>rOrrr)rr*r{rr+rMr;rs'"  $! -*IF@E1@=*?9E;,0.9-21?>+ C 8  rE#s(O+ ,Cc<#PQ $), ,&,!, ,^ &tyy &o-o-dG+G GG! GT 22 2 $EEE2H H VG*G*TD4rMPK!?R"$__pycache__/__init__.cpython-312.pycnu[ -r*jdZy)zIndex interaction codeN)__doc__K/opt/hc_python/lib/python3.12/site-packages/pip/_internal/index/__init__.pyrsrPK!Ȏug//#__pycache__/sources.cpython-312.pycnu[ -r*j!ddlmZddlZddlZddlZddlmZddlmZddl m Z ddl m Z m Z mZmZmZddlmZddlmZdd lmZmZdd lmZej4eZeeZeeZe egeefZe ege fZ!Gd d Z"dd Z#GddZ$Gdde"Z%Gdde"Z&Gdde"Z'Gdde"Z( ddZ)y)) annotationsN) defaultdict)Iterable)Callable)InvalidSdistFilenameInvalidWheelFilenamecanonicalize_nameparse_sdist_filenameparse_wheel_filename)InstallationCandidate)Link) path_to_url url_to_path)is_urlc.eZdZeddZddZddZy) LinkSourcect)z,Returns the underlying link, if there's one.NotImplementedErrorselfs J/opt/hc_python/lib/python3.12/site-packages/pip/_internal/index/sources.pylinkzLinkSource.link s "##ct)z9Candidates found by parsing an archive listing HTML file.rrs rpage_candidateszLinkSource.page_candidates% !##rct)z,Links found by specifying archives directly.rrs r file_linkszLinkSource.file_links)rrNreturnz Link | Noner!FoundCandidatesr! FoundLinks)__name__ __module__ __qualname__propertyrrrrrrrs $$$$rrc<tj|dddk(S)NF)strictrz text/html) mimetypes guess_type)file_urls r _is_html_filer0.s    7 :k IIrcDeZdZdZddZddZed dZed dZy) _FlatDirectoryToUrlsz"Scans directory and caches resultscV||_g|_tt|_d|_y)NF)_path_page_candidatesrlist_project_name_to_urls_scanned_directory)rpaths r__init__z_FlatDirectoryToUrls.__init__5s& +-;Ft;L""'rctj|jD]u}t|j}t |r|j j|? t|jd}|j|j|wd|_y#t$r- t|jd}n#t$rYYwxYwY]wxYw)zrScans directory once and populates both page_candidates and project_name_to_urls at the same time rTN)osscandirr4rr9r0r5appendr namerr rr7r8)rentryurlproject_filenames r_scan_directoryz$_FlatDirectoryToUrls._scan_directory;sZZ +Eejj)CS!%%,,S1 #7 #CA#F   & &'7 8 ? ? D!,"#'( ';EJJ'G'J$+% s6 B  C*CC C CCCCcR|js|j|jSN)r8rCr5rs rrz$_FlatDirectoryToUrls.page_candidatesRs#&&  "$$$rcR|js|j|jSrE)r8rCr7rs rproject_name_to_urlsz)_FlatDirectoryToUrls.project_name_to_urlsYs#&&  ")))rN)r9strr!None)r!rI)r!z list[str])r!zdict[str, list[str]]) r&r'r(__doc__r:rCr)rrGr*rrr2r22s7,( '.%% **rr2cZeZdZUdZiZded< d dZed dZd dZ d dZ y) _FlatDirectorySourcezLink source specified by ``--find-links=``. This looks the content of the directory, and returns: * ``page_candidates``: Links listed on each HTML file in the directory. * ``file_candidates``: Archives in the directory. zdict[str, _FlatDirectoryToUrls]_paths_to_urlsc||_t||_||jvr|j||_yt ||_|j|j|<y)N)r9)_candidates_from_pager _project_namerM _path_to_urlsr2)rcandidates_from_pager9 project_names rr:z_FlatDirectorySource.__init__ls_ &:".|< 4&& &!%!4!4T!:D !54!@D (,(:(:D   %rcyrEr*rs rrz_FlatDirectorySource.link|src#K|jjD]$}|jt|Ed{&y7wrE)rQrrOr rrAs rrz$_FlatDirectorySource.page_candidatess7%%55C11$s)< < <6 `` or ``--[extra-]index-url=``. If a URL is supplied, it must be a ``file:`` URL. If a path is supplied to the option, it is converted to a URL first. This returns: * ``page_candidates``: Links listed on an HTML file. * ``file_candidates``: The non-HTML file. c ||_||_yrErO_linkrrRrs rr:z_LocalFileSource.__init__ &:" rc|jSrEr^rs rrz_LocalFileSource.link zzrc#Kt|jjsy|j|jEd{y7wrE)r0r^rArOrs rrz _LocalFileSource.page_candidatess1TZZ^^, --djj999s?A AA c#hKt|jjry|jywrE)r0r^rArs rrz_LocalFileSource.file_linkss#  ( jjs02NrRrXrr r!rIr r"r$ r&r'r(rJr:r)rrrr*rrr[r[sF0  : rr[cJeZdZdZ ddZeddZd dZd dZy) _RemoteFileSourcez``--find-links=`` or ``--[extra-]index-url=``. This returns: * ``page_candidates``: Links listed on an HTML file. * ``file_candidates``: The non-HTML file. c.||_||_||_yrE)rO_page_validatorr^)rrRpage_validatorrs rr:z_RemoteFileSource.__init__s &:"- rc|jSrErbrs rrz_RemoteFileSource.linkrcrc#K|j|jsy|j|jEd{y7wrE)rkr^rOrs rrz!_RemoteFileSource.page_candidatess3##DJJ/ --djj999s;AAAc#(K|jywrErbrs rrz_RemoteFileSource.file_linkssjjsN)rRrXrl PageValidatorrr r!rIr r"r$rgr*rrririsP0&   : rricFeZdZdZ ddZeddZd dZd dZy) _IndexDirectorySourcez``--[extra-]index-url=``. This is treated like a remote URL; ``candidates_from_page`` contains logic for this by appending ``index.html`` to the link. c ||_||_yrEr]r_s rr:z_IndexDirectorySource.__init__r`rc|jSrErbrs rrz_IndexDirectorySource.linkrcrc#VK|j|jEd{y7wrEr]rs rrz%_IndexDirectorySource.page_candidatess--djj999s )')cy)Nr*r*rs rrz _IndexDirectorySource.file_linkssrNrfr r"r$rgr*rrrrrrsF 0  :rrrcxd}d}tjj|rt|}|}n,|j dr|}t |}n t |r|}|d}tj||y|t||t||} || fStjj|r0|rt|||} || fSt|t||} || fStjj|rt|t||} || fStjd||dfS) Nzfile:zVLocation '%s' is ignored: it is either a non-existing path or lacks a specific scheme.)NN)cache_link_parsing)rRrlr)rRr9rS)rRrz?Location '%s' is ignored: it is neither a file nor a directory.)r<r9existsr startswithrrloggerwarningrir isdirrLrrisfiler[) locationrRrl expand_dirrxrSr9rAmsgsources r build_sourcersPDC ww~~h(#   W %8$   { K  sH% |.!5)c.@A  V} ww}}T )%9)FV} +%9#2DEFV}  !!5c.@A V} NNI ;r)r/rHr!bool)rrHrRrXrlrprrrxrrSrHr!z$tuple[str | None, LinkSource | None])* __future__rloggingr-r< collectionsrcollections.abcrtypingrpip._vendor.packaging.utilsrrr r r pip._internal.models.candidater pip._internal.models.linkr pip._internal.utils.urlsrrpip._internal.vcsr getLoggerr&r{r#r%rXrrprr0r2rLr[rirrrr*rrrs" #$A*=$   8 $01 d^ tfh/D&EEF$&  $ $J,*,*^%:%PzB @J4;;-;" ;  ;  ;;*;rPK! LRLR%__pycache__/collector.cpython-312.pycnu[ -r*j?dZddlmZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl mZmZmZddlmZddlmZddlmZddlmZmZmZdd lmZdd lmZdd lm Z m!Z!dd l"m#Z#dd l$m%Z%ddl&m'Z'ddl(m)Z)ddl*m+Z+ddl,m-Z-ddl.m/Z/ddl0m1Z1ddl2m3Z3ddl4m5Z5m6Z6m7Z7e jpe9Z:ee;e;fZZ?d4dZ@Gdde>ZAd5dZBd6dZCd7dZDGd d!ZEGd"d#eZFd8d$ZGeGd9d&ZHed'(Gd)d%ZIGd*d+eZJ d: d;d,ZK d< d=d-ZLd>d.ZMGd/d0eZNGd1d2ZOy)?zO The main purpose of this module is to expose LinkCollector.collect_sources(). ) annotationsN)IterableMutableMappingSequence) dataclass) HTMLParser)Values)Callable NamedTupleProtocol)requests)Response) RetryErrorSSLError)NetworkConnectionError)Link) SearchScope) PipSession)raise_for_status)is_archive_fileredact_auth_from_url) url_to_path)vcs)CandidatesFromPage LinkSource build_sourcectjD]6}|jj|s#|t |dvs4|cSy)zgLook for VCS schemes in the URL. Returns the matched VCS scheme, or None if there's no match. z+:N)rschemeslower startswithlen)urlschemes L/opt/hc_python/lib/python3.12/site-packages/pip/_internal/index/collector.py_match_vcs_schemer'.s@ ++ 99; ! !& )c#f+.>$.FM c eZdZdfd ZxZS)_NotAPIContentcBt|||||_||_yN)super__init__ content_type request_desc)selfr/r0 __class__s r&r.z_NotAPIContent.__init__:s" |4((r()r/strr0r3returnNone)__name__ __module__ __qualname__r. __classcell__r2s@r&r*r*9s ))r(r*c|jjdd}|j}|jdryt ||j j )z Check the Content-Type header to ensure the response contains a Simple API Response. Raises `_NotAPIContent` if the content type is not a valid content-type. Content-TypeUnknown)z text/htmlz#application/vnd.pypi.simple.v1+html#application/vnd.pypi.simple.v1+jsonN)headersgetr!r"r*requestmethod)responser/content_type_ls r&_ensure_api_headerrE@s[##'' BL!'')N     x'7'7'>'> ??r(c eZdZy)_NotHTTPN)r6r7r8r(r&rGrGVsr(rGctjj|\}}}}}|dvr t|j |d}t |t |y)z Send a HEAD request to the URL, and ensure the response contains a simple API Response. Raises `_NotHTTP` if the URL is not available for a HEAD request, or `_NotAPIContent` if the content type is not a valid content type. >httphttpsT)allow_redirectsN)urllibparseurlsplitrGheadrrE)r$sessionr%netlocpathqueryfragmentresps r&_ensure_api_responserWZsV-3LL,A,A#,F)FFD% &&j <<T< 2DTtr(ctt|jr t||tj dt ||j|djgddd}t|t|tj dt ||jjd d |S) aYAccess an Simple API response with GET, and return the response. This consists of three parts: 1. If the URL looks suspiciously like an archive, send a HEAD first to check the Content-Type is HTML or Simple API, to avoid downloading a large file. Raise `_NotHTTP` if the content type cannot be determined, or `_NotAPIContent` if it is not HTML or a Simple API. 2. Actually perform the request. Raise HTTP exceptions on network failures. 3. Check the Content-Type header to make sure we got a Simple API response, and raise `_NotAPIContent` otherwise. rQzGetting page %sz, )r>z*application/vnd.pypi.simple.v1+html; q=0.1ztext/html; q=0.01z max-age=0)Acceptz Cache-Control)r?zFetched page %s as %sr<r=) rrfilenamerWloggerdebugrr@joinrrEr?)r$rQrVs r&_get_simple_responser_lstCy))*S'2 LL"$8$=> ;; ii()+   D4Tt LLS! 3 Kr(c|rHd|vrDtjj}|d|d<|jd}|r t |Sy)z=Determine if we have any encoding information in our headers.r<z content-typecharsetN)emailmessageMessage get_paramr3)r?mras r&_get_encoding_from_headersrgsK>W, MM ! ! ##N3.++i( w<  r(c$eZdZddZddZddZy)CacheablePageContentc.|jsJ||_yr,)cache_link_parsingpager1rls r&r.zCacheablePageContent.__init__s&&&& r(ct|t|xr-|jj|jjk(Sr,) isinstancetyperlr$)r1others r&__eq__zCacheablePageContent.__eq__s-%d,P%**..1PPr(c@t|jjSr,)hashrlr$r1s r&__hash__zCacheablePageContent.__hash__sDIIMM""r(N)rl IndexContentr4r5)rqobjectr4bool)r4int)r6r7r8r.rrrvrHr(r&ririsQ#r(riceZdZddZy) ParseLinkscyr,rHrms r&__call__zParseLinks.__call__scr(Nrlrwr4zIterable[Link])r6r7r8r~rHr(r&r|r|sAr(r|cztjdfd tjdfd }|S)z Given a function that parses an Iterable[Link] from an IndexContent, cache the function's result (keyed by CacheablePageContent), unless the IndexContent `page` has `page.cache_link_parsing == False`. c:t|jSr,)listrl)cacheable_pagefns r&wrapperz*with_cached_index_content..wrappersB~**+,,r(c`|jrt|St|Sr,)rkrir)rlrrs r&wrapper_wrapperz2with_cached_index_content..wrapper_wrappers+  " "/56 6BtH~r()rrir4 list[Link])rlrwr4r) functoolscachewraps)rrrs` @r&with_cached_index_contentrs@__--__R r(rwc#TK|jj}|jdr^tj|j }|j dgD])}tj||j}|&|+yt|j}|jxsd}|j|j j||j}|jxs|}|jD]!} tj | ||}||#yw)z\ Parse a Simple API's Index Content, and yield its anchor elements as Link objects. r>filesNzutf-8)page_urlbase_url)r/r!r"jsonloadscontentr@r from_jsonr$HTMLLinkParserencodingfeeddecoderanchors from_element) rlrDdatafilelinkparserrr$ranchors r& parse_linksrs &&,,.N  !FGzz$,,'HHWb)D>>$1D|J *  DHH %F}}'H KK ##H-. ((C%#H..  #I <  !sD&D(T)frozencPeZdZUdZded<ded<ded<ded<d Zd ed <dd Zy )rwaRepresents one response (or page), along with its URL. :param encoding: the encoding to decode the given content. :param url: the URL from which the HTML was downloaded. :param cache_link_parsing: whether links parsed from this page's url should be cached. PyPI index urls should have this set to False, for example. bytesrr3r/ str | Nonerr$Tryrkc,t|jSr,)rr$rus r&__str__zIndexContent.__str__s#DHH--r(N)r4r3)r6r7r8__doc____annotations__rkrrHr(r&rwrws/N H##.r(c4eZdZdZdfd ZddZddZxZS)rzf HTMLParser that keeps the first base HREF and a list of all anchor elements' attributes. cPt|d||_d|_g|_y)NT)convert_charrefs)r-r.r$rr)r1r$r2s r&r.zHTMLLinkParser.__init__s( $/$( 46 r(c|dk(r(|j|j|}|||_yy|dk(r%|jjt |yy)Nbasea)rget_hrefrappenddict)r1tagattrshrefs r&handle_starttagzHTMLLinkParser.handle_starttagsT &=T]]2=='D $  CZ LL  U ,r(c*|D]\}}|dk(s |cSy)NrrH)r1rnamevalues r&rzHTMLLinkParser.get_href!s! KD%v~ !r()r$r3r4r5)rr3rlist[tuple[str, str | None]]r4r5)rrr4r)r6r7r8rr.rrr9r:s@r&rr s 7-r(rc<|tj}|d||y)Nz%Could not fetch URL %s: %s - skipping)r\r])rreasonmeths r&_handle_get_simple_failr(s  ||| 0$?r(ct|j}t|j|jd||j|S)Nr<)rr$rk)rgr?rwrr$)rCrkrs r&_make_index_contentr2sE*(*:*:;H ( LL-  r(c$|jjddd}t|}|rtj d||y|j drtt jjt|rL|jds|dz }tjj|d}tjd| t|| }t!||j" S#t$$rtj d |Yyt&$r6}tj d ||j(|j*Yd}~yd}~wt,$r}t/||Yd}~yd}~wt0$r}t/||Yd}~yd}~wt2$r6}d }|t5|z }t/||tj6Yd}~yd}~wt8j:$r}t/|d|Yd}~yd}~wt8j<$rt/|dYywxYw)N#rrzICannot look at %s URL %s because it does not support lookup as web pages.zfile:/z index.htmlz# file: URL is directory, getting %srY)rkz`Skipping page %s because it looks like an archive, and cannot be checked by a HTTP HEAD request.zSkipping page %s because the %s request got Content-Type: %s. The only supported Content-Types are application/vnd.pypi.simple.v1+json, application/vnd.pypi.simple.v1+html, and text/htmlz4There was a problem confirming the ssl certificate: )rzconnection error: z timed out)r$splitr'r\warningr"osrSisdirrendswithrMrNurljoinr]r_rrkrGr*r0r/rrrrr3infor ConnectionErrorTimeout)rrQr$ vcs_schemerVexcrs r&_get_index_contentr?s ((..a  #C#3'J W    ~~g277==S1A#B||C 3JC ll""3 5 :C@U#C9:#4Dz'LinkCollector.create..sIjs-c2js)rrno_index)rQr) index_urlextra_index_urlsrr\r]r^rrcreater)clsrQoptionssuppress_no_indexrrrlink_collectors r&rzLinkCollector.creates''(7+C+CC   $5 LL&IjII J''-2 "))!!%% '% r(c.|jjSr,)rrrus r&rzLinkCollector.find_linkss  +++r(c0t||jS)z> Fetch an HTML page containing package links. rY)rrQ)r1locations r&fetch_responsezLinkCollector.fetch_responses"(DLLAAr(ctjfdjjDj }tjfdj Dj }t jtjrwtj||Dcgc]}||jd|j!}}t|ddg|z}t jdj|t!t#|t#|Scc}w)Nc 3hK|])}t|jjdd+yw)Fcandidates_from_pagepage_validator expand_dirrk project_nameNrrQis_secure_originrlocrrr1s r&rz0LinkCollector.collect_sources..sE 4 P %9#||<< #()   P/2c 3hK|])}t|jjdd+yw)TrNrrs r&rz0LinkCollector.collect_sources..sC 5 ' %9#||<<#')   'rz* z' location(s) to search for versions of : )rr) collections OrderedDictrget_index_urls_locationsvaluesrr\ isEnabledForloggingDEBUG itertoolschainrr#r]r^rr)r1rrindex_url_sourcesfind_links_sourcessliness``` r&collect_sourceszLinkCollector.collect_sourcess5 (33 4 ((AA,O 4   &( )44 5  5   &(    w}} -#);=NOOA=QVV%7QVVH O  u:,##/.3E LL5) *./-.  s>$D<N)rQrrrr4r5)F)rQrrr rryr4r)r4z list[str])rrr4IndexContent | None)rr3rrr4r) r6r7r8rr. classmethodrpropertyrrrrHr(r&rrs"   #(    B,,B , , 1,   , r(r)r$r3r4r)rCrr4r5)r$r3rQrr4r5)r$r3rQrr4r)r?ResponseHeadersr4r)rr|r4r|rr,)rrrzstr | ExceptionrzCallable[..., None] | Noner4r5)T)rCrrkryr4rw)rrrQrr4r)Pr __future__rr email.messagerbrrrrr urllib.parserMcollections.abcrrr dataclassesr html.parserroptparser typingr r r pip._vendorr pip._vendor.requestsrpip._vendor.requests.exceptionsrrpip._internal.exceptionsrpip._internal.models.linkr!pip._internal.models.search_scoperpip._internal.network.sessionrpip._internal.network.utilsrpip._internal.utils.filetypesrpip._internal.utils.miscrpip._internal.utils.urlsrpip._internal.vcsrsourcesrrr getLoggerr6r\r3rr' Exceptionr*rErGrWr_rgrir|rrrwrrrrrrrHr(r&r s#  >>!" !)@;*948990!AA   8 $ c*)Y)@, y $<~ # #BB(8 $...(Z>(,@ @ @ %@ @48  ,0  9x,z, h h r(PK!1%mm)__pycache__/package_finder.cpython-39.pycnu[PK!>k>>"?n__pycache__/sources.cpython-39.pycnu[PK!Srl  #ϊ__pycache__/__init__.cpython-39.pycnu[PK!/>/>$+__pycache__/collector.cpython-39.pycnu[PK!+ sources.pynu[PK!I~D~D collector.pynu[PK!C?K ?)__init__.pynu[PK!W)package_finder.pynu[PK!9  $ѷ__pycache__/__init__.cpython-311.pycnu[PK!{ `n44*2__pycache__/package_finder.cpython-311.pycnu[PK!FX5X5#r__pycache__/sources.cpython-311.pycnu[PK!#]]%k__pycache__/collector.cpython-311.pycnu[PK!L))*__pycache__/package_finder.cpython-312.pycnu[PK!?R"$J__pycache__/__init__.cpython-312.pycnu[PK!Ȏug//#o__pycache__/sources.cpython-312.pycnu[PK! LRLR%__pycache__/collector.cpython-312.pycnu[PKb5