ファイルの検索と選択(indexPackageFinder

pipのpip._internal.indexサブパッケージは、プロジェクトの要件に基づいて、ダウンロードするファイルとその場所を決定する役割を担っています。このパッケージの機能は、主にパッケージのPackageFinderクラスを通じて公開され、調整されます。

概要

パッケージの要件に基づいて、pipがダウンロードするファイルを選択するために使用するプロセスの大まかな説明を以下に示します。

  1. プロジェクトパッケージファイルを含むさまざまなネットワークおよびファイルシステムの場所を収集します。これらの場所は、たとえば、pipの--index-url(デフォルトはhttps://pypi.org/simple/)設定、および構成された--extra-index-urlの場所から派生します。各プロジェクトページのURLは、PEP 503の「Simple Repository API」で定義されているように、アンカーリンクのHTMLページです。

  2. 各プロジェクトページのURLについて、HTMLをフェッチし、アンカーリンクを解析して、それぞれからLinkオブジェクトを作成します。LinkCollectorクラスは、前のステップとネットワーク経由でのHTMLのフェッチの両方を担当します。

  3. どのリンクが最小限に関連しているかをLinkEvaluatorクラスを使用して判断します。これらの関連するリンクごとにInstallationCandidateオブジェクト(インストール候補とも呼ばれる)を作成します。

  4. InstallationCandidateオブジェクトのコレクションを(CandidateEvaluatorクラスを使用して)さらにフィルタリングして、「適用可能な」候補のコレクションにします。

  5. 適用可能な候補がある場合は、それらをソートすることにより最適な候補を選択します(これもCandidateEvaluatorクラスを使用)。

このセクションの残りの部分は、indexパッケージ内のクラスを次の順序でドキュメント化することによって構成されています。

PackageFinderクラス

PackageFinderクラスは、pipのコードがindexパッケージと対話するための主要な方法です。これは、さまざまなパッケージ検索機能をカプセル化およびグループ化する包括的なクラスです。

PackageFinderクラスは、ネットワークとファイルシステムを検索して、pipがインストールできるパッケージのバージョンを検索し、ユーザーの好みや対象のPython環境などに基づいて、どのバージョンが最も優先されるかを決定する役割も担っています。

PackageFinderクラスを使用するpipコマンドは次のとおりです。

PackageFinderクラスの使用を必要とするpipコマンドは、通常、pipの呼び出し全体でPackageFinderを1回だけインスタンス化します。実際、pipはこのPackageFinderインスタンスを、コマンドオプションが最初に解析されたときに作成します。

pip listを除いて、上記の各コマンドはRequirementCommandから継承するCommandクラスとして実装されています(たとえば、pip downloadDownloadCommandによって実装されています)。そして、PackageFinderインスタンスはRequirementCommandクラスの_build_package_finder()メソッドを呼び出すことによって作成されます。一方、pip listは、ListCommandクラスの_build_package_finder()を呼び出すことによって、PackageFinderインスタンスを構築します。(この違いは単に歴史的なものであり、実際には必ずしも必要ではない可能性があります。)

これらの各コマンドは、pipの「自己チェック」(つまり、pipのアップグレードが利用可能かどうかを確認するため)にもPackageFinderクラスを使用します。この場合、PackageFinderインスタンスはself_outdated_check.pyモジュールのpip_self_version_check()関数によって作成されます。

PackageFinderクラスは、概要セクションにリストされているすべての操作(PEP 503のシンプルリポジトリHTMLページのフェッチと解析、シンプルリポジトリページのどのリンクが各要件に関連しているかの評価、関連するリンクから来るインストールの候補をさらにフィルタリングして優先順位付けする)を行う役割を担っています。

PackageFinderのメインのトップレベルメソッドの1つは、find_best_candidate()です。このメソッドは、次の2つのことを行います。

  1. ユーザーが提供したインデックスURLと場所を読み取って解析することによって、可能なすべてのパッケージリンクを収集するfind_all_candidates()メソッドを呼び出し(LinkCollectorクラスのcollect_sources()メソッド)、それらのリンクの一部をフィルタリングするLinkEvaluatorオブジェクトを構築し、InstallationCandidates(インストール候補とも呼ばれる)のリストを返します。これは、上記の概要のステップ1〜3に対応します。

  2. CandidateEvaluatorオブジェクトを構築し、それを使用して最適な候補を決定します。これは、find_all_candidates()の戻り値に対してCandidateEvaluatorクラスのcompute_best_candidate()メソッドを呼び出すことによって行います。これは、概要のステップ4〜5に対応します。

PackageFinderには、PEP 503の「シンプルリポジトリ」プロジェクトページを処理するためのprocess_project_url()メソッド(find_best_candidate()によって呼び出される)もあります。このメソッドは、PEP 503プロジェクトページのURLからHTMLをフェッチして解析し、アンカー要素を抽出してそれらからLinkオブジェクトを作成し、それらのリンクを評価します。

LinkCollectorクラス

LinkCollectorクラスは、ファイルシステムの位置からのパッケージファイルへの「リンク」(Linkオブジェクトとして表される)の生のリストと、PackageFinderがアクセスする必要があるPEP 503プロジェクトページのURLを収集する役割を担うクラスです。

LinkCollector クラスは、リンクを収集する場所を決定する際に、ユーザーの --find-links--extra-index-url、および関連オプションを考慮します。このクラスの主なメソッドは、collect_sources() メソッドです。PackageFinder クラスは、その find_all_candidates() メソッドの最初のステップとして、このメソッドを呼び出します。

LinkCollector は、プロジェクトページの URL から HTML を取得するための fetch_page() メソッドも持っています。このメソッドは HTML を解析しないという点で「非インテリジェント」です。

LinkCollector クラスは、index サブパッケージ内でネットワークリクエストを行う唯一のクラスであり、リクエストを行うための pip の設定オプションと状態を格納する PipSession に直接依存する唯一のクラスです。

LinkEvaluator クラス

LinkEvaluator クラスには、リンク(たとえば、シンプルなリポジトリページ内)がインストール候補となるための最低限の条件を満たしているかどうかを判断するビジネスロジックが含まれています(結果として InstallationCandidate オブジェクトが生成されます)。この決定を行う際、LinkEvaluator インスタンスは、ターゲットの Python インタープリターや、バイナリファイルが許可されているか優先されているかなどのユーザー設定などの情報を使用します。

具体的には、LinkEvaluator クラスには、リンクがインストールの候補であるかどうかを返す evaluate_link() メソッドがあります。

このクラスのインスタンスは、PackageFinder クラスの make_link_evaluator() によって要件ごとに作成されます。

CandidateEvaluator クラス

CandidateEvaluator クラスには、どの InstallationCandidate オブジェクトを優先すべきかを評価するビジネスロジックが含まれています。これは、LinkEvaluator クラスによって実行されるものよりもきめ細かい判断と見なすことができます。

特に、CandidateEvaluator クラスは、LinkEvaluator が行うように各候補を個別に評価するのではなく、決定を行う際に InstallationCandidate オブジェクトの全体セットを使用します。たとえば、プレリリース版が選択の対象となるかどうか、またはハッシュが一致しないファイルが対象となるかどうかは、コレクション全体のプロパティに依存します。

CandidateEvaluator クラスは、ターゲットの Python インタープリターと互換性のあるプラットフォームタグのリスト、ユーザーが提供したハッシュ、その他のユーザー設定などの情報を使用します。

具体的には、クラスには get_applicable_candidates() メソッドがあります。これは、LinkEvaluator クラスの evaluate_link() メソッドによって受け入れられたリンクから生じた InstallationCandidate オブジェクトを受け入れ、「適用可能な」候補のリストにフィルタリングし、優先順位で並べ替えます。

CandidateEvaluator クラスには、最適な(つまり、最も優先度の高い)候補を返す sort_best_candidate() メソッドもあります。

最後に、クラスには get_applicable_candidates() を呼び出した後、sort_best_candidate() を呼び出し、決定の中間結果と最終結果の両方をカプセル化する BestCandidateResult オブジェクトを返す compute_best_candidate() メソッドがあります。

CandidateEvaluator のインスタンスは、PackageFinder クラスの make_candidate_evaluator() メソッドによって要件ごとに作成されます。

CandidatePreferences クラス

CandidatePreferences クラスは、PackageFinderCandidateEvaluator オブジェクトを構築する際に使用するユーザー設定の一部(PackageFinder クラスの make_candidate_evaluator() メソッドを介して)をまとめるシンプルなコンテナクラスです。

PackageFinder インスタンスには、値が CandidatePreferences インスタンスである _candidate_prefs 属性があります。PackageFinder には、その動作を制御する多くの責任とオプションがあるため、CandidateEvaluator に固有の設定をグループ化すると、メンテナーは CandidateEvaluator にのみ必要な属性を知ることができます。

BestCandidateResult クラス

BestCandidateResult クラスは、要件に最適な候補を見つける結果をカプセル化する便利な「コンテナ」クラスです。(「コンテナ」とは、単にデータを含み、独自のビジネスロジックや状態変化メソッドを持たないオブジェクトを意味します。)最終結果だけでなく、結果を決定するために使用された中間値も格納します。

このクラスは、CandidateEvaluator クラスの compute_best_candidate() メソッドと PackageFinder クラスの find_best_candidate() メソッドの両方の戻り値の型です。