Skip to content

Advanced Usage#

Automatic Testing#

Use Tox as the runner#

Toxは、複数のPythonバージョンまたは依存関係セットに対してテストするための優れたツールです。

次のようにtox.iniを設定して、テストをPDMと統合できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[tox]
env_list = py{36,37,38},lint

[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によって作成されたvirtualenvを使用するには、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 lockファイルが予期せず変更されます。deps構成で追加の依存関係を指定できます。さらに、PDMを正しく動作させるために、isolated_buildおよびpassenv構成を上記の例のように設定する必要があります。

To get rid of these constraints, there is a Tox plugin tox-pdm which can ease the usage. You can install it by

これらの制約を取り除くために、Toxプラグインtox-pdmがあり、使用を容易にすることができます。

1
pip install tox-pdm

または

1
pdm add --dev tox-pdm

次のようにしてtox.iniをさらに整理することができます。:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[tox]
env_list = py{36,37,38},lint

[testenv]
groups = dev
commands =
    pytest tests

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

See the project's README for a detailed guidance.

詳細なガイダンスについては、project's READMEを参照してください。

Use Nox as the runner#

Noxは、自動テストのためのもう1つの優れたツールです。toxとは異なり、Noxは構成に標準のPythonファイルを使用します。

NoxでPDMを使用する方がはるかに簡単です。次にnoxfile.pyの例を示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import os
import nox

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

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

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

PDMがvirtualenv内のPythonを正しく取得できるように、PDM_IGNORE_SAVED_PYTHONを設定する必要があります。また、pdmPATH内で使用可能であることも確認してください。

noxを実行する前に、venvの再利用を有効にするために、構成項目python.use_venvがtrueであることも確認する必要があります。

About PEP 582 __pypackages__ directory#

デフォルトでは、pdm runでツールを実行すると、__pypackages__がプログラムとそれによって作成されたすべてのサブプロセスに表示されます。これは、これらのツールによって作成された仮想環境も__pypackages__内のパッケージを認識することを意味し、場合によっては予期しない動作を引き起こします。

noxの場合、noxfile.pyに次の行を追加することでこれを回避できます。

1
os.environ.pop("PYTHONPATH", None)

toxでは、PYTHONPATHはテストセッションに渡されないので、これは問題になりません。さらに、noxtoxを独自のpipx環境に置くことをお勧めします。そうすれば、すべてのプロジェクトにインストールする必要がなくなります。この場合、PEP 582パッケージも問題になりません。

Use PDM in Continuous Integration#

PDMはPython 3.7より前のバージョンにはインストールできないので、これらのPythonバージョンでプロジェクトをテストする場合は

PDMが正しいPythonバージョンにインストールされていることを確認する必要があります。このバージョンは、特定のジョブ/タスクが実行されるターゲットPythonバージョンとは異なる場合があります。

幸いなことに、GitHub Actionを使用している場合は、このプロセスを簡単にするためにpdm-project/setup-pdmがあります。

これはGitHub Actionsのワークフローの例ですが、他のCIプラットフォームにも適用できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
Testing:
  runs-on: ${{ matrix.os }}
  strategy:
    matrix:
      python-version: [3.7, 3.8, 3.9, '3.10', '3.11']
      os: [ubuntu-latest, macOS-latest, windows-latest]

  steps:
    - uses: actions/checkout@v3
    - name: Set up PDM
      uses: pdm-project/setup-pdm@v3
      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仮想環境にknown compatibility issueがあります。そのマシンでPDMパラレルインストールが失敗した場合は、parallel_installfalseに設定するか、env LD_PRELOAD=/lib/x86_64-linux-gnu/libgcc_s.so.1を設定する必要があります。これはすでにpdm-project/setup-pdmアクションによって処理されています。

Note

適切なユーザーセットを使用せずにCIスクリプトを実行すると、PDMがキャッシュディレクトリを作成しようとしたときにパーミッションエラーが発生する可能性があります。この問題を回避するには、HOME環境変数を書き込み可能なディレクトリに設定します。例:

1
export HOME=/tmp/home

Use PDM in a multi-stage Dockerfile#

マルチステージDockerfileでPDMを使用して、まずプロジェクトと依存関係を__pypackages__にインストールし、次にこのフォルダを最終ステージにコピーしてPYTHONPATHに追加することができます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ARG PYTHON_BASE=3.10-slim
# build stage
FROM python:$PYTHON_BASE AS builder

# install PDM
RUN pip install -U pdm
# disable update check
ENV PDM_CHECK_UPDATE=false
# copy files
COPY pyproject.toml pdm.lock README.md /project/
COPY src/ /project/src

# install dependencies and project into the local packages directory
WORKDIR /project
RUN pdm install --check --prod --no-editable

# run stage
FROM python:$PYTHON_BASE

# retrieve packages from build stage
COPY --from=builder /project/.venv/ /project/.venv
ENV PATH="/project/.venv/bin:$PATH"
# set command/entrypoint, adapt to fit your needs
COPY src /project/src
CMD ["python", "src/__main__.py"]

Use PDM to manage a monorepo#

PDMを使用すると、1つのプロジェクト内に複数のサブパッケージを作成できます。各サブパッケージには独自のpyproject.tomlファイルがあります。また、すべての依存関係をロックするpdm.lockファイルを1つだけ作成できます。サブパッケージは、相互に依存関係を持つことができます。これを行うには、次の手順に従います。

project/pyproject.toml:

1
2
3
4
5
6
[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:

1
2
[project]
dependencies = ["foo-core"]

packages/foo-app/pyproject.toml:

1
2
[project]
dependencies = ["foo-core"]

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

詳細については、🚀 Example repositoryを参照してください。

Hooks for pre-commit#

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

Export requirements.txt#

このフックは、有効な引数とともにコマンドpdm exportをラップします。これをフック(CIなど)として使用して、pdm lockの実際の内容を反映したrequirements.txtをコードベースにチェックインすることを確認できます。

1
2
3
4
5
6
7
8
# 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$

Check pdm.lock is up to date with pyproject.toml#

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

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

Sync current working set with pdm.lock#

このフックは、有効な引数とともにコマンドpdm syncをラップします。分岐をチェックアウトまたはマージするたびに、現在の作業セットがpdm.lockと同期されるようにするフックとして使用できます。システムの認証情報ストアを使用する場合は、additional_dependencieskeyringを追加してください。

1
2
3
4
5
6
- repo: https://github.com/pdm-project/pdm
  rev: 2.x.y # a PDM release exposing the hook
  hooks:
    - id: pdm-sync
      additional_dependencies:
        - keyring