Python のプロジェクトマネージャー pdm の紹介

# はじめに

この資料は、pdm の公式ドキュメントをもとに紹介するものです。
誤訳や解釈の間違いが含まれている可能性があることに注意してください。
これから利用する方々の助けになれば幸いです。

# pdm について

[pdm](https://github.com/pdm-project/pdm) は、最新のPEP標準をサポートする最新のPythonパッケージです。依存関係の管理や解決など、開発ワークフローを後押ししてくれます。最大の利点利点は、virtualenvを作成する必要が全くないnpmと同様の方法でパッケージをインストールし管理できることで、プロジェクトが消費するディスクスペースが少なくなります。

# 特徴

- 大規模なバイナリ配布のための，シンプルで高速な依存性解決ツール
- [PEP 517](https://www.python.org/dev/peps/pep-0517) ビルドバックエンド
- [PEP 621](https://www.python.org/dev/peps/pep-0621) のプロジェクトメタデータ
- 柔軟で強力なプラグインシステム
- 多彩なユーザースクリプト
- pnpmのような集中型インストールキャッシュをオプションで提供

# 類似プロジェクトとの比較

### [Pipenv](https://pipenv.pypa.io/)

Pipenvは、その名の通りpipとvenvを組み合わせた依存関係管理ツールです。非標準の `Pipfile.lock` や `Pipfile` からパッケージをインストールすることができます。ただし、Pipenvは開発しているコードのパッケージングに関連するパッケージは扱わないので、インストールできないアプリケーション（例えばDjangoサイト）を開発する場合にのみ有用です。ライブラリ開発者であれば、いずれにせよ setuptools は必要です。

### [Poetry](https://python-poetry.org/)

PoetryはPipenvと同様に環境と依存関係を管理しますが、開発しているコードで`.whl`ファイルをビルドしたり、Wheelやソース配布物をPyPIにアップロードしたりすることができます。きれいなユーザーインターフェイスを持ち、ユーザーはプラグインでカスタマイズすることができます。

Poetryは`pyproject.toml`標準を使用しますが、`pyproject.toml` ファイルでメタデータをどのように表現すべきかを指定する標準（[PEP 621](https://www.python.org/dev/peps/pep-0621)）には従わず、カスタムの `[tool.poetry]` テーブルを使用しています。これは、PoetryがPEP621より前に登場したことも理由のひとつです。

### [Hatch](https://hatch.pypa.io/)

Hatchは環境の管理もできますし（プロジェクトごとに複数の環境を置くことができますが、プロジェクトディレクトリに置くことはできません）、パッケージの管理もできます（ただしロックファイルはサポートされていません）。HatchはプロジェクトをPEP 621に準拠した `pyproject.toml` ファイルを用いてパッケージ化し、PyPIにアップロードするためにも使うことができます。

### PDM

PDMは、Pipenvと同様に、プロジェクトと中央の両方の場所で仮想環境(venv)を管理できます。標準化された `pyproject.toml` ファイルからプロジェクトのメタデータを読み込み、`lockfiles` をサポートします。ユーザーはプラグインによって機能を追加することができ、プラグインを配布物としてアップロードすることで共有することができます。

PoetryやHatchとは異なり、PDMは特定のビルドバックエンドに制限されることはなく、ユーザーは好きなビルドバックエンドを自由に選択することができます。

# インストール

pdm は Python 3.7 以上が必要です。

- Linux / macOS
    
    ```bash
    % URL=https://raw.githubusercontent.com/pdm-project/pdm/main/install-pdm.py
    % curl -sSL $URL | python3 -
    ```
    
    `$HOME/.local/bin` にインストールされます。
    
- Windows
    
    ```powershell
    $ (Invoke-WebRequest -Uri https://raw.githubusercontent.com/pdm-project/pdm/main/install-pdm.py -UseBasicParsing).Content | python -
    ```
    
    • `%APPDATA%\Python\Scripts` にインストールされます。
    

デフォルトのインストール先を変更したい場合は、オプションや環境変数で指示できます。

```powershell
usage: install-pdm.py [-h] [-v VERSION] [--prerelease] [--remove] [-p PATH] [-d DEP]

optional arguments:
  -h, --help            show this help message and exit
  -v VERSION, --version VERSION | envvar: PDM_VERSION
                        Specify the version to be installed, or HEAD to install from the main branch
  --prerelease | envvar: PDM_PRERELEASE    Allow prereleases to be installed
  --remove | envvar: PDM_REMOVE            Remove the PDM installation
  -p PATH, --path PATH | envvar: PDM_HOME  Specify the location to install PDM
  -d DEP, --dep DEP | envvar: PDM_DEPS     Specify additional dependencies, can be given multiple times
```

Linux / macOS でインストール先を `$HOME/.pdm` に変更する場合の例：

```bash
% URL=https://raw.githubusercontent.com/pdm-project/pdm/main/install-pdm.py
% curl -sSL $URL | env PDM_HOME=$HOME/.pdm python3 -
```

インストールした `$PDM_HOME/bin` をシェルの設定ファイルに追記しておきます。

## pdm のアップデート

pdm のアップデートは次のようにコマンドを実行します。

```
% pdm self update
```

# 使用方法

```bash
pdm [OPTIONS] <COMMAND>
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-V` , `—-version` 
バージョン情報を表示する
- `-c CONFIG` , `--config CONFIG`
別のコンフィグファイルのパスを指定する
環境変数： `PDM_CONFIG_FILE`
- `-v` , `--verbose` 
詳細な出力には -`v` を、より詳細な出力には -`vvv` を使用する。
- `-I` , `--ignore-python` 
`.pdm-python` に保存されている Python パスを無視する
環境変数： `PDM_IGNORE_SAVED_PYTHON`
- `--pep582 [SHELL]` 
`SHELL`で評価されるコマンドラインを出力する

**コマンド**

- `add` 
`pyproject.toml` にパッケージを追加し、インストールする
- `build` 
配布用のアーティファクトをビルドする
- `cache` 
PDMのキャッシュを制御する
- `completion` 
与えられたシェルの補完スクリプトを生成する
- `config` 
現在のコンフィギュレーションを表示する
- `export` 
ロックされたパッケージを他の形式にエクスポートします。
- `fix` 
プロジェクトの問題をPDMの最新版に従って修正する。
- `import` 
他のフォーマットからプロジェクトのメタデータをインポートする
- `info` 
プロジェクト情報を表示する
- `init` 
PDM用の `pyproject.tom`l を初期化する。
- `install` 
ロックファイルから依存関係をインストールする
- `list` 
現在の作業セットにインストールされているパッケージの一覧を表示する
- `lock` 
依存関係を解決してロックする
- `publish` 
プロジェクトをビルドしてPyPIに公開する。
- `remove` 
`pyproject.toml` からパッケージを削除する。
- `run` 
ローカルパッケージがロードされた状態でコマンドやスクリプトを実行する
- `search` 
PyPI パッケージを検索する
- `self`
PDMプログラム自体を管理する（古いバージョンでは plugin )
- `show` 
パッケージ情報を表示する
- `sync` 
現在の作業セットとロックファイルを同期させる
- `update` 
`pyproject.toml` にあるパッケージを更新する
- `use` 
与えられたpythonのバージョンまたはパスをベースとして使用する
- `venv` 
Virtualenvの管理

# 使用例

## プロジェクトの新規作成

まず始めに、`pdm init`で新しいプロジェクトを作成します。

```bash
% mkdir pdm_demo && cd pdm_demo
% pdm init
```

### Pythonインタプリタの選択

pdm init を実行すると、マシンにインストールされているPythonのバージョンをリストアップします。このリストから、Pythonインタプリタを選択する必要があります。
選択したPythonのパスは `.pdm-python` に保存され、以降のコマンドで使用されます。また、後でpdm useで変更することも可能です。

また、環境変数 `PDM_PYTHON` でPythonのインタープリタパスを指定することもできます。この変数が設定されている場合、`.pdm-python` に保存されているパスは無視されます。

### 仮想環境を作成

Pythonインタプリタを選択すると、PDMはプロジェクトに仮想環境（Virtualenv）を作成するかどうかを尋ねます。ここで、 yes (`y`) を選択すると、PDMはプロジェクトのルートディレクトリに仮想環境を作成し、それをプロジェクトのPythonインタプリタとして使用します。

選択したPythonインタプリタが仮想環境にある場合、PDMはそれをプロジェクトの環境として使用し、依存関係をその環境にインストールします。そうでない場合は，プロジェクトルートに`__pypackages__`が作成され，そこに依存関係がインストールされます．

この2つのアプローチの違いについては、docsの対応するセクションを参照してください：

- Virtualenv
- pypackages__(PEP58)

### プロジェクトのタイプを選択

ライブラリとアプリケーションは、多くの点で異なります。ライブラリは他のプロジェクトにインストールされて使われることを目的としたパッケージです。ほとんどの場合、PyPIへのアップロードも必要です。一方、アプリケーションはエンドユーザーと直接向き合うものであり、いくつかの本番環境にデプロイする必要がある場合もあります。

PDMでは、ライブラリを作成することを選択すると、PDMは `pyproject.toml` ファイルに 名前(`name`)、バージョン(`version`) フィールドを追加し、さらにビルドバックエンド用の `[build-system]` テーブルを追加しますが、これはプロジェクトをビルドして配布する必要がある場合にのみ有用です。そのため、プロジェクトをアプリケーションからライブラリに変更したい場合は、これらのフィールドを手動で `pyproject.toml` に追加する必要があります。また、`--no-self` が指定されていない限り、`pdm install` や `pdm sync` を実行すると、ライブラリプロジェクトが環境にインストールされます。

### require-python の値を設定

プロジェクトに適切な `requires-python` の値を設定する必要があります。これは、依存関係の解決方法に影響する重要なプロパティです。基本的に、各パッケージの `requires-python` は、プロジェクトの `requires-python` の範囲をカバーする必要があります。例えば、以下のような設定を考えてみましょう：

- プロジェクト： `requires-python = ">=3.9"`
- パッケージ foo ： `requires-python = ">=3.7,<3.11"`

依存関係を解決すると、`ResolutionImpossible` が発生します：

```
Unable to find a resolution because the following dependencies don't work
on all Python versions defined by the project's `requires-python`
```

依存関係の `requires-python` が `>=3.7,<3.11` なので、プロジェクトの `requires-python` の範囲である `>=3.9` をカバーしていません。つまり、プロジェクトはPython3.11以上で動作することを約束しているのに、依存関係ではそれをサポートしていないことになります。PDMは `requires-python` の範囲内のすべてのPythonバージョンで動作するはずのクロスプラットフォームロックファイルを作成するので、有効な解決策を見つけることができません。

これを解決するには、`requires-python` に`>=3.9,<3.11`のように、最大バージョンを追加する必要があります。

`requires-python` の値は、[PEP 440](https://peps.python.org/pep-0440)で定義されているバージョン指定子です。以下はその例です：

| バージョン指定子 | マッチするバージョン |
| --- | --- |
| >=3.7 | Python 3.7 以上 |
| >=3.7,<3.11 | Python3.7 以上、Python 3.11 未満 |
| >=3.6,!=3.8.,!=3.9 | Python 3.6以上（3.8、3.9を除く） |

### Python < 3.7での作業

PDMはPython 3.7以上で動作しますが、作業プロジェクトにPythonの下位バージョンを使用することができます。しかし、もしあなたのプロジェクトがライブラリで、ビルド、公開、インストールが必要な場合、使用するPEP 517ビルドバックエンドが、あなたが必要とする最も低いPythonバージョンをサポートしていることを確認することを忘れないでください。例えば、デフォルトのバックエンドpdm-pep517はPython 3.7+でしか動作しないので、Python 3.6のプロジェクトでpdm buildを実行すると、エラーが発生します。最近のビルドバックエンドはPython 3.6以下のサポートを終了しているので、Pythonのバージョンを3.7+にアップグレードすることが強く推奨されます。以下は、よく使われるビルドバックエンドでサポートされているPythonの範囲です。PEP 621をサポートしているものだけをリストアップしていますが、それ以外のものはPDMで動作しないためです。

| ビルドバックエンド | サポートPython | PEP 621 のサポート |
| --- | --- | --- |
| pdm-pep517 | >=3.7 | Yes |
| setuptools>=60 | >=3.7 | 実験的 |
| hatchling | >=3.7 | Yes |
| flit-core>=3.4 | >=3.6 | Yes |
| flit-core>=3.2,<3.4 | >=3.6 | Yes |

なお、プロジェクトがアプリケーション（`name`メタデータなし）の場合は、上記のバックエンドの制限は適用されません。つまり、ビルドバックエンドは不要であり、Pythonのバージョンも2.7まで使用可能です。

### 他のパッケージマネージャからプロジェクトをインポート

PipenvやPoetryのような他のパッケージマネージャツールをすでに使っている場合、PDMへの移行は簡単です。PDMはimportコマンドを提供し、プロジェクトを手動で初期化する必要がありません：

- Pipenv の `Pipfile`
- `pyproject.toml` にある Poetryのセクション
- `pyproject.toml` にある Flitのセクション
- pipが使用する `requirements.txt` 形式
- setuptools の`setup.py`
プロジェクト環境にsetuptoolsがインストールされていることが必要
PDMでは、`venv.with_pip`を`true`に設定し、`__pypackages__`　にsetuptoolsを追加する

また、`pdm init` や `pdm install` を実行する際、PDMプロジェクトがまだ初期化されていない場合、PDMはインポート可能なファイルを自動検出することができます。

> 備考：
setup.pyを変換すると、プロジェクトのインタープリターで実行されます。setuptoolsがインタプリタと共にインストールされ、`setup.py` が信頼されていることを確認してください。
> 

### バージョン管理システム(VCS)での作業

`pyproject.toml` ファイルおよび、`pdm.lock` と `pdm.toml` ファイルはコミットする必要があります。`.pdm-python` ファイルはコミットしないでください。

`pyproject.toml` ファイルは、PDMに必要なプロジェクトのビルドメタデータと依存関係を含んでいるので、コミットする必要があります。また、他のpythonツールでも設定のためによく使われます。`pyproject.toml` ファイルについて詳しくは[Pipドキュメント](https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml/)を参照してください。

`pdm.lock` ファイルをコミットすることで、すべてのインストーラが同じバージョンの依存関係を使用していることを確認できます。依存関係を更新する方法については、既存の依存関係を更新するを参照してください。

`pdm.toml` ファイルにはプロジェクト全体の設定が含まれており、共有するためにコミットしておくと便利です。

`.pdm-python` ファイルには、現在のプロジェクトで使用されている Python のパスが格納されており、共有する必要はありません。

### Python実行環境の参照

```bash
$ pdm info
PDM version:
  2.0.0
Python Interpreter:
  /opt/homebrew/opt/python@3.9/bin/python3.9 (3.9)
Project Root:
  /Users/fming/wkspace/github/test-pdm
Project Packages:
  /Users/fming/wkspace/github/test-pdm/__pypackages__/3.9

# Show environment info
$ pdm info --env
{
  "implementation_name": "cpython",
  "implementation_version": "3.8.0",
  "os_name": "nt",
  "platform_machine": "AMD64",
  "platform_release": "10",
  "platform_system": "Windows",
  "platform_version": "10.0.18362",
  "python_full_version": "3.8.0",
  "platform_python_implementaiton": "CPython",
  "python_version": "3.8",
  "sys_platform": "win32"
}
```

`pdm info` コマンドは、プロジェクトでどのモードが使用されているかを確認するのに便利です：

- Project PackagesがNoneの場合、virtualenvモードが有効です。
- それ以外の場合は、PEP 582モードが有効です。

これで、新しいPDMプロジェクトがセットアップされ、`pyproject.toml`ファイルが作成されました。`pyproject.toml` ファイルの正しい書き方については、[メタデータ](https://qiita.com/iisaka51/items/f500da5968df355f4c8b#pep-621-%E3%83%A1%E3%82%BF%E3%83%87%E3%83%BC%E3%82%BF)のセクションを参照してください。

## 依存関係の管理

PDMは、プロジェクトと依存関係を管理するのに役立つ、たくさんのコマンドを提供しています。以下の例はUbuntu 18.04で実行されています。Windowsを使用している場合は、いくつかの変更を行う必要があります。

### 依存関係を追加する

`pdm add` の後には、1つまたは複数の依存関係を指定することができ、依存関係の指定はPEP 508で説明されています。

例を挙げます：

```bash
pdm add requests           # requests を追加
pdm add requests==2.25.1   # ferequests をバージョン指定子を記述して追加
pdm add requests[socks]    # requests の追加の依存関係を指定して追加
pdm add "flask>=1.0" flask-sqlalchemy   # 異なる指定子で複数の依存関係を追加
```

PDMでは、`-G` / `--group <name>` オプションを指定することで、追加の依存関係グループも使用できます。これらの依存関係は、それぞれプロジェクトファイルの `[project.optional-dependencies.<name>]` テーブルに移動します。

パッケージがアップロードされる前であっても、`optional-dependencies` で他のオプショングループを参照することができます：

```toml
[project]
name = "foo"
version = "0.1.0"

[project.optional-dependencies]
socks = ["pysocks"]
jwt = ["pyjwt"]
all = ["foo[socks,jwt]"]
```

その後、依存関係やサブ依存関係が適切に解決され、インストールされます。`pdm.lock` を見ると、すべての依存関係の解決結果を見ることができます。

### ローカルな依存関係

ローカルパッケージは、そのパスで追加することができます。パスはファイルまたはディレクトリです：

```bash
$ pdm add ./sub-package
$ pdm add ./first-1.0.0-py2.py3-none-any.whl
```

パスは.で始めなければなりません。そうでなければ、通常の名前付き要件として認識されます。ローカルな依存関係は、URL形式で `pyproject.toml` ファイルに書き込まれます：

```toml
[project]
dependencies = [
    "sub-package @ file:///${PROJECT_ROOT}/sub-package",
    "first @ file:///${PROJECT_ROOT}/first-1.0.0-py2.py3-none-any.whl",
]
```

### 他のバックエンドの設定

pdmバックエンド(`pdm-pep517`)の代わりに `hatchling` を使用している場合、URLは次のようになります：

```toml
sub-package @ {root:uri}/sub-package
first @ {root:uri}/first-1.0.0-py2.py3-none-any.whl
```

他のバックエンドは、URLの相対パスのエンコーディングをサポートしていないため、代わりに絶対パスを記述します。

### VCSの依存関係

gitリポジトリのurlや他のバージョン管理システムからインストールすることも可能です。

以下がサポートされています：

| VCS | コマンド | スキーム |
| --- | --- | --- |
| Git | git | git+https |
| Mercurial | hg | hg+https |
| Subversion | svn | svn+https |
| Bazaar | bzr | bzr+https |

URLは  `{vcs}+{url}@{rev}` のようになります。

例を挙げます：

```bash
#  pip リポジトリのタグ `22.0` をインストールする
pdm add "git+https://github.com/pypa/pip.git@22.0"

# URL認証情報を記述する
pdm add "git+https://username:password@github.com/username/private-repo.git@master"

# 依存関係に名前をつける
pdm add "pip @ git+https://github.com/pypa/pip.git@22.0"

# あるいは #egg フラグメントを使う
pdm add "git+https://github.com/pypa/pip.git@22.0#egg=pip"

# サブディレクトリからインストール
pdm add "git+https://github.com/owner/repo.git@master#egg=pkg&subdirectory=subpackage"
```

### URLから認証情報を隠す

`${ENV_VAR}` 変数構文を使用することで、URL内の認証情報を非表示にすることができます：

```toml
[project]
dependencies = [
  "mypackage @ git+http://${VCS_USER}:${VCS_PASSWD}@test.git.com/test/mypackage.git@master"
]
```

これらの変数は、プロジェクトのインストール時に環境変数から読み込まれます。

### 開発専用の依存関係を追加する

PDMでは、開発に役立つ依存関係のグループを定義することもできます。例えば、テスト用の依存関係やリント用の依存関係などです。通常、これらの依存関係をディストリビューションのメタデータに表示させたくないので、optional-dependenciesを使うのはおそらく良い考えではないでしょう。そこで、開発用の依存関係として定義することができます：

```bash
pdm add -dG test pytest
```

この結果、`pyproject.toml`は以下のようになります：

```toml
[tool.pdm.dev-dependencies]
test = ["pytest"]
```

開発のみの依存関係をいくつかのグループに分けて持つことができます。オプションの依存関係とは異なり、これらは `PKG-INFO` や `METADATA` のようなパッケージ配布のメタデータには表示されません。パッケージインデックスはこれらの依存関係を認識することはありません。スキーマは、tool.pdm テーブルにあることを除いて、オプション依存関係のものと似ています。

```toml
[tool.pdm.dev-dependencies]
lint = [
    "flake8",
    "black"
]
test = ["pytest", "pytest-cov"]
doc = ["mkdocs"]
```

後方互換性のため、`-d` または `--dev` オプションのみを指定した場合、依存関係はデフォルトで`[tool.pdm.dev-dependencies]`の `dev` グループへ移動します。

> **注意**：
同じグループ名を `[tool.pdm.dev-dependencies]` と `[project.optional-dependencies]` の両方に書いてはいけません 。
> 

### 編集可能な依存関係

ローカルディレクトリやVCSの依存関係を編集可能なモードでインストールすることができます。pip に慣れている人なら、`pip install -e <package>` と同じようなものです。編集可能なパッケージは、開発用の依存関係でのみ許可されています：

> **注意**：
編集可能なインストールは、dev 依存関係グループでのみ許可されています。デフォルトを含む他のグループでは、`[PdmUsageError]` が発生して失敗します。
> 

```bash
# ディレクトリへの相対パス
pdm add -e ./sub-package --dev
# ディレクトリへのURI
pdm add -e file:///path/to/sub-package --dev
# VCS への URL
pdm add -e git+https://github.com/pallets/click.git@main#egg=click --dev
```

### バージョン指定子を保存する

パッケージが `pdm add requests` のようにバージョン指定子なしで与えられる場合では、PDMはどのようなバージョン指定子を依存関係に保存するかについて、3つの異なる動作を提供し、それはオプション `—save-<strategy>`で与えられます。

`2.21.0`が依存関係に見つかる最新バージョンだと仮定して説明しましょう。

- `minimum` ： 最小バージョン指定子を保存する： `>=2.21.0` (デフォルト).
- `compatible`： 互換性バージョン指定子を保存する： `>=2.21.0,<3.0.0`
- `exact`： 正確なバージョン指定子を保存する：`==2.21.0`
- `wildcard`： バージョンを指定せず、ワイルドカードで指定します： `*`

### プレリリースの追加

`pdm add` で `--pre` / `--prerelease` オプションを指定すると、指定したパッケージに対して `prereleases` をピン留めすることができます。

### 既存の依存関係を更新する

ロックファイル内のすべての依存関係を更新します：

```bash
pdm update
```

指定されたパッケージをアップデートする

```bash
pdm update requests
```

指定されたパッケージをアップデートする

```bash
pdm update requests
```

複数の依存関係のグループを更新する

```bash
pdm update -G security -G http
```

または、カンマ区切りのリストを使用する

```bash
pdm update -G "security,http"
```

指定されたグループ内の指定されたパッケージを更新する

```bash
pdm update -G security cryptography
```

グループが与えられない場合、PDMはデフォルトの依存関係セットで要件を検索し、見つからない場合はエラーを発生させます。

開発依存関係でパッケージを更新する

```bash
# defult と dev の依存関係グループのすべてのパッケージを更新
pdm update -d
#dev 依存関係グループの特定のパッケージを更新
pdm update -dG test pytest
```

アップデート戦略について

同様に，PDMでは依存関係やサブ依存関係を更新する際に，`--update-<strategy>` オプションで3種類の動作を指定することができます．

- `reuse` (再利用)
コマンドラインで指定された以外のロックされた依存関係をすべて保持します。
これは、デフォルトの動作です。
- `eager` (積極的)
コマンドラインで指定されたパッケージとその再帰的なサブ依存関係をロックし，それ以外の依存関係をそのまま維持します．
- `all`
すべての依存関係と副依存関係を更新します。

### バージョン指定子を無視したバージョンにパッケージを更新する

`pdm update` にオプション `-u` / `--unconstrained` を与えると、`pyproject.toml` のバージョン指定を無視するようPDMに指示することができます。これは `yarn upgrade` コマンドの `-L` / `--latest` オプションと同じように動作します。さらに、`pdm update` は `——pre` / `——prerelease` オプションもサポートしています。

### 既存の依存関係を削除する

プロジェクトファイルとライブラリディレクトリから既存の依存関係を削除します：

```bash
# デフォルトの依存関係からリクエストを削除する
pdm remove requests
# オプションの依存関係グループ web から h11 を削除する 
pdm remove -G web h11
＃開発依存関係グループの test グループから pytest-cov を削除する
pdm remove -dG test pytest-cov
```

### ロックファイルに固定されたパッケージをインストールする

この仕事をするための類似のコマンドがいくつかありますが、若干の違いがあります：

- `pdm sync` はロックファイルからパッケージをインストールします。
- `pdm update` はロックファイルを更新し、その後同期します。
- `pdm install` は、プロジェクトファイルの変更をチェックし、必要であればロックファイルを更新し、その後同期を行います。

`pdm sync` には、インストールされたパッケージを管理するためのオプションもいくつかあります：

- `——clean`： ロックファイルにないパッケージを削除します。
- `--only-keep`： `-G` や `—prod` などのオプションで選択されたパッケージだけが保持されます。

### 使用するロックファイルを指定する

オプション `-L` / `--lockfile` `<filepath>` または 環境変数 `PDM_LOCKFILE` を使用すると、デフォルトの `pdm.lock` とは別のロックファイルを指定することができます。

### インストールまたはロックする依存関係グループのサブセットを選択する

次のような依存関係を持つプロジェクトがあるとします：

```toml
[project]  # プロダクションの依存関係
dependencies = ["requests"]

[project.optional-dependencies]  # オプションの依存関係
extra1 = ["flask"]
extra2 = ["django"]

[tool.pdm.dev-dependencies]  # dev 依存関係
dev1 = ["pytest"]
dev2 = ["mkdocs"]
```

| コマンド | 動作内容 | 備考 |
| --- | --- | --- |
| pdm install | 依存関係グループ prod と dev をインストール
オプションの依存関係グループは対象外 |  |
| pdm install -G extra1 | 依存関係グループ prod と dev と、オプションの依存関係グループ extra1 をインストール |  |
| pdm install -G dev1 | 依存関係グループ prod と dev の dev1 パッケージだけをインストール |  |
| pdm install -G:all | 依存関係グループ prod と dev、およびオプションの依存関係グループ extra1 と extra2 をインストール |  |
| pdm install -G extra1 -G dev1 | 依存関係グループ prod と オプションの依存関係グループの extra1 および、dev 依存関係グループの dev1 パッケージだけをインストール |  |
| pdm install --prod | 依存関係グループ prod だけをインストール |  |
| pdm install --prod -G extra1 | 依存関係グループ prod とオプションの依存関係グループ extra1 をインストール |  |
| pdm install --prod -G dev1 | 失敗する
--prod は dev 依存関係グループをインストールできない | --prod オプションを指定しなければOK |

また、`--prod` を指定せず、`-G` で開発グループを指定しない限り、すべての開発依存パッケージが含まれます。

また、ルートプロジェクトをインストールしたくない場合は `--no-self` オプションを、すべてのパッケージを編集できないバージョンでインストールしたい場合は `--no-editable` を使用することができます`no-editable` をオンにすると、`__pypackages__` 全体を安全にアーカイブして、ターゲット環境にコピーしてデプロイすることができます。

また、これらのオプションを指定して `pdm lock` コマンドを使用すると、指定したグループのみをロックすることができ、ロックファイルの `[metadata]` テーブルに記録されます。

`—group` / `--prod` / `--dev` / `--no-default` オプションを指定しない場合、`pdm sync` と `pdm update` はロックファイル内のグループを使って動作します。しかし、ロックファイルに含まれていないグループがコマンドの引数として与えられた場合、PDMはエラーを発生させます。

この機能は、複数のロックファイルを管理する場合に特に有効で、それぞれのロックファイルには同じパッケージの異なるバージョンが固定されていることがあります。ロックファイルを切り替えるには、`-L`  /  `--lockfile`オプションを使用することができます。

現実的な例として、あなたのプロジェクトがリリース版の werkzeug に依存しており、開発時にローカルの開発中コピーで作業したい場合があります。`pyproject.toml` に以下を追加することができます：

```toml
[project]
requires-python = ">=3.7"
dependencies = ["werkzeug"]

[tool.pdm.dev-dependencies]
dev = ["werkzeug @ file:///${PROJECT_ROOT}/dev/werkzeug"]
```

次に、`pdm lock` を異なるオプションで実行し、異なる目的のロックファイルを生成します：

```bash
# default + devをロックし、
# werkzeugのローカルコピーを固定された状態でpdm.lockに書き込み
pdm lock

# デフォルトをロックし、
# リリース版の werkzeug が固定された pdm.prod.lock に書き込む
pdm lock --prod -L pdm.prod.lock
```

ロックファイル `metadata.groups` フィールドで、どのグループが含まれるかを確認できます。

### クロスプラットフォーム・ロックファイル

デフォルトでは、生成されるロックファイルはクロスプラットフォームで、依存関係を解決するときに現在のプラットフォームが考慮されないことを意味します。つまり、依存関係を解決する際に現在のプラットフォームは考慮されないということです。しかし、リリースにすべてのホイールが含まれていない場合、間違ったロックファイルになってしまうことがあります。これを避けるために、PDMに、現在のプラットフォームに関係ないWheelを捨てて、このプラットフォームだけで動作するロックファイルを作成するように指示することができます。これは `pdm lock` に `--no-cross-platform` オプションを渡すことで可能です：

```bash
pdm lock --no-cross-platform
```

### どのようなパッケージがインストールされているかを表示する

`pip list` と同様に、packages ディレクトリにインストールされているすべてのパッケージを一覧表示することができます：

```bash
pdm list
```

また、依存関係のグラフを表示することもできます。

```bash
$ pdm list --graph
tempenv 0.0.0
└── click 7.0 [ required: <7.0.0,>=6.7 ]
black 19.10b0
├── appdirs 1.4.3 [ required: Any ]
├── attrs 19.3.0 [ required: >=18.1.0 ]
├── click 7.0 [ required: >=6.5 ]
├── pathspec 0.7.0 [ required: <1,>=0.6 ]
├── regex 2020.2.20 [ required: Any ]
├── toml 0.10.0 [ required: >=0.9.4 ]
└── typed-ast 1.4.1 [ required: >=1.4.0 ]
bump2version 1.0.0
```

### プレリリースバージョンのインストールを許可する

`pyproject.toml` に以下の設定を入れて、有効にしてください：

```toml
[tool.pdm]
allow_prereleases = true
```

### ロックやインストールに使用できるフォーマットの設定

環境変数 `PDM_NO_BINARY` と `PDM_ONLY_BINARY` を設定すると、パッケージの形式（wheel/sdist）を制御することができます。

各環境変数はパッケージ名をカンマで区切ったリストです。`:all:` に設定すると、すべてのパッケージに適用されます。例えば、以下のようになります：

```bash
# werkzeug 用のバイナリはロックされず、インストールに使用されない
PDM_NO_BINARY=werkzeug pdm add flask

# ロックファイルにはバイナリのみがロックされる
PDM_ONLY_BINARY=:all: pdm lock

# インストールにバイナリを使用しない
PDM_NO_BINARY=:all: pdm install

# より高いバージョンのsdistが利用可能であっても、バイナリ配布を優先する
PDM_PREFER_BINARY=flask pdm install
```

### ロッキングの失敗を解決する

PDMが要件を満たす解決策を見つけることができない場合、エラーを発生させます。例えば、以下のような感じです

```bash
pdm django==3.1.4 "asgiref<3"
...
🔒 Lock failed
Unable to find a resolution for asgiref because of the following conflicts:
  asgiref<3 (from project)
  asgiref<4,>=3.2.10 (from <Candidate django 3.1.4 from https://pypi.org/simple/django/>)
To fix this, you could loosen the dependency version constraints in pyproject.toml. If that is not possible, you could also override the resolved version in `[tool.pdm.resolution.overrides]` table.
```

djangoの下位バージョンに変更するか、asgirefの上位を削除するか、どちらかでしょう。しかし、もしそれがあなたのプロジェクトの対象外であれば、 `pyproject.toml` で解決されたパッケージのバージョンを上書きしてみることができます。

### グローバルプロジェクトの管理

グローバルなPythonインタプリタの依存関係も管理したいと思うことがあります。PDMでは、ほとんどのサブコマンドでサポートされている `-g` / `--global` オプションによって、簡単にできます。

このオプションを渡すと、`<CONFIG_ROOT>/global-project` がプロジェクトディレクトリとして使用されます。これは通常のプロジェクトとほとんど同じですが、`pyproject.toml` が自動的に作成され、ビルド機能をサポートしません。このアイデアは、Haskell の [stack](https://docs.haskellstack.org/) から引用したものです。

しかし、stackとは異なり、PDMはデフォルトでは、ローカルプロジェクトが見つからない場合、自動的にグローバルプロジェクトを使用することはありません。パッケージが間違った場所に行くのはあまり嬉しくないので、ユーザは明示的に `-g` / `--global` を渡して有効にする必要があります。しかし、PDMでは、`global_project.fallback` を `true` に設定するだけで、その判断をユーザーに委ねることもできます。

デフォルトでは、PDMが暗黙のうちにグローバルプロジェクトを使用すると、次のようなメッセージが表示されます： プロジェクトが見つかりません、グローバルプロジェクトにフォールバックします。このメッセージを無効にするには、 `global_project.fallback_verbose` を `false` に設定します。

グローバルプロジェクトを `<CONFIG_ROOT>/global-project` 以外のプロジェクトファイルに追跡させたい場合は、`-p` / `--project`  `<path>` オプションでプロジェクトのパスを指定することができます。

> **警告**：
グローバルプロジェクトを使用する場合、`pdm remove` 、`pdm sync --clean` /`--pure` コマンドを使用すると、システム Python にインストールされているパッケージを削除する可能性があるため、注意が必要です。
> 

### ロックされたパッケージを別形式でエクスポートする

CIフローやイメージ構築を容易にするために、pdmロックを他の形式にエクスポートすることもできます。現在のところ、`requirements.txt`  形式のみがサポートされています：

```bash
pdm export -o requirements.txt
```

> 備考：
`.pre-commit` フックを使って `pdm export` を実行することもできます。
> 

# ビルドと公開

ライブラリを開発する場合、プロジェクトに依存関係を追加し、コーディングを終えたら、パッケージをビルドして公開するときです。これは1つのコマンドで簡単にできます：

```bash
pdm publish
```

これにより、自動的にホイールとソースディストリビューション(sdist)がビルドされ、PyPIインデックスにアップロードされます。

PyPI以外のリポジトリを指定する場合は、--repositoryオプションを使用します。パラメータには、アップロードURLまたは設定ファイルに保存されているリポジトリの名前のいずれかを指定します。

```bash
pdm publish --repository testpypi
pdm publish --repository https://test.pypi.org/legacy/
```

### 信頼できるパブリッシャーで公開する

PyPIの信頼できるパブリッシャーを設定することで、リリースワークフローでPyPIトークンを公開する必要がなくなります。そのためには、[ガイド](https://docs.pypi.org/trusted-publishers/adding-a-publisher/)に従ってパブリッシャーを追加し、以下のようにGitHub Actionsのワークフローを記述します：

```yaml
jobs:
  pypi-publish:
    name: upload release to PyPI
    runs-on: ubuntu-latest
    permissions:
      # IMPORTANT: this permission is mandatory for trusted publishing
      id-token: write
    steps:
      - uses: actions/checkout@v3

      - uses: pdm-project/setup-pdm@v3

      - name: Publish package distributions to PyPI
        runs: pdm publish
```

### ビルドと公開を別々に行う

パッケージをビルドするため、`pdm build` を実行します。

```bash
pdm build
```

使用するバックエンドによって、ビルドプロセスを制御するための多くのオプションがあります。詳しくは、[ビルド設定](https://qiita.com/iisaka51/items/f500da5968df355f4c8b#%E3%83%93%E3%83%AB%E3%83%89%E8%A8%AD%E5%AE%9A)のセクションを参照してください。

アーティファクトは `dist` ディレクトリに作成され、PyPIにアップロードすることができるようになります。

```bash
pdm publish --no-build
```

# プロジェクトを設定

`pdm config` コマンドは `git config` と同じように動作しますが、引数を与えないと設定内容を表示するため、`git config` と違って`—list` が不要です。

現在のコンフィギュレーションを表示します：

```bash
pdm config
```

特定の設定内容を表示する

```bash
pdm config pypi.url
```

設定値を変更し、グローバル設定ファイルに保存する

```bash
pdm config pypi.url "https://test.pypi.org/simple"
```

デフォルトでは、設定はグローバルに変更されますが、このプロジェクトでのみ見られるようにしたい場合は、`—local` オプションを追加してください：

```bash
pdm config --local pypi.url "https://test.pypi.org/simple"
```

ローカルな設定は、プロジェクトのルートディレクトリの `pdm.toml` に保存されます。

### 設定ファイル

設定ファイルは、次の順序で検索されます：

1. `<PROJECT_ROOT>/pdm.toml` - プロジェクト設定ファイル
2. `<CONFIG_ROOT>/config.toml` - ホームコンフィギュレーション
3. `<SITE_CONFIG_ROOT>/config.toml` - サイトの設定です。

ここで、`<CONFIG_ROOT>`  は次のとおりです：

- `$XDG_CONFIG_HOME/pdm` 
多くの場合 `~/.config/pdm`
Linux では [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) で定義されています。
- MacOS では `~/Library/Preference/pdm` 
Apple File System Basics で定義されています。
- Windows では、 `%USERPROFILE%\AppData\Local\pdm`
Known folders で定義されています。

また、`<SITE_CONFIG_ROOT>` は次のとおりです：

- `$XDG_CONFIG_DIRS/pdm` 
ほとんどの場合 `/etc/xdg/pdm`
Linux では [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) で定義されています。
- MacOS では `/Library/Preference/pdm`
Apple File System Basics で定義されています。
- Windows では、 `C:\ProgramData\pdm\pdm`
Known folders で定義されています。

`-g` / `--global` オプションを使用した場合、`<PROJECT_ROOT>/pdm.toml` は`<CONFIG_ROOT>/global-project/pdm.toml`で置き換えられます。

利用可能なすべての設定項目は、設定セクションで確認できます。

### 解決結果でプレリリースを許可する

デフォルトでは、pdmの依存関係解決ツールは、依存関係の与えられたバージョン範囲に安定版が存在しない限り、プレリリースを無視します。この動作は `[tool.pdm]` テーブルで `allow_prereleases` を `true` に設定することで変更できます：

```toml
[tool.pdm]
allow_prereleases = true
```

### パッケージインデックスの設定

`pyproject.toml` でソースを指定するか、`pypi.*` の設定により、PDMにパッケージを見つける場所を指示することができます。

`pyproject.toml` にソースを追加します：

```toml
[[tool.pdm.source]]
name = "private"
url = "https://private.pypi.org/simple"
verify_ssl = true
```

`pdm config` でデフォルトのインデックスを変更します：

```bash
pdm config pypi.url "https://test.pypi.org/simple"
```

pdm configで追加インデックスを追加する：

```bash
pdm config pypi.extra.url "https://extra.pypi.org/simple"
```

設定可能なオプションは以下の通りです：

- `url`：  インデックスのURL
- `verify_ssl`： (オプション) SSL証明書を検証するかどうか、デフォルトは `true` です。
- `username`： (オプション) インデックスのユーザー名
- `password`： (オプション) インデックスのパスワード
- `type`： （オプション）`index` または `find_links`、デフォルトは `index`

> **ソースのタイプについて**
デフォルトのタイプは  `index` で、すべてのソースはpipの `--index-url` や `--extra-index-url` のような[PEP 503](https://www.python.org/dev/peps/pep-0503/)スタイルです。直接探すべきファイルやリンクを含む `find_links` にタイプを設定することもできます。
この2つのタイプの違いについては、StackOverflow の[この回答](https://stackoverflow.com/questions/46651454/whats-the-difference-between-find-links-and-index-url-pip-flags/46651848#46651848)を参照してください。
> 
> 回答の抄訳:
> `index-url` は、パッケージ以外の何もないページと考えることができます。あなたはpipに、そのページでインストールしたいものを見つけるように指示しています。そしてそのページは、PEP 503に従って予測可能なフォーマットになっています。インデックスは、利用可能なパッケージのみをリストアップします。
> 
> `find-links` は、特定のパッケージを探すための場所の配列です。ファイルパス、TAR や WHEEL ファイルへの個別の URL、HTML ファイル、git リポジトリなど、さまざまなものを渡すことができます。
> 
> 例えば、あるパッケージをローカルシステムから、他のパッケージをオンラインリポジトリから使用したい場合、この2つを組み合わせることができます。
> 

これらの設定は、最終的なソースリストを作成するために、次の順序で読み込まれます：

1. `pypi.url`
もし pypiが `pyproject.toml` のどのソースの名前フィールドにも表示されない場合
2. `pyproject.toml` の ソース
3. PDMの設定にある `pypi.<name>.url` 

`pypi.ignore_stored_index` を `true` に設定すると、PDMの設定からすべてのインデックスを無効にし、`pyproject.toml` で指定されたものだけを使用することができます。

### **デフォルトのPyPIインデックスを無効化**

デフォルトのPyPIインデックスを省略したい場合は、ソース名を`pypi`にするだけで、そのソースに置き換わります。

```toml
[[tool.pdm.source]]
url = "[https://private.pypi.org/simple](https://private.pypi.org/simple)"
verify_ssl = true
name = "pypi"
```

### pyproject.toml または config にインデックスを追加

プロジェクトを利用する他の人とインデックスを共有したいときは、`pyproject.toml` にインデックスを追加する必要があります。例えば、プライベートなインデックスにしか存在しないパッケージがあり、誰かがそのインデックスを設定しないとインストールできないものがあります。そうでない場合は、他の人に見られないローカル設定に保存してください。

### ソースの順序を尊重する

デフォルトでは、すべてのソースは同等とみなされ、それらのソースからのパッケージはバージョンとWHEELタグでソートされ、最もバージョンの高いものに一致するものが選択されます。

場合によっては、優先されるソースからパッケージを返し、以前のソースからパッケージが欠落している場合は他のソースを検索したいことがあります。PDMは `respect-source-order` という設定を読み込むことで、これをサポートします：

```toml
[tool.pdm.resolution]
respect-source-order = true
```

### インデックスと一緒に認証情報を保存する

`${ENV_VAR}`構文での変数展開でURL内に資格情報を指定すると、これらの変数が環境変数から読み込まれます：

```toml
[[tool.pdm.source]]
name = "private"
url = "https://${PRIVATE_PYPI_USERNAME}:${PRIVATE_PYPI_PASSWORD}/private.pypi.org/simple"
```

### インデックス設定のマージ

インデックス設定は、`[[tool.pdm.source]]` テーブルの `name` フィールド、または設定ファイルの`pypi.<name>` キーとマージされます。これにより、URLとクレデンシャルを別々に保存することができ、ソース管理で秘密が公開されるのを防ぐことができます。例えば、以下のような構成の場合です：

```toml
[[tool.pdm.source]]
name = "private"
url = "https://private.pypi.org/simple"
```

認証情報を設定ファイルに保存することができます：

```toml
pdm config pypi.private.username "foo"
pdm config pypi.private.password "bar"
```

PDMはプライベートインデックスの設定を両方の場所から取得することができます。

もしインデックスがユーザー名とパスワードを要求しているにもかかわらず、環境変数や設定ファイルからそれらを見つけることができない場合、PDMはそれらを入力するよう促します。また、keyringがインストールされている場合は、それがクレデンシャルストアとして使用されます。PDMはインストールされたパッケージまたはCLIからkeyringを使用することができます。

### セントラルインストールキャッシュ

あるパッケージがシステム上の多くのプロジェクトで必要とされる場合、各プロジェクトは独自のコピーを保持する必要があります。これは、特にデータサイエンスや機械学習プロジェクトでは、ディスクスペースの無駄遣いになりかねません。

PDMは、一元化されたパッケージリポジトリにインストールし、異なるプロジェクトでそのインストールにリンクすることによって、同じホイールのインストールをキャッシュすることをサポートしています。これを有効にするには、実行します：

```bash
pdm config install.cache on
```

`pdm config` コマンドに `--local` オプションを追加することで、プロジェクト単位で有効にすることができます。

キャッシュは `$(pdm config cache_dir)/packages` に配置されます。キャッシュの使用状況は、`pdm cache info` で確認できます。キャッシュされたインストールは自動的に管理されることに注意してください。どのプロジェクトにもリンクされていない場合は削除されます。ディスクからキャッシュを手動で削除すると、システム上のいくつかのプロジェクトが壊れる可能性があります。

> **注意**：
PyPIから解決された名前付き要件のインストールのみ、キャッシュすることができます。
> 

### アップロードするリポジトリの設定

`pdm publish` コマンドを使用する場合、グローバルコンフィグファイル(`<CONFIG_ROOT>/config.toml`)からリポジトリのシークレットを読み取ります。設定内容は以下の通りです：

```toml
[repository.pypi]
username = "frostming"
password = "<secret>"

[repository.company]
url = "https://pypi.company.org/legacy/"
username = "frostming"
password = "<secret>"
ca_certs = "/path/to/custom-cacerts.pem"
```

PEMエンコードされた認証局バンドル（ca_certs）は、サーバー証明書が標準のcertifi CAバンドルで署名されていないローカル/カスタムPyPIリポジトリに使用することができます。

> **注意**：
リポジトリは、前のセクションのインデックスとは異なります。リポジトリは公開するためのもので、インデックスはロックと解決するためのものです。これらは構成を共有しません。
> 

> **ヒント：**
pypiとtestpypiリポジトリのurlは設定する必要はなく、デフォルト値で埋められています。
ユーザー名、パスワード、証明書バンドルは、`pdm publish` のオプション`--username`、`--password`、`--ca-certs` で渡すことができます。
> 

コマンドラインからリポジトリの設定を変更するには、`pdm config` コマンドを使用します：

```bash
pdm config repository.pypi.username "__token__"
pdm config repository.pypi.password "my-pypi-token"

pdm config repository.company.url "https://pypi.company.org/legacy/"
pdm config repository.company.ca_certs "/path/to/custom-cacerts.pem"
```

### 解決されたパッケージのバージョンをオーバーライドする

上流のライブラリが設定したバージョン範囲が不正確で、それを修正できないために依存関係を解決できないことがあります。この場合、PDMのoverrides 機能を使って、パッケージの特定のバージョンを強制的にインストールすることができます。

`pyproject.toml` に以下のような構成があるとします：

```toml
[tool.pdm.resolution.overrides]
asgiref = "3.2.10"  # exact version
urllib3 = ">=1.26.2"  # version range
pytz = "https://mypypi.org/packages/pytz-2020.9-py3-none-any.whl"  
```

そのテーブルの各エントリーは、パッケージ名と希望するバージョンです。この例では、PDMは上記のパッケージを、他の解決方法があるかどうかにかかわらず、指定されたバージョンに解決します。

> 警告：
`[tool.pdm.resolution.overrides]` 設定を使用することで、その解決方法による非互換性のリスクは、あなた自身にあります。この設定は、あなたの要件に有効な解像度がなく、特定のバージョンが動作することが分かっている場合にのみ使用することができます。ほとんどの場合、依存関係の配列に一時的な制約を追加するだけでよいでしょう。
> 

# PDMスクリプト

PDM では `npm run` と同様に、ローカルパッケージをロードした状態で任意のスクリプトやコマンドを実行することができます。

## 任意のスクリプト

```bash
pdm run flask run -p 54321
```

これは、`__pypackages__` ディレクトリのパッケージを認識している環境で、`flask run -p 54321` を実行することになります。

## ユーザースクリプト

PDMは、`pyproject.toml` のオプションの `[tool.pdm.scripts]` セクションでカスタムスクリプトショートカットをサポートします。

`pdm run <script_name>` のように実行すると、PDMプロジェクトのコンテキストでスクリプトを呼び出すことができます。例えば、以下のようになります：

```bash
[tool.pdm.scripts]
start = "flask run -p 54321"
```

次にターミナルで以下のように」コマンドを実行します。

```bash
$ pdm run start
Flask server started at http://127.0.0.1:54321
```

コマンドラインでスクリプト名の後に続く引数は、すべて実行されるコマンドに渡されます。

```bash
$ pdm run start -h 0.0.0.0
Flask server started at http://0.0.0.0:54321
```

> **yarn のようなスクリプトのショートカット**
スクリプトがビルトインやプラグインのコマンドと競合しない限り、すべてのスクリプトをルートコマンドとして使用できるようにするビルトインショートカットが用意されています。つまり、スタートスクリプトがあれば、`pdm run start` と `pdm start` の両方を実行することができます。しかし、`install` スクリプトがある場合、`pdm run install` だけが実行され、`pdm install` はビルトインのインストールコマンドを実行します。
> 

## PDMは4種類のスクリプトをサポートしています：

### `cmd`

プレーンテキストのスクリプトは通常のコマンドとみなされますが、明示的に指定することも可能です。

```toml
[tool.pdm.scripts]
start = {cmd = "flask run -p 54321"}
```

パラメータ間にコメントを入れたい場合など、文字列ではなく、配列でコマンドを指定した方が便利な場合があります：

```toml
[tool.pdm.scripts]
start = {cmd = [
    "flask",
    "run",
    # Important comment here about always using port 54321
    "-p", "54321"
]}
```

### `shell`

シェルスクリプトは、パイプラインや出力リダイレクトなど、よりシェルに特化したタスクを実行するために使用することができます。これは基本的に `subprocess.Popen()`で `shell=True` で実行されます：

```toml
[tool.pdm.scripts]
filter_error = {shell = "cat error.log|grep CRITICAL > critical.log"}
```

### `call`

スクリプトは、`<module_name>:<func_name>`の形でpython関数を呼び出すように定義することもできます：

```toml
[tool.pdm.scripts]
foobar = {call = "foo_package.bar_module:main"}
```

この関数には、リテラル引数を与えることができます。

```toml
[tool.pdm.scripts]
foobar = {call = "foo_package.bar_module:main('dev')"}
```

### `composite`

このスクリプトは、他の定義されたスクリプトを実行することができます。

```toml
[tool.pdm.scripts]
lint = "flake8"
test = "pytest"
all = {composite = ["lint", "test"]}
```

`pdm run all` を実行すると、まず lint が実行され、その後 lint が成功したかどうかテストされます。

呼び出されたスクリプトに引数を指定することもできます：

```toml
[tool.pdm.scripts]
lint = "flake8"
test = "pytest"
all = {composite = ["lint mypackage/", "test -v tests/"]}
```

注：コマンドラインから渡された引数は、呼び出された各タスクに渡されます。

## スクリプトオプション

### `env`

現在のシェルで設定されている環境変数はすべて `pdm run` で見ることができ、実行時に展開されます。また、`pyproject.toml` の中で、いくつかの固定環境変数を定義することもできます：

```toml
[tool.pdm.scripts]
start.cmd = "flask run -p 54321"
start.env = {FOO = "bar", FLASK_ENV = "development"}
```

[TOML構文](https://github.com/toml-lang/toml)を使って複合辞書を定義していることに注目してください。

> **注意**：
複合タスクのレベルで指定された環境変数は、呼び出されたタスクで定義されたものを上書きします。
> 

### `env_file`

また、すべての環境変数をdotenvファイルに格納し、PDMに読ませることも可能です

```toml
[tool.pdm.scripts]
start.cmd = "flask run -p 54321"
start.env_file = ".env"
```

dotenvファイル内の変数は、既存の環境変数を上書きすることはありません。dotenvファイルに既存の環境変数を上書きさせたい場合は、次のようにします：

```toml
[tool.pdm.scripts]
start.cmd = "flask run -p 54321"
start.env_file.override = ".env"
```

> **注意**：
複合タスクレベルで指定されたdotenvファイルは、呼び出されたタスクで定義されたものを上書きします。
> 

### `site_packages`

実行環境が外側のPythonインタプリタから適切に隔離されていることを確認するために、以下の条件のいずれかが成立しない限り、選択したインタプリタからの `site-packages` は `sys.path` にロードされません：

- 実行ファイルがPATHにあるが、`__pypackages__` ディレクトリの中にない。
- pdmの実行時に`-s` / `—site-packages` オプションが与えられている。
- `site_packages = true` が `scripts` テーブルまたはグローバル設定キー `_` にある。

なお、PEP 582を有効にした場合、site-packagesは常にロードされます（pdm runの接頭辞なし）。

## 共有オプション

`pdm run`で実行されるすべてのタスクでオプションを共有したい場合は、`[tool.pdm.scripts]` テーブルの特別なキー `_` の下に書き込むことができます：

```toml
[tool.pdm.scripts]
_.env_file = ".env"
start = "flask run -p 54321"
migrate_db = "flask db upgrade"
```

また、タスクの中では、環境変数 `PDM_PROJECT_ROOT` がプロジェクトルートに設定されます。

## 引数のプレースホルダー

デフォルトでは、ユーザーから提供されたすべての追加引数は、単にコマンドに追加されます（`composite`タスクの場合はすべてのコマンドに追加されます）。

ユーザーが提供する追加引数をもっと制御したい場合は、`{args}` プレースホルダーを使用できます。これはすべてのスクリプトタイプで利用可能で、それぞれ適切に補間されます：

```toml
[tool.pdm.scripts]
cmd = "echo '--before {args} --after'"
shell = {shell = "echo '--before {args} --after'"}
composite = {composite = ["cmd --something", "shell {args}"]}
```

これは、次のような補間を行います（これらは実際のスクリプトではなく、補間を説明するためだけのものです）：

```bash
$ pdm run cmd --user --provided
--before --user --provided --after
$ pdm run cmd
--before --after
$ pdm run shell --user --provided
--before --user --provided --after
$ pdm run shell
--before --after
$ pdm run composite --user --provided
cmd --something
shell --before --user --provided --after
$ pdm run composite
cmd --something
shell --before --after
```

オプションで、ユーザー引数が与えられない場合に使用されるデフォルト値を指定することができます：

```toml
[tool.pdm.scripts]
test = "echo '--before {args:--default --value} --after'"
```

これは、次のような補間を行います。

```bash
$ pdm run test --user --provided
--before --user --provided --after
$ pdm run test
--before --default --value --after
```

> **注意**：
プレースホルダーが検出されると、引数が追加されなくなります。これは複合スクリプトにとって重要です。なぜなら、サブタスクの1つでプレースホルダーが検出されると、どのサブタスクにも引数が追加されないからです。プレースホルダーを必要とするネストしたコマンドには、明示的にプレースホルダーを渡す必要があります。
> 

> **注意**：
コールスクリプトは{args}プレースホルダーをサポートしていません。スクリプトはsys.argvに直接アクセスして、このような複雑なケースを処理することができます。
> 

## スクリプトの一覧を表示する

`pdm run` `-l`  / `--list` を使うと、利用可能なスクリプトのショートカットの一覧が表示されます：

```bash
$ pdm run --list
╭─────────────┬───────┬───────────────────────────╮
│ Name         │ Type   │ Description                 │
├─────────────┼───────┼───────────────────────────┤
│ test_cmd     │ cmd   │ flask db upgrade             │
│ test_script  │ call  │ call a python function       │
│ test_shell   │ shell │ shell command                │
╰─────────────┴───────┴───────────────────────────╯
```

スクリプトの説明でヘルプオプションを追加すると、上記の出力の`Description`欄に表示されます。

> **注意** ：
名前がアンダースコア（`_`）で始まるタスクは、内部タスク（ヘルパー...）とみなされ、一覧には表示されません。
> 

## プリ/ポストスクリプト

npmと同様に、PDMもプリスクリプトとポストスクリプトによるタスクの構成に対応しており、プリスクリプトは与えられたタスクの前に、ポストスクリプトはその後に実行されます。

```toml
[tool.pdm.scripts]
pre_compress = "{{ Run BEFORE the `compress` script }}"
compress = "tar czvf compressed.tar.gz data/"
post_compress = "{{ Run AFTER the `compress` script }}"
```

この例では、`pdm run compress` はこれら3つのスクリプトをすべて順次実行します。

> **パイプラインが速攻で失敗する**
pre -> self -> postスクリプトのパイプラインでは、失敗するとその後の実行がキャンセルされます。
> 

## フックスクリプト

ある状況下では、PDMはいくつかの特別なフックスクリプトを探し、実行します：

- `post_init`： `pdm init` の後に実行されます。
- `pre_install`： パッケージのインストール前に実行する
- `post_install`： パッケージがインストールされた後に実行する
- `pre_lock`： 依存性解決の前に実行する
- `post_lock`： 依存性解決後の実行
- `pre_build`： ディストリビューションをビルドする前に実行する
- `post_build`： ディストリビューションのビルド後に実行する
- `pre_publish`： ディストリビューションを公開する前に実行する
- `post_publish`： ディストリビューションが公開された後に実行する
- `pre_script`： スクリプトの前に実行する
- `post_script`： スクリプトの後に実行する
- `pre_run`： スクリプトを実行する前に一度だけ実行する
- `post_run`： スクリプト実行後に1回実行する

> **注意**：
preとpostのスクリプトは、引数を受け取ることができません。
> 

> **名前の衝突を回避**
`[tool.pdm.scripts]` テーブルにインストールスクリプトが存在する場合、`pdm install` と `pdm run install` の両方で `pre_install` スクリプトが実行されることがあります。そのため、保存された名前を使用しないことをお勧めします。
> 

> **注意**：
複合タスクは、プレスクリプトとポストスクリプトを持つことができます。呼び出されたタスクは、それぞれ独自のプレスクリプトとポストスクリプトを実行します。
> 

## スクリプトのスキップ

フックやpre / post スクリプトを使わずにスクリプトを実行したい場合があるため、`—skip=:all` があります。また、`—skip=:pre` と `--skip=:post` もあり、それぞれ `pre_*` フックと `post_*` フックをすべてスキップすることができます。

また、pre スクリプトは必要だが post スクリプトは必要ない、あるいは複合タスクから 1 つを除いたすべてのタスクが必要ということもあり得ます。このような場合には、より細かい `--skip` パラメータが用意されており、除外するタスクやフック名のリストを指定することができます。

```bash
pdm run --skip pre_task1,task2 my-composite
```

このコマンドは、`my-composite` タスクを実行し、`pre_task1` フックと `task2` およびそのフックをスキップします。

環境変数 `PDM_SKIP_HOOKS` でスキップリストを指定することもできますが、`--skip` オプションが指定されるとすぐに上書きされます。

フックとpre / post スクリプトの動作についての詳細は、[フックスクリプト](https://qiita.com/iisaka51/items/f500da5968df355f4c8b#%E3%83%95%E3%83%83%E3%82%AF%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88)のセクションを参照してください。

# ライフサイクルとフック

Pythonの成果物として、プロジェクトはPythonプロジェクトのライフサイクルのさまざまなフェーズを通過することになり、PDMはこれらのフェーズで期待されるタスクを実行するコマンドを提供します。

また、これらのステップに接続されるフックも提供され、以下のことが可能になります：

- プラグインが同名のシグナルをリッスンする。
- 開発者が同じ名前のカスタムスクリプトを定義する。

さらに、`pre_invoke` シグナルは、あらゆるコマンドが呼び出される前に発せられ、プラグインが事前にプロジェクトやオプションを変更することを可能にします。

ビルトインコマンドは、現在3つのグループに分かれています：

- 初期化タスク
- 依存関係の管理
- 公開タスク

インストールと公開の間には、おそらくいくつかの繰り返しタスク（ハウスキーピング、リント、テストなど）を実行する必要があると思います。

柔軟性を持たせるために、PDMはいくつかのフックやタスクを必要に応じてスキップすることができます。

## 初期化タスク

初期化タスクは、既存のプロジェクトを初期化するために `pdm init` コマンドを実行することによって、プロジェクトの寿命の中で一度だけ発生します。（`pyproject.toml` ファイルを埋めるためのプロンプト）

これらは、以下のフックをトリガーします：

- post_init![pdm_post_init.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182364/3f9334a4-56df-3cdd-4cbd-1d51ec8f2206.png)

## 依存関係の管理

依存関係管理は、開発者が作業して以下のことを実行できるようにするために必要です：

- **lock** 
`pyproject.toml` の要件からロックファイルを計算する。
- **sync** 
ロックファイルからPEP582パッケージを同期（追加/削除/更新）し、現在のプロジェクトを編集可能な状態でインストールする。
- **add** 
依存関係を追加する
- **remove** 
依存関係を削除する

これらの手順はすべて、次のコマンドで直接利用できます：

- `pdm lock`
ロックタスクの実行
- `pdm sync` 
同期タスクを実行します。
- `pdm install` 
同期タスクを実行し、必要であればロックから先行する。
- `pdm add` 
依存性要件を追加し、再ロックした後、同期する。
- `pdm remove` 
依存性要件を削除し、再ロックした後、同期する。
- `pdm update` 
依存関係を最新版から再ロックし、その後同期する。

これらは、以下のフックをトリガーします：

- `pre_install`
- `post_install`
- `pre_lock`
- `post_lock`

![pdm_prepost_install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182364/9b19f772-baca-e312-97b5-16362bccad84.png)

### Pythonのバージョン切り替え

これは依存関係の管理における特別なケースです。`pdm use` を使って現在のPythonのバージョンを切り替えることができ、新しいPythonインタプリタで `post_use` シグナルを発することができます。

![pdm_use.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182364/86f8b052-8739-b5f6-af70-531f2cd532d9.png)

## 公開タスク

パッケージ/ライブラリの公開準備が整うと同時に、公開タスクが必要になります：

- **build** 
必要な資産をビルド/コンパイルして、すべてをPythonパッケージにする (sdist, wheel)
- **upload** 
パッケージをリモートのPyPIインデックスにアップロード/公開する。

これらの手順はすべて以下のコマンドで可能です：

- `pdm build`
- `pdm publish`

これらは以下のフックをトリガーします：

- `pre_publish`
- `post_publish`
- `pre_build`
- `post_build`
    
 ![pdm_publish.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182364/e6e7d8e2-f4be-ab70-f897-dd9c943af016.png)

フックを含む最初の失敗で実行を停止します。

## ユーザースクリプト

ユーザースクリプトでは以下のことを知っておく必要があります。

詳細は[PDMスクリプト](https://qiita.com/iisaka51/items/f500da5968df355f4c8b#pdm%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88)のセクションを参照してください。

- 各ユーザースクリプトは、複合スクリプトを含め、`pre_*`と`post_*` スクリプトを定義する。
- 各スクリプトを `pdm run` で実行すると、pre_run と post_run フックが起動する。
- 各スクリプトを実行すると、`pre_script` と `post_script` フックが起動する。

次のようなスクリプトの定義があるとします：

```toml
[tool.pdm.scripts]
pre_script = ""
post_script = ""
pre_test = ""
post_test = ""
test = ""
pre_composite = ""
post_composite = ""
composite = {composite = ["test"]}
```

`pdm run test` は、次のようなライフサイクルを持ちます：

![pdm_run_test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182364/99435e2f-e37d-c9d3-90cd-f26894951d21.png)

これに対し、pdm run compositeは以下のようになります：

![pdm_run_composite.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182364/f7a639d6-0f43-0606-d6de-f2438413e678.png)

## スキップ

ビルトインコマンドやカスタムユーザスクリプトに対して、どのタスクやフックを実行するかを --skip オプションで制御することが可能です。

このオプションには、スキップするフックやタスクの名前をカンマで区切ったリストと、定義済みの `:all` ,  `:pre` ,  `:post` ショートカットを指定することができます。環境変数 `PDM_SKIP_HOOKS` にスキップリストを指定することもできますが、`—skip` オプションが指定されるとすぐに上書きされます。

先ほどのスクリプトブロックがある場合、`pdm run --skip=:pre,post_test composite` を実行すると、次のようにライフサイクルが短縮されます：

![pdm_run_composite_with_skip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182364/1ce82b3c-3ada-b963-2c05-b4b5e74754fd.png)

# 高度な使用方法

## 自動テスト

### ランナーとしてToxを使用する

[Tox](https://tox.readthedocs.io/en/latest/) は、複数のPythonバージョンや依存関係セットに対するテストに最適なツールです。以下のような`tox.ini` を設定することで、テストをPDMと統合することができます：

```
[tox]
env_list = py{36,37,38},lint
isolated_build = true

[testenv]
setenv =
    PDM_IGNORE_SAVED_PYTHON="1"
deps = pdm
commands =
    pdm install --dev
    pytest tests

[testenv:lint]
deps = pdm
commands =
    pdm install -G lint
    flake8 src/
```

Toxが作成した仮想環境を使用するためには、`pdm config python.use_venv true` を設定していることを確認する必要があります。そうすると、PDMは`pdm lock`の依存関係に virtualenv をインストールします。専用venvでは、pdm run pytest tests/の代わりにpytest tests/でツールを直接実行することができます。

また、テストコマンドの中で `pdm add` / `pdm remove` / `pdm update` / `pdm lock` を実行しないように注意してください、そうしないとPDMのロックファイルが予期せず変更されてしまいます。その他の依存関係は、deps config で指定することができます。また、PDMを正しく動作させるためには、上記の例のように `isolated_buid` と `passenv` を設定する必要があります。

これらの制約を解消するために、Toxプラグイン `tox-pdm` があります。これは次のようにインストールできます。

```bash
python3 -m pip install tox-pdm
```

あるいは、`pdm add` を使うこともできます。

```bash
pdm add --dev tox-pdm
```

そして次のような `tox.ini` を作成します。

```
[tox]
env_list = py{36,37,38},lint

[testenv]
groups = dev
commands =
    pytest tests

[testenv:lint]
groups = lint
commands =
    flake8 src/
```

詳細は、[tox-pdm](https://github.com/pdm-project/tox-pdm) のプロジェクトを参照してください。

### ランナーとしてNoxを使用する

[Nox](https://nox.thea.codes/) もまた、自動テストに最適なツールです。toxとは異なり、Noxは設定に標準的なPythonファイルを使用します。

NoxでPDMを使うのはもっと簡単です。ここに `noxfile.py` の例を示します：

```python
import os
import nox

os.environ.update({"PDM_IGNORE_SAVED_PYTHON": "1"})

@nox.session
def tests(session):
    session.run('pdm', 'install', '-G', 'test', external=True)
    session.run('pytest')

@nox.session
def lint(session):
    session.run('pdm', 'install', '-G', 'lint', external=True)
    session.run('flake8', '--import-order-style', 'google')
```

なお、`PDM_IGNORE_SAVED_PYTHON` は、PDMが仮想環境内のPythonを正しくピックアップできるように設定する必要があります。また、pdmがPATHで利用可能であることを確認してください。noxを実行する前に、venvの再利用を有効にするために、設定項目 `python.use_venv` が `true` であることも確認する必要があります。

## PEP 582 __pypackages__ディレクトリについて

デフォルトでは、`pdm run`でツールを実行した場合、`__pypackages__`はプログラムとそれによって作成されたすべてのサブプロセスによって参照されます。これは、これらのツールによって作成された仮想環境も `__pypackages__` 内のパッケージを認識することを意味し、場合によっては予期せぬ動作を引き起こすことになります。noxの場合、`noxfile.py` に以下の行を追加することでこれを回避することができます：

```python
os.environ.pop("PYTHONPATH", None)
```

toxの場合、PYTHONPATHはテストセッションに渡されないので、これは問題にはならないでしょう。さらに、プロジェクトごとにインストールする必要がないように、noxとtoxをそれぞれのpipx環境で動作させることが推奨されています。この場合、PEP 582パッケージも問題ないでしょう。

## 継続的インテグレーションでPDMを使う

PDM は Python < 3.7 にはインストールできないので、もしあなたのプロジェクトがこれらの Python バージョンでテストされるなら、PDM が正しい Python バージョンにインストールされているかどうかを確認する必要があります。これは、特定のジョブ/タスクが実行されるターゲット Python バージョンとは異なる場合があります。

幸い、GitHub Actionを使用している場合、[pdm-project/setup-pdm](https://github.com/marketplace/actions/setup-pdm) があるので、このプロセスを簡単に行うことができます。以下はGitHub Actionsのワークフロー例ですが、他のCIプラットフォームにも適応できます。

```yaml
Testing:
  runs-on: ${{ matrix.os }}
  strategy:
    matrix:
      python-version: [3.7, 3.8, 3.9, '3.10']
      os: [ubuntu-latest, macOS-latest, windows-latest]

  steps:
    - uses: actions/checkout@v3
    - name: Set up PDM
      uses: pdm-project/setup-pdm@v2
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install dependencies
      run: |
        pdm sync -d -G testing
    - name: Run Tests
      run: |
        pdm run -v pytest tests
```

> TIPS：
GitHub Actionをご利用の場合、Ubuntuの仮想環境では互換性に問題があることが確認されています。そのマシンでPDMの並列インストールに失敗した場合は、`parallel_install` を `false` に設定するか、`env LD_PRELOAD=lib/x86_64-linux-gnu/libgcc_s.so.1` を設定する必要があります。これはすでに `pdm-project/setup-pdm` アクションによって処理されます。
> 

> **注意**：
CIスクリプトが適切なユーザーを設定せずに実行されると、PDMがキャッシュディレクトリを作成しようとしたときにパーミッションエラーが発生することがあります。これを回避するには、環境変数 `HOME` を書き込み可能なディレクトリに自分で設定します：
> 

```bash
export HOME=/tmp/home
```

## 複数ステージのDockerfileでPDMを使用する

PDMを複数ステージのDockerfileで使用するには、まずプロジェクトと依存関係を `__pypackages__` にインストールし、このフォルダを最終ステージにコピーして `PYTHONPATH` に追加する方法が有効です。

```docker
# ビルドステージ
FROM python:3.8 AS builder

# PDMのインストール
RUN pip install -U pip setuptools wheel
RUN pip install pdm

# ファイルをコピーする
COPY pyproject.toml pdm.lock README.md /project/
copy src/ /project/src

# 依存関係やプロジェクトをローカルパッケージのディレクトリにインストールする
WORKDIR /project
RUN mkdir __pypackages__ && pdm install --prod --no-lock --no-editable

# ステージを実行する
FROM python:3.8

# ビルドステージからパッケージを取得する
ENV PYTHONPATH=/project/pkgs
COPY --from=builder /project/__pypackages__/3.8/lib /project/pkgs

#コマンド/エントリーポイントを設定する
CMD ["python", "-m", "project" ]
```

## PDMを使って複数のサブパッケージを管理する

PDMを使えば、1つのプロジェクトの中に複数のサブパッケージが存在し、それぞれに `pyproject.toml` ファイルを持たせることができます。そして、すべての依存関係をロックするためのpdm.lockファイルを1つだけ作成することができます。サブパッケージは、互いに依存関係を持つことができます。これを実現するには、次のステップに従います：

`project/pyproject.toml` ：

```toml
[tool.pdm.dev-dependencies]
dev = [
    "-e file:///${PROJECT_ROOT}/packages/foo-core",
    "-e file:///${PROJECT_ROOT}/packages/foo-cli",
    "-e file:///${PROJECT_ROOT}/packages/foo-app",
]
```

`packages/foo-cli/pyproject.toml` ：

```toml
[projects]
dependencies = ["foo-core"]
```

`packages/foo-app/pyproject.toml`：

```toml
[projects]
dependencies = ["foo-core"]
```

ここで、プロジェクトのルートで `pdm install` を実行すると、すべての依存関係がロックされた`pdm.lock` が得られます。すべてのサブパッケージは編集可能な状態でインストールされます。

具体的な例は、[リポジトリのサンプル](https://github.com/pdm-project/pdm-example-monorepo)を参照してください。

## pre-commitのフック

pre-commitは、gitフックを一元的に管理するための強力なフレームワークです。PDMはすでに内部のQAチェックのためにpre-commitフックを使っています。PDMは、ローカルまたはCIパイプラインで実行できるいくつかのフックも公開しています。

## requirements.txt や setup.py をエクスポートする

このフックは、pdm exportコマンドを有効な引数とともにラップします。これは、`pdm lock` の実際の内容を反映した r`equirements.txt` や `setup.py` ファイルをコードベースで確認するためのフックとして使用できます。（例えば、CI用）

```yaml
# export python requirements
- repo: https://github.com/pdm-project/pdm
  rev: 2.x.y # a PDM release exposing the hook
  hooks:
    - id: pdm-export
      # command arguments, e.g.:
      args: ['-o', 'requirements.txt', '--without-hashes']
      files: ^pdm.lock$
```

## pdm.lockがpyproject.tomlで最新かどうかをチェックする

このフックは、`pdm lock —check` コマンドを任意の有効な引数とともにラップします。`pyproject.toml`に依存関係が追加/変更/削除されるたびに、`pdm.lock` も最新であることを確認するフックとして使用できます。（例えば、CI用）

```yaml
- repo: https://github.com/pdm-project/pdm
  rev: 2.x.y # a PDM release exposing the hook
  hooks:
    - id: pdm-lock-check
```

# 仮想環境での作業

`pdm init` コマンドを実行すると、PDMはプロジェクトで使用するPythonインタプリタを尋ねます。これは、依存関係をインストールしたりタスクを実行するためのベースとなるインタプリタです。

[PEP 582](https://www.python.org/dev/peps/pep-0582/) と比較して、仮想環境はより成熟していると考えられ、IDEだけでなくPythonエコシステムでのサポートも充実しています。したがって、他に設定されていない場合は、仮想環境がデフォルトモードとなります。

プロジェクトのインタプリタ（`.pdm-python` で指定されているインタプリタ、`pdm info` で確認可能）が仮想環境のものである場合、仮想環境が使用されます。

## 仮想環境の自動作成

デフォルトでは、PDMは他のパッケージマネージャと同様に仮想環境のレイアウトを使用することを好みます。Pythonインタプリタが未決定の新しいPDM管理プロジェクトで初めて `pdm install` を実行すると、PDMは`<project_root>/.venv` に仮想環境を作成し、依存関係をそこにインストールします。

`pdm init` の対話型セッションでも、PDMは仮想環境を作成するかどうか聞いてきます。

PDMが仮想環境を作成する際に使用するバックエンドを選択することができます。現在のところ、3つのバックエンドをサポートしています：

- `virtualenv`  (デフォルト)
- `venv`
- `conda`

これは、`pdm config venv.backend [virtualenv|venv|conda]` で変更することができます。

## 自分で仮想環境を作成する

Pythonのバージョンに関係なく、複数の仮想環境を作成することができます。

```bash
# 3.8 インタプリタに基づく仮想環境を作成する
$ pdm venv create 3.8

# バージョン文字列とは別の名前を割り当てる
$ pdm venv create --name for-test 3.8

# venv をバックエンドにして仮想環境を作成する
# サポートしているバックエンド: virtualenv(default), venv, conda
$ pdm venv create --with venv 3.9
```

## 仮想環境の場所

初めてPDMを使用する場合、`.venv` が既に存在しない限り、PDMはプロジェクト内に仮想環境を作成しようとします。その他の仮想環境は `venv.location` で指定された場所に移動します。名前の衝突を避けるために、`<project_name>-<path_hash>-<name_or_python_version>` のように命名されます。

オプション`——name` を与えて作成された仮想環境は、常にこの場所に移動します。

`pdm config venv.in_project false`でプロジェクト内仮想環境の作成を無効にできます。

## 仮想環境の自動検出

プロジェクト設定にインタプリタが格納されていない場合や環境変数 `PDM_IGNORE_SAVED_PYTHON` が設定されている場合、PDMは利用可能な仮想環境を検出しようとします：

- プロジェクトルートにある `venv`、`env`、`.venv` ディレクトリー
- 環境変数 `PDM_IGNORE_ACTIVE_VENV` が設定されていない限り、現在有効になっている環境変数

このプロジェクトで作成されたすべての環境変数を一覧します。

```bash
$ pdm venv list
Virtualenvs created with this project:

-  3.8.6: C:\Users\Frost Ming\AppData\Local\pdm\pdm\venvs\test-project-8Sgn_62n-3.8.6
-  for-test: C:\Users\Frost Ming\AppData\Local\pdm\pdm\venvs\test-project-8Sgn_62n-for-test
-  3.9.1: C:\Users\Frost Ming\AppData\Local\pdm\pdm\venvs\test-project-8Sgn_62n-3.9.1
```

## 仮想環境のパスまたはpythonインタプリタを表示

```bash
$ pdm venv --path for-test
$ pdm venv --python for-test
```

## 仮想環境の削除

```bash
$ pdm venv remove for-test
Virtualenvs created with this project:
Will remove: C:\Users\Frost Ming\AppData\Local\pdm\pdm\venvs\test-project-8Sgn_62n-for-test, continue? [y/N]:y
Removed C:\Users\Frost Ming\AppData\Local\pdm\pdm\venvs\test-project-8Sgn_62n-for-test
```

## 仮想環境の有効化

pipenvやpoetryのようにサブシェルを生成するのではなく、pdm-venv は activateコマンドをコンソールに表示します。そして、その出力を eval に送り、現在のシェルから離れることなく仮想環境を有効化することができます。

- bash , csh , zsh
    
    ```bash
    $ eval $(pdm venv activate for-test)
    (test-project-for-test) $  # Virtualenv entered
    Fish
    
    $ eval (pdm venv activate for-test)
    ```
    
- powershell
    
    ```bash
    PS1> Invoke-Expression (pdm venv activate for-test)
    ```
    

長いコマンドの入力を避けるために、独自のシェルショートカット関数を作ることができます。

以下はBashの例です：

```bash
pdm_venv_activate() {
    eval $('pdm' 'venv' 'activate' "$1")
}
```

そして、`pdm_venv_activate $venv_name`で活性化し、直接 `deactivate` で仮想環境を無効にすることができます。

さらに、プロジェクトのインタプリタが仮想環境Pythonの場合、`activate` に続く引数(仮想環境名）を省略することができます。

> **注意**：
`pdm venv activate` は、プロジェクトが使用するPythonインタプリタを切り替えるものではありません。環境変数に仮想環境のパスを注入することで、シェルを変更するだけです。
Pythonインタプリタを切り替えるためには、`pdm use` コマンドを使用します。
> 

CLIの詳しい使い方は、[`pdm venv`](https://qiita.com/iisaka51/items/f500da5968df355f4c8b#venv-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%8) のヘルプメッセージを参照してください。

## プロンプトのカスタマイズ

デフォルトでは、仮想環境をアクティブにすると、`{プロジェクト名}-{python_version}`のようにプロンプトが表示されます。

例えば、プロジェクト名が `test-project` の場合：

```bash
$ eval $(pdm venv activate for-test)
(test-project-3.10) $  # {project_name} == test-project and {python_version} == 3.10
```

このフォーマットは、設定 `venv.prompt` または環境変数 `PDM_VENV_PROMPT` を設置してから、pdm initまたはpdm venv createで仮想環境を作成することでカスタマイズすることができます。

利用可能な変数は以下の通りです：

- `project_name`： プロジェクトの名前
- `python_version`：  仮想環境で使用するPythonのバージョン

```bash
$ PDM_VENV_PROMPT='{project_name}-py{python_version}' pdm venv create --name test-prompt
$ eval $(pdm venv activate test-prompt)
(test-project-py3.10) $
```

## 仮想環境で有効化せずにコマンドを実行する

```bash
# スクリプトの実行
$ pdm run --venv test test

# パッケージのインストール
$ pdm sync --venv test

# インストール済みのパッケージの一覧
$ pdm list --venv test
```

他にも `--venv`フラグや環境変数 `PDM_IN_VENV` をサポートするコマンドがありますので、pdm コマンド詳細を参照してください。この機能を使う前に、`pdm venv create --name <name>` で仮想環境を作成する必要があります。

## プロジェクト環境として仮想環境に切り替える

デフォルトでは、`pdm use` で 仮想環境でないPythonを選択した場合、プロジェクトは[PEP 582モード](https://pdm.fming.dev/latest/usage/pep582/)に切り替わります。また、`--venv` オプションで名前付きの仮想環境に切り替えられるようにしています：

```bash
# 仮想環境 test に切り替える 
$ pdm use --venv test

# プロジェクト内の $PROJECT_ROOT/.venv にある仮想環境に切り替える
$ pdm use --venv
```

## 仮想環境モードの無効化

`pdm config python.use_venv false` で 仮想環境の自動作成と自動検出を無効にすることができます。`**use_venv` を無効にすると、選択したインタプリタが仮想環境のものであっても、常にPEP 582モードが使用されます。**

## 仮想環境へpipをインストール

デフォルトでは、PDMは仮想環境にpipを含めません。これは、仮想環境に依存するものだけがインストールされるようにすることで、隔離性を高めるためです。

一度だけpipをインストールしたい場合（例えばCIで任意の依存関係をインストールしたい場合）には、以下のように実行します：

```bash
# 仮想環境に pip をインストール
$ pdm run python -m ensurepip

# 任意の依存関係をインストールする
# これらの依存関係は、lockfileの依存関係との競合をチェックしません
$ pdm run python -m pip install coverage
```

または、`--with-pip` で仮想環境を作成することもできます：

```bash
$ pdm venv create --with-pip 3.9
```

`ensurepip` については、[ensurepip のドキュメント](https://docs.python.org/3/library/ensurepip.html)を参照してください。

仮想環境にpipを含めるようにPDMを恒久的に設定したい場合は、設定 `venv.with_pip` を使用できます。

# PEP 582で作業する

> **注意**：**PEP 582は却下されました**
しかし、この機能がPDMの誕生理由であることから、PDMはサポートを維持します。
代わりに仮想環境の利用を推奨します。
> 

[PEP 582](https://www.python.org/dev/peps/pep-0582/)では、依存関係はプロジェクトルート下の`__pypackages__`ディレクトリにインストールされます。PEP 582をグローバルに有効にすると、プロジェクトインタプリタを使ってスクリプトを直接実行することもできるようになります。

**プロジェクトインタプリタが通常のPythonの場合、このモードは有効です。**

なお，自分のマシンで初めて扱うプロジェクトで，空の`__pypackages__`ディレクトリがあると，自動的にPEP 582が有効になり，仮想環境は作成されません．

## PEP 582をグローバルに有効化する

PythonインタプリタにPEP 582パッケージを認識させるには、`pdm/pep582/sitecustomize.py` をPythonライブラリ検索パスに追加する必要があります。

- Linux / macOS
    
    環境変数を変更するコマンドは `pdm --pep582 [<SHELL>]` で出力することができます。
    `<SHELL>` が与えられない場合、PDMはいくつかの推測に基づき選択します。
    `eval "$(pdm --pep582)"` を実行すると、コマンドを実行できます。
    
    シェルの設定ファイル（例：`~/.bash_profile`）に、ログイン時に有効になるような行を書くとよいでしょう。例えば、bashでは次のようにします：
    
    ```bash
    $ pdm --pep582 >> ~/.bash_profile
    ```
    
    繰り返しますが、有効にするためにはシェルを再起動することを忘れないでください。
    
    ```bash
    $ exec $SHELL -l
    ```
    
- Windows
`pdm --pep582` を実行するだけで、環境変数が自動的に変更されます。このとき、ターミナルセッションを再起動することを忘れないでください。
    
    ```powershell
    $ . $profile
    ```
    
    あるいは
    
    ```powershell
    Invoke-Command { & "powershell.exe" } -NoNewScope # PowerShell 5
    Invoke-Command { & "pwsh.exe"       } -NoNewScope # PowerShell 7
    ```
    

> **どのように実装されているのでしょうか？**
Pythonの起動時にサイトパッケージが読み込まれるおかげです。PDMに同梱されている`sitecustomize.py` を実行することで、`sys.path` にパッチを当てることが可能です。インタプリタは最も近い`__pypackage__`ディレクトリを探し、`sys.path` 変数にそれを追加することで実現していきます。
> 

## PEP 582をサポートするためにIDEを設定

現在、ほとんどのIDEにはPEP 582のサポートやプラグインが組み込まれていないので、ツールを手動で設定する必要があります。

### PyCharmの場合

`__pypackages__/<major.minor>/lib`を`Sources Root` としてマークします。そして、Pythonインタプリタとして、同じ<major.minor>バージョンのPythonを選択します。

また、環境からツール（例：pytest）を使用したい場合は、対応するrun/debug設定のPATH変数に`__pypackages__/<major.minor>/bin`ディレクトリを追加する必要があります。

### VSCodeの場合

`.vscode/settings.json` のトップレベルに以下の2つのエントリを追加します：

```json
{
  "python.autoComplete.extraPaths": ["__pypackages__/<major.minor>/lib"],
  "python.analysis.extraPaths": ["__pypackages__/<major.minor>/lib"]
}
```

このファイルは、プラグイン [pdm-vscode](https://github.com/frostming/pdm-vscode) で自動生成することができます。

PEP582をグローバルに有効にして、VSCodeがPEP582を有効にしたのと同じユーザーとシェルを使って実行されていることを確認します。

**PEP582をグローバルに有効化できないのですか？**

何らかの理由でPEP582をグローバルに有効にできない場合でも、各プロジェクトの「起動」ごとに設定することができます：起動の設定で環境変数 `PYTHONPATH` を `.vscode/launch.json` に設定してください。例えば、pytestの実行をデバッグする場合：

```json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "pytest",
            "type": "python",
            "request": "launch",
            "module": "pytest",
            "args": ["tests"],
            "justMyCode": false,
            "env": {"PYTHONPATH": "__pypackages__/<major.minor>/lib"}
        }
    ]
}
```

パッケージが`src`ディレクトリに存在する場合は、`PYTHONPATH` にも追加してください：

```json
"env": {"PYTHONPATH": "src:__pypackages__/<major.minor>/lib"}
```

**Pylance/Pyrightを使用していますか？**

`python.analysis.diagnosticMode` を設定した場合： `workspace`を設定した結果、大量のエラーや警告が表示された場合、workspaceディレクトリに`pyrightconfig.json`を作成し、以下のフィールドを埋める必要があるかもしれません：

```json
{
    "exclude": ["__pypackages__"]
}
```

その後、言語サーバーやVS Codeを再起動すればOKです。
今後（[microsoft/pylance-release#1150](https://github.com/microsoft/pylance-release/issues/1150)）、もしかしたらこの問題は解決されるかもしれません。

**Jupyter Notebookを使用する場合**

pdmを使ってjupyter notebookをインストールし、python拡張と合わせてvscodeで使用したい場合：

`pdm add notebook` などを使ってnotebookをインストールします。
プロジェクトディレクトリの中に、以下のような内容の `.env` ファイルを追加してください：

```bash
PYTHONPATH=/your-workspace-path/__pypackages__/<major>.<minor>/lib
```

それでもうまくいかない場合は、Notebookの起動時に環境変数が正しくロードされていないことが原因である可能性が高いです。回避策は2つあります。

- ターミナルで `code` を実行する。
これにより、パスが正しく設定されたカレントディレクトリに新しいVSCodeウィンドウが開かれます。
- 新しいウィンドウでJupyter Notebookを使用する
新しいウィンドウを開きたくない場合は、Jupyter Notebookの冒頭で以下を実行し、パスを明示的に設定します：
    
    ```python
    import sys
    sys.path.append('/your-workspace-path/__pypackages__/<major>.<minor>/lib')
    ```
    

**PDMタスクプロバイダ**

また、[VSCode Task Provider](https://marketplace.visualstudio.com/items?itemName=knowsuchagency.pdm-task-provider)エクステンションもダウンロード可能です。

これにより、VSCodeはpdmスクリプトを自動的に検出し、VSCodeタスクとしてネイティブに実行することができるようになります。

### neovim の場合

[neovim-lsp](https://github.com/neovim/nvim-lspconfig)を[pyright](https://github.com/Microsoft/pyright)で使用していて、`__pypackages__`ディレクトリをパスに追加したい場合は、プロジェクトの `pyproject.toml` に次のように追加します。

```toml
[tool.pyright]
extraPaths = ["__pypackages__/<major.minor>/lib/"]
```

### Emacs の場合

いくつかのオプションがありますが、基本的にはLSPクライアントが参照するパスに`__pypackages__`を追加するように指示することになるでしょう。以下は、利用可能ないくつかのオプションです：

- `pyproject.toml`とpyrightを使用する。
あなたのプロジェクトの `pyproject.toml` に以下を追加してください：
    
    ```toml
    [tool.pyright]
    extraPaths = ["__pypackages__/<major.minor>/lib/"]
    ```
    
- eglot + pyright
pyrightとeglot（Emacs 29に含まれる）を使って、以下を設定に追加します：
    
    ```lisp
    (defun get-pdm-packages-path ()
      "For the current PDM project, find the path to the packages."
      (let ((packages-path (string-trim (shell-command-to-string "pdm info --packages"))))
        (concat packages-path "/lib")))
    
    (defun my/eglot-workspace-config (server)
      "For the current PDM project, dynamically generate a python lsp config."
      `(:python\.analysis (:extraPaths ,(vector (get-pdm-packages-path)))))
    
    (setq-default eglot-workspace-configuration #'my/eglot-workspace-config)
    ```
    
    pyrightはグローバルに、またはプロジェクトに（おそらく開発依存関係として）インストールする必要があります。これを追加するには、例えば次のようにします：
    
    ```bash
    $ pdm add --dev --group devel pyright
    ```
    
- LSPモード＋lsp-python-ms
以下は、EmacsでPDMをlsp-python-msで動作させる方法を示すサンプルコードスニペットです。寄稿者は @linw1995 です。
    
    ```lisp
    ;; TODO: Cache result
      (defun linw1995/pdm-get-python-executable (&optional dir)
        (let ((pdm-get-python-cmd "pdm info --python"))
          (string-trim
           (shell-command-to-string
            (if dir
                (concat "cd "
                        dir
                        " && "
                        pdm-get-python-cmd)
              pdm-get-python-cmd)))))
    
      (defun linw1995/pdm-get-packages-path (&optional dir)
        (let ((pdm-get-packages-cmd "pdm info --packages"))
          (concat (string-trim
                   (shell-command-to-string
                    (if dir
                        (concat "cd "
                                dir
                                " && "
                                pdm-get-packages-cmd)
                      pdm-get-packages-cmd)))
                  "/lib")))
    
      (use-package lsp-python-ms
        :ensure t
        :init (setq lsp-python-ms-auto-install-server t)
        :hook (python-mode
               . (lambda ()
                   (setq lsp-python-ms-python-executable (linw1995/pdm-get-python-executable))
                   (setq lsp-python-ms-extra-paths (vector (linw1995/pdm-get-packages-path)))
                   (require 'lsp-python-ms)
                   (lsp))))  ; or lsp-deferred
    ```
    

# PEP 621 メタデータ

プロジェクトのメタデータは、`pyproject.toml` に格納されています。仕様は[PEP 621](https://www.python.org/dev/peps/pep-0621/)、[PEP 631](https://www.python.org/dev/peps/pep-0631/)、[PEP 639](https://www.python.org/dev/peps/pep-0639/)で定義されています。詳細な仕様は各PEPをお読みください。

本書の以下の部分では、メタデータは、明示的に与えられていない場合は、`[project]`テーブルの下に記述するものとします。

## 複数行の記述

TOMLは複数行の文字列をサポートしているため、長い説明を複数行に分割して記述することができます。ただ、新しい行をエスケープすることを忘れないでください。そうすれば、最終的な説明は[パッケージのメタデータの中で1行にのみ表示](https://packaging.python.org/specifications/core-metadata/#summary)されます。新しい行をエスケープすると、インデントも削除されます：

```toml
description = """\
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
    Ut enim ad minim veniam, quis nostrud exercitation ullamco \
    laboris nisi ut aliquip ex ea commodo consequat.\
"""
```

文字列に関する[TOMLの仕様](https://toml.io/en/v1.0.0#string)を参照してください。

## パッケージバージョン

- 静的に設定
    
    ```toml
    [project]
    version = "1.0.0"
    ```
    
- 動的に設定
    
    ```toml
    [project]
    ...
    dynamic = ["version"]
    
    [tool.pdm]
    version = { source = "file", path = "mypackage/__version__.py" }
    ```
    

バージョンは、`mypackage/**version**.py`ファイルから  `version = "{version}"`のパターンを検索して読み込まれます。

ダイナミック・バージョニングの他の設定についての詳細はこちらをご覧ください。

## 依存関係の指定

`project.dependencies` は、[PEP 440](https://www.python.org/dev/peps/pep-0440/) および [PEP 508](https://www.python.org/dev/peps/pep-0508/) に従った依存関係の指定文字列の配列です。

例

```toml
[project]
...
dependencies = [
    # 依存関係のパッケージ名
    "requests",
    # 依存関係のパッケージ名とバージョンを指定
    "flask >= 1.1.0",
    # 環境マーカを持つ要件
    "pywin32; sys_platform == 'win32'",
    # 依存関係のURL
    "pip @ git+https://github.com/pypa/pip.git@20.3.1"
]
```

## オプションの依存関係

`setuptools` の `extras_require`　パラメータと同様に、いくつかの要件をオプションとして設定することができます。

```toml
[project.optional-dependencies]
socks = [ 'PySocks >= 1.5.6, != 1.5.7, < 2' ]
tests = [
  'ddt >= 1.2.2, < 2',
  'pytest < 6',
  'mock >= 1.0.1, < 4; python_version < "3.4"',
]
```

オプションの依存関係をまとめてインストールする場合：

```bash
pdm install -G socks
```

`-G` オプションは、複数のグループを含めるために複数回指定することができます。

## コンテキスト変数の展開

使用しているビルドバックエンドに応じて、PDMは依存関係の文字列のいくつかの変数を展開します。

### 環境変数

- **pdm-pep517**
    
    ```toml
    [project]
    dependencies = ["flask @ https://${USERNAME}:${PASSWORD}/artifacts.io/Flask-1.1.2.tar.gz"]
    ```
    
- **hatchling**
    
    ```toml
    [project]
    dependencies = ["flask @ https://{env:USERNAME}:{env:PASSWORD}/artifacts.io/Flask-1.1.2.tar.gz"]
    ```
    
    [hatchling のサンプル](https://hatch.pypa.io/dev/config/context/#environment-variables)も参照してください。
    

環境変数は必要なときに展開され、ロックファイルにはそのまま保存されるので、クレデンシャルの漏洩を心配する必要はありません。

### 相対パス

相対パスからパッケージを追加すると、PDMは自動的にpdm-pep517とhatchlingのための相対パスとして保存します。

例えば、`pdm add ./my-package` を実行すると、`pyproject.toml` に以下のような行ができます。

- **pdm-pep517**
    
    ```toml
    [project]
    dependencies = ["my-package @ file:///${PROJECT_ROOT}/my-package"]
    ```
    
- **hatchling**
    
    ```toml
    [project]
    dependencies = ["my-package @ {root:uri}/my-package"]
    ```
    

デフォルトでは、hatchlingは依存関係の文字列での直接参照をサポートしていませんので、`pyproject.toml`でオンにする必要があります：

```toml
[tool.hatch.metadata]
allow-direct-references = true
```

相対パスは、インストール時やロック時にプロジェクトルートを基準に展開されます。

## コンソールスクリプト

コンソールスクリプトは次のように定義します：

```toml
[project.scripts]
mycli = "mycli.__main__:main"
```

これは、setuptoolsスタイルに変換されます：

```python
entry_points = {
    'console_scripts': [
        'mycli=mycli.__main__:main'
    ]
}
```

また、`[project.gui-scripts]` は、setuptools スタイルの `gui_scripts` エントリーポイントグループに変換される予定です。

### エントリーポイント

その他のエントリーポイントの種類は、`[project.scripts]` と同じ形式で、`[project.entry-points.<type>]` セクションで与えられます：

```toml
[project.entry-points.pytest11]
myplugin = "mypackage.plugin:pytest_plugin"
```

エントリーポイント名にドットなどの特殊文字が含まれる場合は、引用符で囲んでください：

```toml
[project.entry-points."flake8.extension"]
myplugin = "mypackage.plugin:flake8_plugin"
```

# PDMの設定

## カラーテーマ

PDMで使用されるデフォルトのテーマは以下の通りです：

| KEY | デフォルトスタイル |
| --- | --- |
| primary | $\color{cyan}{cyan}$  |
| success | $\color{green}{green}$ |
| warning | $\color{yellow}{yellow}$ |
| error | $\color{red}{red}$ |
| info | $\color{blue}{blue}$ |
| req | $\color{green}{\textbf{bold green}}$ |

`pdm config` コマンドでテーマカラーを変更することができます。例えば、デフォルトの色を$\color{magenta}{magenta}$に変更する場合：

```bash
pdm config theme.primary magenta
```

あるいは、16進表記で指定することもできます。

```bash
pdm config theme.success '#51c7bd'
```

## 利用可能な設定項目

`pdm config` コマンドで取得・変更できる設定項目は以下の通りです。

- `build_isolation`
ビルド環境をプロジェクト環境から分離する
デフォルト： True
プロジェクトで利用： No
環境変数： `PDM_BUILD_ISOLATION`
- `cache_dir`
キャッシュされたファイルのルートディレクトリ
デフォルト： OSのデフォルトのキャッシュの場所
プロジェクトで利用： No
- `check_update`
新しいバージョンがあるかどうか確認する
デフォルト： True
プロジェクトで利用： No
- `global_project.fallback`
ローカルプロジェクトが見つからない場合、暗黙のうちにグローバルプロジェクトを使用する
デフォルト： False
プロジェクトで利用： No
- `global_project.fallback_verbose`
True の場合、グローバルプロジェクトが暗黙のうちに使用されている場合にメッセージを表示する
デフォルト： True
プロジェクトで利用： No
- `global_project.path`
グローバルプロジェクトへのパス
デフォルト： `<OS上のデフォルトの設定場所>/global-project`
プロジェクトで利用： No
- `global_project.user_site`
ユーザーサイトへのインストールの可否
デフォルト： True
プロジェクトで利用： No
- `install.cache` 
ホイールインストール時のキャッシュを有効にする
デフォルト： False
プロジェクトで利用： Yes
- `install.cache_method` 
キャッシュへのリンクの作成方法を指定する
指定可能な値： `symlink` , `pth` 
デフォルト：`symlink` 
プロジェクトで利用： Yes
- `install.parallel` 
インストールとアンインストールを並行して行うかどうか 
デフォルト：True 
プロジェクトで利用： Yes 
環境変数： `PDM_PARALLEL_INSTALL`
- `project_max_depth` 
親からプロジェクトを検索する最大深度 
デフォルト：`5` 
プロジェクトで利用： No 
環境変数： `PDM_PROJECT_MAX_DEPTH`
- `python.use_pyenv` 
pyenv インタプリタを使用する 
デフォルト：True 
プロジェクトで利用： Yes
- `python.use_venv` 
利用可能な場合に仮想環境を使用する 
デフォルト：True 
プロジェクトで利用： Yes 
環境変数： `PDM_USE_VENV`
- `pypi.url` 
PyPI ミラーの URL
デフォルト： `https://pypi.org/simple` 
プロジェクトで利用： Yes 
環境変数： `PDM_PYPI_URL`
- `pypi.username` 
PyPIにアクセスするためのユーザー名 
デフォルト：
プロジェクトで利用： Yes 
環境変数： `PDM_PYPI_USERNAME`
- `pypi.password` 
PyPIにアクセスするためのパスワード 
デフォルト：
プロジェクトで利用： Yes 
環境変数： `PDM_PYPI_PASSWORD`
- `pypi.ignore_stored_index` 
設定されているインデックスを無視する 
デフォルト：False 
プロジェクトで利用： Yes 
環境変数： `PDM_IGNORE_STORED_INDEX`
- `pypi.ca_certs` 
PEM エンコードされた CA 証明書バンドルへのパス（サーバ証明書の検証に使用） 
デフォルト：certifi からの CA 証明書 
プロジェクトで利用： No.
- `pypi.client_cert` 
PEM エンコードされたクライアント証明書とオプションの鍵へのパス。
- `pypi.client_key` 
pypi.client_cert にない場合、PEM エンコードされたクライアント証明書の秘密鍵へのパス 
デフォルト：
プロジェクトで利用： No.
- `pypi.verify_ssl` 
PyPIに問い合わせるときにSSL証明書を検証する 
デフォルト：True 
プロジェクトで利用： Yes
- `pypi.json_api` 
パッケージのメタデータを PyPI の JSON API に問い合わせる 
デフォルト：False 
プロジェクトで利用： Yes 
環境変数： `PDM_PYPI_JSON_API`
- `strategy.save` 
パッケージが追加されたときにバージョンを保存する方法を指定する 
指定可能な値： `exact` , `wildcard` , `minimum` , `compatible`
デフォルト：`minimum`
プロジェクトで利用： Yes
- `strategy.update` 
パッケージを更新する際のデフォルトの戦略 
指定可能な値： `reuse` , `eager`
デフォルト：`reuse`
プロジェクトで利用： Yes
- `strategy.resolve_max_rounds` 
解決処理の最大ラウンド数を指定する 
デフォルト：`10000` 
プロジェクトで利用： Yes 
環境変数： `PDM_RESOLVE_MAX_ROUNDS`
- `venv.location` 
仮想環境の親ディレクトリ 
デフォルト：`<OS のデフォルトのデータ置き場>/venvs` 
プロジェクトで利用： No
- `venv.backend` 
仮想環境を作成するためのデフォルトのバックエンド 
指定可能な値： `virtualenv` , `venv` , `conda`
デフォルト：`virtualenv`
プロジェクトで利用： Yes
環境変数： `PDM_VENV_BACKEND`
- `venv.prompt` 
仮想環境がアクティブなときにプロンプトに表示される書式付き文字列 
デフォルト：`{project_name}-{python_version}` 
プロジェクトで利用： Yes 
環境変数： `PDM_VENV_PROMPT`
- `venv.in_project` 
プロジェクトルート下の `.venv` に仮想環境を作成する 
デフォルト：False 
プロジェクトで利用： Yes 
環境変数： `PDM_VENV_IN_PROJECT`
- `venv.with_pip` 
新しい 仮想環境を作成するときに pip をインストールする 
デフォルト：False 
プロジェクトで利用： Yes 
環境変数： `PDM_VENV_WITH_PIP`

> 備考：
対応する環境変数が設定されている場合、その値は設定ファイルに保存されているものよりも優先されます。
>

# ビルド設定

pdmは、[PEP517](https://www.python.org/dev/peps/pep-0517/)を使用してパッケージをビルドします。これは、パッケージをビルドするためにビルドバックエンドを呼び出すビルドフロントエンドとして機能します。

ビルドバックエンドとは、任意のソースツリーからソース配布やホイールをビルドするためにビルドシステムを動かすものです。

`pdm init` を実行すると、PDMは使用するビルドバックエンドを選択できるようになります。他のパッケージマネージャとは異なり、PDMは特定のビルドバックエンドを使うことを強要しません。好きなものを選ぶことができます。以下は、PDMが初期にサポートするビルドバックエンドとそれに対応する`pyproject.toml` の設定方法です：

- **pdm-backend**
    
    ```toml
    [build-system]
    requires = ["pdm-backend"]
    build-backend = "pdm.backend"
    ```
    
    プロジェクト：　[PDM-Backend](https://pdm-backend.fming.dev/)
    
- **setuptools**
    
    ```toml
    [build-system]
    requires = ["setuptools", "wheel"]
    build-backend = "setuptools.build_meta"
    ```
    
    プロジェクト：　[setuptools 67.7.2.post20230511 documentation](https://setuptools.pypa.io/)
    
- **flit**
    
    ```toml
    [build-system]
    requires = ["flit_core >=3.2,<4"]
    build-backend = "flit_core.buildapi"
    ```
    
    プロジェクト：　[Flit 3.9.0 — Flit 3.9.0 documentation](https://flit.pypa.io/en/stable/)
    
- **hatchling**
    
    ```toml
    [build-system]
    requires = ["hatchling"]
    build-backend = "hatchling.build"
    ```
    
    プロジェクト：　[Hatch](https://hatch.pypa.io/latest/)
    
- **pdm-pep517(非推奨)**
このバックエンドは非推奨です。pdm-backend を使用するようにしてください。
    
    ```toml
    [build-system]
    requires = ["pdm-pep517"]
    build-backend = "pdm.pep517.api"
    ```
    
    プロジェクト：　[pdm-pep517](https://pypi.org/project/pdm-pep517/)
    

上記以外のバックエンドでも、PEP 621をサポートしているバックエンドであれば使用可能ですが、poetry-core はPEP 621のメタデータの読み取りに対応していないため、サポート対象外です。

> **注意**：
上記のリストにないカスタムビルドバックエンドを使用している場合、PDMは相対パスをPDMスタイル(変数 ${PROJECT_ROOT} )として扱います。
> 

# ドキュメント

## pdm 公式ドキュメント

[Introduction - PDM](https://pdm.fming.dev/latest/)

## pdm のヘルプメッセージ

```bash
% pdm --help
Usage: pdm [-h] [-V] [-c CONFIG] [-v] [-I] [--pep582 [SHELL]]
           {add,build,cache,completion,config,export,fix,import,info,init,install,list,lock,publish,remove,run,search,self,plugin,show,sync,update,use,venv}
           ...

    ____  ____  __  ___
   / __ \/ __ \/  |/  /
  / /_/ / / / / /|_/ /
 / ____/ /_/ / /  / /
/_/   /_____/_/  /_/

Commands:
  {add,build,cache,completion,config,export,fix,import,info,init,install,list,lock,publish,remove,run,search,self,plugin,show,sync,update,use,venv}
    add                 Add package(s) to pyproject.toml and install them
    build               Build artifacts for distribution
    cache               Control the caches of PDM
    completion          Generate completion scripts for the given shell
    config              Display the current configuration
    export              Export the locked packages set to other formats
    fix                 Fix the project problems according to the latest
                        version of PDM
    import              Import project metadata from other formats
    info                Show the project information
    init                Initialize a pyproject.toml for PDM
    install             Install dependencies from lock file
    list                List packages installed in the current working set
    lock                Resolve and lock dependencies
    publish             Build and publish the project to PyPI
    remove              Remove packages from pyproject.toml
    run                 Run commands or scripts with local packages loaded
    search              Search for PyPI packages
    self (plugin)       Manage the PDM program itself (previously known as
                        plugin)
    show                Show the package information
    sync                Synchronize the current working set with lock file
    update              Update package(s) in pyproject.toml
    use                 Use the given python version or path as base
                        interpreter
    venv                Virtualenv management

Options:
  -h, --help            Show this help message and exit.
  -V, --version         Show the version and exit
  -c CONFIG, --config CONFIG
                        Specify another config file path [env var:
                        PDM_CONFIG_FILE]
  -v, --verbose         Use `-v` for detailed output and `-vv` for more
                        detailed
  -I, --ignore-python   Ignore the Python path saved in .pdm-python. [env var:
                        PDM_IGNORE_SAVED_PYTHON]
  --pep582 [SHELL]      Print the command line to be eval'd by the shell
```

# pdm のコマンド詳細

## `add` コマンド

`pyproject.toml` にパッケージを追加し、インストールする

```
pdm add [-h] [-v] [-g] [-p PROJECT_PATH] [-L LOCKFILE]
        [--save-compatible | --save-wildcard | --save-exact | --save-minimum]
        [--update-reuse | --update-eager | --update-all] [--pre] [-u]
        [-e EDITABLES] [--no-editable] [--no-self] [--fail-fast]
        [--no-isolation] [--dry-run] [--venv [NAME]] [-k SKIP] [-d]
        [-G GROUP] [--no-sync]
        [packages ...]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する。
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-L LOCKFILE` , `--lockfile LOCKFILE`
別のロックファイル・パスを指定する
環境変数： `PDM_LOCKFILE` 
デフォルト：  `pdm.lock`
- `--save-compatible` 
互換性のあるバージョン指定子を保存する
- `--save-wildcard` 
ワイルドカードバージョン指定子を保存する
- `--save-exact` 
正確なバージョン指定子を保存する
- `--save-minimum` 
最小バージョン指定子を保存する
- `--update-reuse` 
可能であればロックファイル内に既に存在する固定バージョンを再利用する
- `--update-eager` 
パッケージとその依存関係を再帰的に更新しようとする
- `--update-all` 
すべての依存関係およびサブ依存関係を更新する
- `--pre` , `--prerelease` 
プレリリースを固定バージョンにすることを許可する
- `-u` , `--unconstrained` 
パッケージのバージョン制約を無視する
- `--dry-run` 
差分のみを表示し、何も実行しない
- `--venv [NAME]` 
指定したキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `-d` , `--dev` 
パッケージをdev依存に追加する
- `-G GROUP` , `--group GROUP`
追加する対象の依存グループを指定する
- `--no-sync`
`pyproject.toml` の書き込みのみ行い、作業セットを同期させない

**インストールオプション**

- `--no-editable` 
すべてのパッケージについて、編集不可のバージョンをインストールする
- `--no-self` 
プロジェクト自体をインストールしない
環境変数：  `PDM_NO_SELF`
- `-x` , `--fail-fast` 
最初のインストールでエラーが発生した場合に中止する
- `---no-isolation` 
クリーンな環境でのビルドを隔離しない

**引数**

- `-e EDITABLES` , `--editable EDITABLES`
編集可能なパッケージを指定する
- `packages`
パッケージを指定する

## `build` コマンド

配布用のアーティファクトをビルドする

```
pdm build [-h] [-v] [-p PROJECT_PATH] [--no-isolation] [-k SKIP]
          [--no-sdist] [--no-wheel] [-d DEST] [--no-clean]
          [--config-setting CONFIG_SETTING]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `--no-isolation` 
クリーンな環境でビルドを隔離しない
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `——no-sdist` 
ソースパッケージ（tarball)をビルドしない
- `--no-wheel` 
Wheellパッケージをビルドしない
- `-d DEST`, `--dest DEST` 
アーティファクトを配置するターゲット・ディレクトリ
- `--no-clean` 
ターゲットディレクトリのクリーニングを行わない
- `-C CONFIG_SETTING` , `--config-setting CONFIG_SETTING` 
バックエンドにオプションを渡する
値を持つオプションは"`=`"の後に指定する必要がある
例： `--config-setting=--opt=value`または`-C --opt=value`

## `cache` コマンド

PDMのキャッシュを制御する

```
pdm cache clear [-h] [-v]
pdm cache remove [-h] [-v] pattern
pdm cache list [-h] [-v] [pattern]
pdm cache info [-h] [-v]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する

**サブコマンド**

- `clear`
キャッシュディレクトリ以下のすべてのファイルを削除する
- `remove`
キャッシュディレクトリ以下の指定したパターンにマッチするファイルを削除する
- `list`
キャッシュされているビルドされたWheelパッケージをリストアップする
パターンを指定することができる
- `info`
キャッシュの現在のサイズを表示する

## `completion` コマンド

与えられたシェルの補完スクリプトを生成する

```
pdm completion [-h] [shell]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には -`v` を、より詳細な出力には -`vvv` を使用する。

**引数**

- `shell`
シェルを指定
デフォルト： 環境変数 `SHELL` の値から推定される

## `config` コマンド

現在のコンフィギュレーションを表示する

```
pdm config [-h] [-v] [-g] [-p PROJECT_PATH] [-l] [-d] [key] [value]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-l` , `--local` 
プロジェクトのローカル設定ファイルに設定する
- `-d` , `--delete` 
コンフィギュレーション・キーの設定を解除する

**引数**

- `key`
設定キー
- `value`
設定する値

## `export` コマンド

ロックされたパッケージを他の形式にエクスポートします。

```
pdm export [-h] [-v] [-g] [-p PROJECT_PATH] [-L LOCKFILE]
           [-f {pipfile,poetry,flit,setuppy,requirements}] [-G GROUP]
           [--no-default] [-d | --prod] [--without-hashes] [-o OUTPUT]
           [--pyproject]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-L LOCKFILE` , `--lockfile LOCKFILE`
別のロックファイル・パスを指定する
環境変数： `PDM_LOCKFILE` 
デフォルト：  `pdm.lock`
- `-f EXPORT_FORMAT` , `--format EXPORT_FORMAT`
エクスポートファイルの形式を指定する
指定可能な値： `pipfile` , `poetry` , `flit` , `setuppy` , `requirements`
- `--without-hashes` 
アーティファクトのハッシュを含めない
- `-o OUTPUT` , `--output OUTPUT`
与えられたファイルに出力を書き込む
指定されない場合stdout に出力する
- `--pyproject` 
`pyproject.toml` からパッケージのリストを読み込む

**依存関係指定オプション**

- `-G GROUP` , `--group GROUP`
オプション依存のグループを選択する
カンマ（`,`）で区切って依存関係、ビルド時の依存関係を指定する
複数回指定することがでる
”`:all`” を与えると、すべてのグループを同じ種に含めることがでる
- `--no-default` 
デフォルトグループの依存関係を含めない
- `-d` , `--dev` 
ビルド時（dev)の依存関係を選択する
- `——prod` , `——production` ビルド時（dev)の依存関係を選択しない

## `fix` コマンド

プロジェクトの問題をPDMの最新版に従って修正する。

```
pdm fix [-h] [-v] [-g] [-p PROJECT_PATH] [--dry-run] [problem]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する。
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `--dry-run` 
プロジェクトの問題を表示するだけで、何も実行しない

**引数**

- `problem`
修正する問題を指示する
省略された場合は、すべての問題を修正する

## `import` コマンド

他のフォーマットからプロジェクトのメタデータをインポートする

```
pdm import [-h] [-v] [-g] [-p PROJECT_PATH] [-d] [-G GROUP]
           [-f {pipfile,poetry,flit,setuppy,requirements}]
           filename
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する
`-p` / `--project` でプロジェクトルートを指定
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-d` , `--dev` 
ビルド時（dev)の依存関係を選択する
- `-G GROUP` , `--group GROUP`
ターゲットの依存のグループを選択する
- `-f EXPORT_FORMAT` , `--format EXPORT_FORMAT`
インポートするファイル形式を指定する
指定可能な値： `pipfile` , `poetry` , `flit` , `setuppy` , `requirements`

## `info` コマンド

プロジェクト情報を表示する

```
pdm info [-h] [-v] [-g] [-p PROJECT_PATH] [--venv [NAME]]
         [--python | --where | --packages | --env | --json]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する
`-p` / `--project` でプロジェクトルートを指定
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `--venv [NAME]` 
与えられたキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`
- `--python` 
Pythonインタプリタのパスを表示する
- `--where` 
プロジェクトのルートパスを表示する
- `--packages` 
ローカルパッケージのルートを表示する
- `--env` 
PEP 508の環境マーカを表示する
- `--json` 
情報をJSON形式で出力する

## `init` コマンド

PDM用の `pyproject.tom`l を初期化する。

```
pdm init [-h] [-v] [-g] [-p PROJECT_PATH] [-k SKIP] [-n]
         [--python PYTHON]
         [--backend {pdm-backend,setuptools,flit-core,hatchling,pdm-pep517}]
         [--lib]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する
`-p` / `--project` でプロジェクトルートを指定
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `-n` , `—no-interactive` 
デフォルト値を使用して対話型には処理しない
- `--python  PYTHON`
Pythonインタプリタのパスを表示する
- `—backend BACKEND`
ビルドバックエンドを指定する
指定可能な値： `pdm-backend` , `setuptools` , `flit-core` , `hatchling` , `pdm-pep517`
- `—lib` 
ライブラリプロジェクトを作成する

## `install` コマンド

ロックファイルから依存関係をインストールする

```
pdm install [-h] [-v] [-g] [-p PROJECT_PATH] [-G GROUP] [--no-default]
            [-d | --prod] [--no-editable] [--no-self] [--fail-fast]
            [--no-isolation] [--dry-run] [-L LOCKFILE] [-k SKIP]
            [--venv [NAME]] [--no-lock] [--check] [--plugins]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `--dry-run` 
プロジェクトの問題を表示するだけで、何も実行しない
- `-L LOCKFILE` , `--lockfile LOCKFILE`
別のロックファイル・パスを指定する
環境変数： `PDM_LOCKFILE` 
デフォルト：  `pdm.lock`
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `--venv [NAME]` 
与えられたキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`
- `--no-lock` 
ロックファイルが見つからないか、古い場合はロックを行わない
- `--check` 
ロックファイルが最新かどうかをチェックし、そうでない場合は失敗する
- `--plugins` 
`pyproject.toml` で指定されたプラグインをインストールする

**依存関係指定オプション**

- `-G GROUP` , `--group GROUP`
オプション依存のグループを選択する
カンマ（`,`）で区切って依存関係、ビルド時の依存関係を指定する
複数回指定することがでる
”`:all`” を与えると、すべてのグループを同じ種に含めることがでる
- `--no-default` 
デフォルトグループの依存関係を含めない
- `-d` , `--dev` 
ビルド時（dev)の依存関係を選択する
- `——prod` , `——production` ビルド時（dev)の依存関係を選択しない

**インストールオプション**

- `--no-editable` 
すべてのパッケージについて、編集不可のバージョンをインストールする
- `--no-self` 
プロジェクト自体をインストールしない
環境変数：  `PDM_NO_SELF`
- `-x` , `--fail-fast` 
最初のインストールでエラーが発生した場合に中止する
- `---no-isolation` 
クリーンな環境でのビルドを隔離しない

## `list` コマンド

現在の作業セットにインストールされているパッケージの一覧を表示する

```
pdm list [-h] [-v] [-g] [-p PROJECT_PATH] [--venv [NAME]] [--freeze]
         [--graph] [-r] [--resolve] [--fields FIELDS] [--sort SORT]
         [--csv | --json | --markdown] [--include INCLUDE]
         [--exclude EXCLUDE]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `--venv [NAME]` 
指定したキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`
- `--freeze` 
インストールされている依存関係をpipの r`equirements.txt` 形式で表示する
- `--graph` 依存関係のグラフを表示する
- `-r` , `--reverse` 
依存関係グラフを反転させる
- `--resolve` 
現在インストールされているものだけを表示するのではなく、すべての要件を解決してライセンスを出力する
- `--fields FIELDS` 
出力する情報をカンマ区切りの文字列として選択する
例： `—fields name,version,homepage,licenses,groups`
- `--sort SORT` 
与えられたフィールド名を用いて出力をソートする
何も設定されていない場合は、ソートは適用されない
複数のフィールドをカンマ（`,`）で結合することができる
- `--csv` 
依存関係をCSV形式で出力する
- `--json` 
依存関係をJSON形式で出力する
`--markdown` 
依存関係と法的告知をマークダウンで出力する
ベストエフォートベース
- `--include INCLUDE` 
出力に含める依存関係グループを指定する
デフォルト： すべての依存グループが含まれる
- `--exclude EXCLUDE` 
出力から依存関係グループを除外する

## `lock` コマンド

依存関係を解決してロックする

```
pdm lock [-h] [-v] [-g] [-p PROJECT_PATH] [-L LOCKFILE] [--no-isolation]
         [-k SKIP] [-G GROUP] [--no-default] [-d | --prod] [--refresh]
         [--check] [--no-cross-platform]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-L LOCKFILE` , `--lockfile LOCKFILE`
別のロックファイル・パスを指定する
環境変数： `PDM_LOCKFILE` 
デフォルト：  `pdm.lock`
- `--no-isolation` 
クリーンな環境でビルドを隔離しない
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `--refresh` 
固定されたバージョンを更新せず、ロックファイルだけを更新する
- `--check`
ロックファイルが最新かどうかをチェックして終了する
- `--no-cross-platform` 
現在のプラットフォーム用のパッケージのみをロックする

**依存関係指定オプション**

- `-G GROUP` , `--group GROUP`
オプション依存のグループを選択する
カンマ（`,`）で区切って依存関係、ビルド時の依存関係を指定する
複数回指定することがでる
”`:all`” を与えると、すべてのグループを同じ種に含めることがでる
- `--no-default` 
デフォルトグループの依存関係を含めない
- `-d` , `--dev` 
ビルド時（dev)の依存関係を選択する
- `——prod` , `——production` ビルド時（dev)の依存関係を選択しない

## `publish` コマンド

プロジェクトをビルドしてPyPIに公開する。

```
pdm publish [-h] [-v] [-p PROJECT_PATH] [-k SKIP] [-r REPOSITORY]
            [-u USERNAME] [-P PASSWORD] [-S] [-i IDENTITY] [-c COMMENT]
            [--no-build] [--ca-certs CA_CERTS]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `-r REPOSITORY` , `--repository REPOSITORY`
パッケージの公開先となるリポジトリ名またはURLを指定する
環境変数： `PDM_PUBLISH_REPO`
- `-u USERNAME` , `--username USERNAME`
リポジトリにアクセスするためのユーザー名
環境変数： `PDM_PUBLISH_USERNAME`
- `-P PASSWORD` , `--password PASSWORD` 
リポジトリにアクセスするためのパスワード
環境変数：`PDM_PUBLISH_PASSWORD`
- `-S` , `--sign` 
パッケージをPGP署名付きでアップロードする
- `-i IDENTITY` ,  `--identity IDENTITY`
ファイルへの署名に使用するGPGのID
- `-c COMMENT`, `--comment COMMENT`
配布ファイルに含めるコメント
- `--no-build` 
公開前にパッケージをビルドしない
- `——ca-certs CA_CERTS`
 パブリッシュサーバーの検証に使用するPEMエンコードされた認証局バンドルへのパス
環境変数：`PDM_PUBLISH_CA_CERTS`

## `remove` コマンド

`pyproject.toml` からパッケージを削除する。

```
pdm remove [-h] [-v] [-g] [-p PROJECT_PATH] [--no-editable] [--no-self]
           [--fail-fast] [--no-isolation] [--dry-run] [-L LOCKFILE]
           [-k SKIP] [--venv [NAME]] [-d] [-G GROUP] [--no-sync]
           packages [packages ...]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する。
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `--dry-run` 
プロジェクトの問題を表示するだけで、何も実行しない
- `-L LOCKFILE` , `--lockfile LOCKFILE`
別のロックファイル・パスを指定する
環境変数： `PDM_LOCKFILE` 
デフォルト：  `pdm.lock`
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `--venv [NAME]` 
指定したキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`
- `-d` , `--dev` 
ビルド時（dev)の依存関係を選択する
- `-G GROUP` , `--group GROUP`
オプション依存のグループを選択する
カンマ（`,`）で区切って依存関係、ビルド時の依存関係を指定する
複数回指定することがでる
”`:all`” を与えると、すべてのグループを同じ種に含めることがでる
- `--no-sync`
`pyproject.toml` の書き込みのみ行い、作業セットを同期させない

**インストールオプション**

- `--no-editable` 
すべてのパッケージについて、編集不可のバージョンをインストールする
- `--no-self` 
プロジェクト自体をインストールしない
環境変数：  `PDM_NO_SELF`
- `-x` , `--fail-fast` 
最初のインストールでエラーが発生した場合に中止する
- `---no-isolation` 
クリーンな環境でのビルドを隔離しない

**引数**

- `packages` 
削除するパッケージを指定する

## `run` コマンド

ローカルパッケージがロードされた状態でコマンドやスクリプトを実行する

```
pdm run [-h] [-v] [-g] [-p PROJECT_PATH] [-k SKIP] [--venv [NAME]]
        [-l | -j] [-s]
        [script] ...
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する。
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `--venv [NAME]` 
指定したキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`
- `—list`
`pyproject.toml` に定義されている利用可能なスクリプトをすべて表示する
- `--json` 
スクリプト情報をJSON形式で出力する

## `search` コマンド

PyPI パッケージを検索する

```
pdm search [-h] [-v] query
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する

**引数**

- `query` 
検索するクエリ文字列

## `self`コマンド

PDMプログラム自体を管理する（古いバージョンでは plugin )

```
pdm self [-h] [-v] {list,add,remove,update} ...
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する

**サブコマンド**

- `list` 
PDMでインストールされているすべてのパッケージをリストアップする
- `add` 
PDMの環境にパッケージをインストールする
- `remove` 
PDMの環境からパッケージを削除する
- `update` 
PDM自身をアップデートする

## `self list` コマンド

PDMでインストールされているすべてのパッケージをリストアップする

```
pdm self list [-h] [-v] [--plugins]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `—plugins` 
プラグインだけをリストアップする

## `self add`  コマンド

PDMの環境にパッケージをインストールする

```
pdm self add [-h] [-v] [--pip-args PIP_ARGS] packages [packages ...]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `——pip-args PIP_ARGS` 
pip install に渡される引数

**引数**

- `packages` 
1つまたは複数のパッケージ名を指定する
各パッケージはバージョン指定子を持つことができる

## `self remove`  コマンド

PDMの環境からパッケージを削除する

```
pdm self remove [-h] [-v] [--pip-args PIP_ARGS] [-y]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `——pip-args PIP_ARGS` 
pip install に渡される引数
- `-y` , `—yes`
問い合わせに常に yes を回答する

**引数**

- `packages` 
1つまたは複数のパッケージ名を指定する

## `self update`  コマンド

PDM自身をアップデートする

```
pdm self update [-h] [-v] [--head] [--pre] [--pip-args PIP_ARGS]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `--head` 
メインブランチの最新コミットに更新する
- `--pre` 
最新のプレリリースバージョンにアップデートする
- `——pip-args PIP_ARGS` 
pip install に渡される引数

## `show` コマンド

パッケージ情報を表示する

```
pdm show [-h] [-v] [-g] [-p PROJECT_PATH] [--venv [NAME]] [--name]
         [--version] [--summary] [--license] [--platform] [--keywords]
         [package]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する。
- `--venv [NAME]` 
指定したキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`
- `--name` 
名前を表示する
- `--version` 
バージョンを表示する
- `--summary` 
サマリーを表示する
- `--license` 
ライセンスを表示する
- `--platform` 
プラットフォームを表示する
- `--keywords` 
キーワードを表示する

**引数**

- `package` 
パッケージ名を指定する
指定しない場合はこのパッケージを表示する

## `sync` コマンド

現在の作業セットとロックファイルを同期させる

```
pdm sync [-h] [-v] [-g] [-p PROJECT_PATH] [-G GROUP] [--no-default]
         [-d | --prod] [--dry-run] [-L LOCKFILE] [-k SKIP]
         [--clean | --only-keep] [--no-editable] [--no-self]
         [--fail-fast] [--no-isolation] [--venv [NAME]] [-r]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する。
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `--dry-run` 
プロジェクトの問題を表示するだけで、何も実行しない
- `-L LOCKFILE` , `--lockfile LOCKFILE`
別のロックファイル・パスを指定する
環境変数： `PDM_LOCKFILE` 
デフォルト：  `pdm.lock`
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `——clean`
ロックファイルにないパッケージを削除する
- `——only-keep`
選択したパッケージのみを残す
- `--venv [NAME]` 
指定したキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`
- `-r` , `--reinstall` 
既存の依存関係を強制的に再インストールする

**依存関係指定オプション**

- `-G GROUP` , `--group GROUP`
オプション依存のグループを選択する
カンマ（`,`）で区切って依存関係、ビルド時の依存関係を指定する
複数回指定することがでる
”`:all`” を与えると、すべてのグループを同じ種に含めることがでる
- `--no-default` 
デフォルトグループの依存関係を含めない
- `-d` , `--dev` 
ビルド時（dev)の依存関係を選択する
- `——prod` , `——production` ビルド時（dev)の依存関係を選択しない

**インストールオプション**

- `--no-editable` 
すべてのパッケージについて、編集不可のバージョンをインストールする
- `--no-self` 
プロジェクト自体をインストールしない
環境変数：  `PDM_NO_SELF`
- `-x` , `--fail-fast` 
最初のインストールでエラーが発生した場合に中止する
- `---no-isolation` 
クリーンな環境でのビルドを隔離しない

## `update` コマンド

`pyproject.toml` にあるパッケージを更新する

```
pdm update [-h] [-v] [-g] [-p PROJECT_PATH] [-G GROUP] [--no-default]
           [-d | --prod] [--no-editable] [--no-self] [--fail-fast]
           [--no-isolation] [-L LOCKFILE]
           [--save-compatible | --save-wildcard | --save-exact | --save-minimum]
           [--update-reuse | --update-eager | --update-all] [--pre] [-u]
           [-k SKIP] [--venv [NAME]] [-t] [--dry-run] [--no-sync]
           [packages ...]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する。
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-L LOCKFILE` , `--lockfile LOCKFILE`
別のロックファイル・パスを指定する
環境変数： `PDM_LOCKFILE` 
デフォルト：  `pdm.lock`
- `--save-compatible` 
互換性のあるバージョン指定子を保存する
- `--save-wildcard` 
ワイルドカードバージョン指定子を保存する
- `--save-exact` 
正確なバージョン指定子を保存する
- `--save-minimum` 
最小バージョン指定子を保存する
- `--update-reuse` 
可能であればロックファイル内に既に存在する固定バージョンを再利用する
- `--update-eager` 
パッケージとその依存関係を再帰的に更新しようとする
- `--update-all` 
すべての依存関係およびサブ依存関係を更新する
- `--pre` , `--prerelease` 
プレリリースを固定バージョンにすることを許可する
- `-u` , `--unconstrained` 
パッケージのバージョン制約を無視する
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `--venv [NAME]` 
指定したキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`
- `-t` , `--top` 
`pyproject.toml` に記載されているもののみ更新する
- `--dry-run` , `--outdated`
差分のみを表示し、何も実行しない
- `--no-sync`
`pyproject.toml` の書き込みのみ行い、作業セットを同期させない

**依存関係指定オプション**

- `-G GROUP` , `--group GROUP`
オプション依存のグループを選択する
カンマ（`,`）で区切って依存関係、ビルド時の依存関係を指定する
複数回指定することがでる
”`:all`” を与えると、すべてのグループを同じ種に含めることがでる
- `--no-default` 
デフォルトグループの依存関係を含めない
- `-d` , `--dev` 
ビルド時（dev)の依存関係を選択する
- `——prod` , `——production` ビルド時（dev)の依存関係を選択しない

**インストールオプション**

- `--no-editable` 
すべてのパッケージについて、編集不可のバージョンをインストールする
- `--no-self` 
プロジェクト自体をインストールしない
環境変数：  `PDM_NO_SELF`
- `-x` , `--fail-fast` 
最初のインストールでエラーが発生した場合に中止する
- `---no-isolation` 
クリーンな環境でのビルドを隔離しない

**引数**

- `packages` 
1つまたは複数のパッケージ名を指定する
各パッケージはバージョン指定子を持つことができる

## `use` コマンド

与えられたpythonのバージョンまたはパスをベースとして使用する

```
pdm use [-h] [-v] [-g] [-p PROJECT_PATH] [-k SKIP] [-f] [-i]
        [--venv VENV]
        [python]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-g` , `--global` 
グローバルプロジェクトを使用する。
- `-p PROJECT_PATH` , `--project PROJECT_PATH`
プロジェクトルートとして別のパスを指定する
`pyproject.toml` と`__pypackages__` のベースパスを変更する
- `-k SKIP` , `--skip SKIP`
タスクやフックをカンマ区切りでスキップする
複数回指定することができる
"`:all`" を与えると、すべてのフックをスキップする
"`:pre`" と "`:post`" を与えると、すべての `pre` または `post` のフックをスキップする
- `-f` , `--first` 
最初にマッチしたインタプリタを選択する
- `-i` , `--ignore-remembered`
記憶している選択項目を無視する
- `--venv [NAME]` 
指定したキーを持つ仮想環境でコマンドを実行する
環境変数： `PDM_IN_VENV`

## `venv` コマンド

仮想環境の管理

```
pdm venv [-h] [--path PATH | --python PYTHON]
         {create,list,remove,activate,purge} ...
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `——path PATH`
指定した仮想環境で使用されるPATHを表示する
- `--python  PYTHON`
指定した仮想環境で使用されるPythonインタプリタのパスを表示する

**サブコマンド**

- `create` 
仮想環境を作成する
- `list` 
このプロジェクトに関連するすべての 仮想環境をリストアップする
- `remove` 
指定された名前の仮想環境を削除します。
- `activate` 
指定された名前の仮想環境を有効化する
- `purge` 
選択した／作成されたすべての仮想環境を消去する

## `venv create` コマンド

仮想環境を作成する

```
pdm venv create [-h] [-v] [-w {virtualenv,venv,conda}] [-f] [-n NAME]
                [--with-pip]
                [python] ...
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-w BACKEND` , `--with BACKEND`
仮想env を作成するバックエンドを指定する
指定可能な値： `virtualenv` , `venv` , `conda`
- `-f` , `--force` 
仮想環境が既に存在する場合は再作成する
- `-n NAME` , `--name NAME` 
仮想環境の名前を指定する
- `--with-pip` 
仮想環境を作成するときに一緒にpipをインストールする

**引数**

- `python` 
仮想環境を作成する際に使用するpythonを指定する
- `venv_args` 
バックエンドに渡される追加引数を指定する

## `venv list`  コマンド

このプロジェクトに関連するすべての 仮想環境をリストアップする

```
pdm venv list [-h] [-v]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する

## `venv remove`  コマンド

指定された名前の仮想環境を削除します。

```
pdm venv remove [-h] [-v] [-y] env
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-y` , `—yes`
問い合わせに常に yes を回答する

**引数**

- `env` 
仮想環境のキーを指定する

## `venv activate`  コマンド

指定された名前の仮想環境を有効化する

```
pdm venv activate [-h] [-v] [env]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する

**引数**

- `env` 
仮想環境のキーを指定する

## `venv purge`  コマンド

選択した／作成されたすべての仮想環境を消去する

```
pdm venv purge [-h] [-v] [-f] [-i]
```

**オプション**

- `-h` , `—-help` 
ヘルプ情報を表示する
- `-v` , `--verbose` 
詳細な出力には `-v` を、より詳細な出力には `-vvv` を使用する
- `-f` , `--force` 
確認のプロンプトを出さずに強制的に削除する
- `-i` , `--interactive` 
仮想環境を対話的に選択して削除する

# ライセンス

- [**MIT license**](https://github.com/The-Noah/lsfp/blob/master/LICENSE)