pax_global_header00006660000000000000000000000064152707713300014517gustar00rootroot0000000000000052 comment=86bab32d69f9447140672662f87a72377b4670fa pdm-2.29.5/000077500000000000000000000000001527077133000123765ustar00rootroot00000000000000pdm-2.29.5/.github/000077500000000000000000000000001527077133000137365ustar00rootroot00000000000000pdm-2.29.5/.github/ISSUE_TEMPLATE/000077500000000000000000000000001527077133000161215ustar00rootroot00000000000000pdm-2.29.5/.github/ISSUE_TEMPLATE/bug_report.yml000066400000000000000000000040741527077133000210210ustar00rootroot00000000000000name: "Bug report" description: Create a report to help us improve labels: ['� bug'] body: - type: markdown attributes: value: "Thank you for taking the time to report a bug. Please provide as much information as possible to help us understand and resolve the issue." - type: textarea id: describe-bug attributes: label: Describe the bug description: "A clear and concise description of what the bug is." placeholder: "Describe the bug..." validations: required: true - type: textarea id: reproduce-bug attributes: label: To reproduce description: "Steps to reproduce the behavior." placeholder: "Steps to reproduce the behavior..." validations: required: true - type: textarea id: expected-behavior attributes: label: Expected Behavior description: "A clear and concise description of what you expected to happen." placeholder: "Explain what you expected to happen..." validations: required: true - type: textarea id: "environment-info" attributes: label: Environment Information description: "Paste the output of `pdm info && pdm info --env`" placeholder: "Paste the output of `pdm info && pdm info --env`" validations: required: true - type: textarea id: "pdm-debug-output" attributes: label: "Verbose Command Output" description: "Please provide the command output with `-v`." placeholder: "Add the command output with `-v`..." validations: required: false - type: textarea id: additional-context attributes: label: Additional Context description: "Add any other context about the problem here." placeholder: "Additional details..." validations: required: false - type: checkboxes id: willing-to-submit-pr attributes: label: "Are you willing to submit a PR to fix this bug?" description: "Let us know if you are willing to contribute a fix by submitting a Pull Request." options: - label: "Yes, I would like to submit a PR." pdm-2.29.5/.github/ISSUE_TEMPLATE/feature_request.yml000066400000000000000000000030241527077133000220460ustar00rootroot00000000000000name: "Feature / Enhancement Proposal" description: Suggest an idea for this project labels: ['� enhancement'] body: - type: markdown attributes: value: "Thank you for suggesting a new feature. Please fill out the details below to help us understand your idea better." - type: textarea id: feature-description attributes: label: Feature Description description: "A detailed description of the feature you would like to see." placeholder: "Describe the feature you'd like..." validations: required: true - type: textarea id: problem-solution attributes: label: Problem and Solution description: "Describe the problem that this feature would solve. Explain how you envision it working." placeholder: "What problem does this feature solve? How do you envision it working?" validations: required: true - type: textarea id: additional-context attributes: label: Additional Context description: "Add any other context or screenshots about the feature request here." placeholder: "Add any other context or screenshots about the feature request here." validations: required: false - type: checkboxes id: willing-to-contribute attributes: label: "Are you willing to contribute to the development of this feature?" description: "Let us know if you are willing to help by contributing code or other resources." options: - label: "Yes, I am willing to contribute to the development of this feature." pdm-2.29.5/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000002651527077133000175420ustar00rootroot00000000000000## Pull Request Checklist - [ ] A news fragment is added in `news/` describing what is new. - [ ] Test cases added for changed code. ## Describe what you have changed in this PR. pdm-2.29.5/.github/dependabot.yml000066400000000000000000000004251527077133000165670ustar00rootroot00000000000000version: 2 updates: # Maintain dependencies for workflow actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" labels: - "github_actions" groups: actions: patterns: - "*" pdm-2.29.5/.github/workflows/000077500000000000000000000000001527077133000157735ustar00rootroot00000000000000pdm-2.29.5/.github/workflows/ci.yml000066400000000000000000000057601527077133000171210ustar00rootroot00000000000000name: Tests on: pull_request: branches: - main - dev - "maintain/*" paths-ignore: - "docs/**" - "news/**" - "*.md" push: branches: - main - dev - "maintain/*" paths-ignore: - "docs/**" - "news/**" - "*.md" concurrency: group: ${{ github.event.number || github.run_id }} cancel-in-progress: true jobs: Testing: env: PYTHONDEVMODE: 1 runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: python-version: ["3.10", 3.11, 3.12, 3.13, 3.14, 3.15] os: [ubuntu-latest, windows-latest, macos-latest] install-via: [pip] include: - python-version: 3.12 os: ubuntu-latest install-via: script - python-version: pypy-3.11 os: ubuntu-latest install-via: pip steps: - uses: actions/checkout@v7.0.1 - name: Setup Python Versions uses: actions/setup-python@v7 with: python-version: | 3.10 3.11 3.12 3.13 3.14 3.15 allow-prereleases: true - name: Setup Python ${{ matrix.python-version }} uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} cache: pip allow-prereleases: true - name: Cache venv uses: actions/cache@v6.1.0 with: path: .venv key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('pdm.lock') }} - name: Install uv uses: astral-sh/setup-uv@v10.2.0 with: version: "latest" - name: Install current PDM via pip if: matrix.install-via == 'pip' run: python -m pip install -U . - name: Install current PDM via script if: matrix.install-via == 'script' run: | shasum -a256 --check install-pdm.py.sha256 python install-pdm.py --version head echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install Dev Dependencies run: | pdm install -v -Gtest pdm run pip install -U setuptools pdm info # - name: Setup tmate session # uses: mxschmitt/action-tmate@v3.22 - name: Run Tests run: pdm run pytest -n auto --cov=pdm --cov-config=pyproject.toml --cov-report=xml tests - name: Upload coverage to Codecov uses: codecov/codecov-action@v7.1.1 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage.xml flags: unittests Pack: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7.0.1 with: fetch-depth: 0 - uses: actions/setup-python@v7 with: python-version: 3.x - name: Install PDM run: | python -m pip install . pdm self add pdm-packer - name: Pack pdm run: pdm pack - name: Test zipapp run: python pdm.pyz --version pdm-2.29.5/.github/workflows/release.yml000066400000000000000000000114411527077133000201370ustar00rootroot00000000000000name: Release on: push: tags: - "*" defaults: run: # make sure to work on Windows shell: bash jobs: release-pypi: name: release-pypi runs-on: ubuntu-latest permissions: id-token: write contents: write steps: - uses: actions/checkout@v7.0.1 - uses: actions/setup-python@v7 with: python-version: "3.11" cache: pip - name: Check prerelease id: check_version run: | if [[ "${{ github.ref }}" =~ ^refs/tags/[0-9.]+$ ]]; then echo "PRERELEASE=false" >> $GITHUB_OUTPUT else echo "PRERELEASE=true" >> $GITHUB_OUTPUT fi - name: Build artifacts run: | pipx run build - name: Upload artifacts uses: actions/upload-artifact@v7.0.1 with: name: pdm-wheel path: dist/*.whl if-no-files-found: error retention-days: 15 - name: Test Build run: | python -m pip install "pdm[locked] @ file://$(ls ${GITHUB_WORKSPACE}/dist/*.whl)" pdm --help - name: Publish package distributions to PyPI run: pdm publish --no-build - name: Get Changelog id: get-changelog run: | awk '/## Release/{if (flag==1)exit;else;flag=1;next} flag' CHANGELOG.md > .changelog.md - name: Create Release uses: actions/create-release@main env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} release_name: v${{ github.ref }} body_path: .changelog.md draft: false prerelease: ${{ steps.check_version.outputs.PRERELEASE }} - name: Trigger Bucket Update uses: benc-uk/workflow-dispatch@v1.3.3 with: workflow: Excavator repo: frostming/scoop-frostming token: ${{ secrets.G_T }} ref: master binary: needs: release-pypi runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ "ubuntu-24.04", "ubuntu-24.04-arm", "windows-2025", "macos-15-intel", "macos-15", ] env: PYAPP_REPO: pyapp PYAPP_VERSION: "0.27.0" PYAPP_PROJECT_NAME: pdm PYAPP_PROJECT_VERSION: ${{ github.ref_name }} PYAPP_SELF_COMMAND: app # since `self` has been taken in `pdm` PYAPP_DISTRIBUTION_EMBED: true PYAPP_PROJECT_FEATURES: locked SOURCE_FILE: ${{ matrix.os != 'windows-2025' && 'pyapp' || 'pyapp.exe' }} TARGET_FILE: ${{ matrix.os != 'windows-2025' && 'pdm' || 'pdm.exe' }} steps: - name: Checkout uses: actions/checkout@v7.0.1 - name: Fetch PyApp run: >- mkdir $PYAPP_REPO && curl -L https://github.com/ofek/pyapp/releases/download/v$PYAPP_VERSION/source.tar.gz | tar --strip-components=1 -xzf - -C $PYAPP_REPO - name: Setup Rust uses: dtolnay/rust-toolchain@stable - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.11 if: matrix.os != 'macos-15-intel' - name: Set sccache env if: matrix.os != 'macos-15-intel' run: | echo "SCCACHE_GHA_ENABLED=true" >> $GITHUB_ENV echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV - name: Download artifacts uses: actions/download-artifact@v8.0.1 with: name: pdm-wheel path: dist - name: Configure embedded wheel run: | cd dist wheel="$(echo *.whl)" mv $wheel ../$PYAPP_REPO echo "PYAPP_PROJECT_PATH=$wheel" >> $GITHUB_ENV echo "TARGET_TRIPLE=$(rustc --version --verbose | grep "host" | awk '{print $2}')" >> $GITHUB_ENV - name: Build run: | cd $PYAPP_REPO cargo build --release mv target/release/$SOURCE_FILE ../$TARGET_FILE - name: Upload Assets uses: actions/upload-artifact@v7.0.1 with: name: pdm-${{ github.ref_name }}-${{ env.TARGET_TRIPLE }} path: ${{ env.TARGET_FILE }} if-no-files-found: error retention-days: 15 - name: Create and Upload Archive with Checksum env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} UPLOAD_FILE: pdm-${{ github.ref_name }}-${{ env.TARGET_TRIPLE }}.tar.gz CHECKSUM_FILE: pdm-${{ github.ref_name }}-${{ env.TARGET_TRIPLE }}.tar.gz.sha256 run: | tar -czf $UPLOAD_FILE $TARGET_FILE if command -v sha256sum &> /dev/null; then sha256sum $UPLOAD_FILE > $CHECKSUM_FILE else shasum -a 256 $UPLOAD_FILE > $CHECKSUM_FILE fi gh release upload ${{ github.ref_name }} $UPLOAD_FILE $CHECKSUM_FILE --clobber pdm-2.29.5/.gitignore000066400000000000000000000036451527077133000143760ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ docs/site # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ /venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ .vscode/ caches/ .idea/ __pypackages__ .pdm.toml .pdm-python temp.py # Pyannotate generated stubs type_info.json .pdm-build/ src/pdm/VERSION .zed/ pdm-2.29.5/.pre-commit-config.yaml000066400000000000000000000012371527077133000166620ustar00rootroot00000000000000ci: autoupdate_schedule: monthly repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: 'v0.16.10' hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix, --show-fixes] - id: ruff-format - repo: https://github.com/codespell-project/codespell rev: v2.4.3 hooks: - id: codespell # See pyproject.toml for args additional_dependencies: - tomli - repo: https://github.com/pre-commit/mirrors-mypy rev: v2.4.0 hooks: - id: mypy args: [src] pass_filenames: false additional_dependencies: - types-requests - types-certifi - pytest pdm-2.29.5/.pre-commit-hooks.yaml000066400000000000000000000013001527077133000165270ustar00rootroot00000000000000- id: pdm-lock-check name: pdm-lock-check description: run pdm lock --check to validate config entry: pdm lock --check language: python language_version: python3 pass_filenames: false files: ^pyproject.toml$ - id: pdm-export name: pdm-export-lock description: export locked packages to requirements.txt or setup.py entry: pdm export language: python language_version: python3 pass_filenames: false files: ^pdm.lock$ - id: pdm-sync name: pdm-sync description: sync current working set with pdm.lock entry: pdm sync language: python language_version: python3 pass_filenames: false stages: - post-checkout - post-merge - post-rewrite always_run: true pdm-2.29.5/.readthedocs.yaml000066400000000000000000000014421527077133000156260ustar00rootroot00000000000000# Read the Docs configuration file for MkDocs projects # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Set the version of Python and other tools you might need build: os: ubuntu-22.04 tools: python: "3.12" jobs: install: - python install-pdm.py --path ~/.local/pdm - ~/.local/pdm/bin/pdm --version - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH ~/.local/pdm/bin/pdm install -dG doc build: html: - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH ~/.local/pdm/bin/pdm run python tasks/render_reference_docs.py - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH ~/.local/pdm/bin/pdm run zensical build - mkdir --parents $READTHEDOCS_OUTPUT/html/ - cp --recursive site/. $READTHEDOCS_OUTPUT/html/ pdm-2.29.5/AGENTS.md000066400000000000000000000070231527077133000137030ustar00rootroot00000000000000# AGENTS.md This file provides guidance to AI coding assistants when working with code in this repository. ## Project Overview PDM (Python Dependency Manager) is a modern Python package and dependency manager that supports the latest PEP standards (PEP 517, PEP 621). It provides fast dependency resolution, flexible plugin system, and centralized cache management similar to pnpm. ## Core Architecture ### Key Components 1. **Project Management** (`src/pdm/project/`): Handles pyproject.toml parsing, project configuration, and metadata management 2. **Dependency Resolution** (`src/pdm/resolver/`): Fast dependency resolver using resolvelib with custom optimizations for binary distributions 3. **Environment Management** (`src/pdm/environments/`): Manages Python environments (virtualenv, PEP 582, system) 4. **Installer System** (`src/pdm/installers/`): Installs and uninstalls packages into the site-packages directory with centralized cache support 5. **CLI System** (`src/pdm/cli/commands/`): Command-line interface using argparse with plugin support 6. **Repository Models** (`src/pdm/models/repositories/`): PyPI repository interaction and package finder 7. **Build System** (`src/pdm/builders/`): PEP 517 build front-end for creating wheels and sdists ### Command Entry Points All CLI commands are in `src/pdm/cli/commands/` with command registration in `src/pdm/core.py`. Commands inherit from `BaseCommand` and use decorator patterns for common options. ## Development Commands ### Setup Development Environment ```bash # Install development dependencies pdm install ``` ### Run Tests ```bash # Run all tests pdm run test # Run tests in parallel pdm run test -n auto ``` Most of the time, you can exclude tests with "integration" mark to save runtime: ```bash pdm run test -n auto -m "not integration" ``` ### Code Quality ```bash # Run linting (ruff-format + codespell + mypy) pdm run lint ``` ### Documentation ```bash # Serve documentation locally pdm run doc ``` ### Contribution Guidelines Refer to [CONTRIBUTING.md](CONTRIBUTING.md) ## Important Files - `pyproject.toml`: Project configuration and dependencies - `src/pdm/core.py`: Main application entry point and command registration - `src/pdm/project/__init__.py`: Project class managing project state - `src/pdm/cli/commands/base.py`: Base command class for all CLI commands - `.pre-commit-config.yaml`: Code quality hooks (ruff, mypy, codespell) ## Common Development Tasks ### Adding a New Command 1. Create new file in `src/pdm/cli/commands/` 2. Inherit from `BaseCommand` 3. Register in `src/pdm/core.py` ### Debugging Resolution Issues - Set `PDM_DEBUG=1` environment variable for verbose output - Check `pdm.lock` for resolved versions - Use `pdm lock --check` to verify lock file ### Working with Lock Files PDM uses its own lock file format (`pdm.lock`) that includes: - Exact versions with hashes - Environment markers - Cross-platform support - Group dependencies ### Update dependencies ```bash # Add a new dependency to default group pdm add # Update all dependencies pdm update # Remove a dependency pdm remove # Add a new dependency to given group pdm add --group ``` ## Architecture Patterns - **Dependency Injection**: Core class passed to commands - **Signal System**: Event-driven architecture for plugins - **Repository Pattern**: Abstract repository interface for package sources - **Strategy Pattern**: Different environment backends (venv, conda, etc.) - **Chain of Responsibility**: Middleware system for HTTP client pdm-2.29.5/CHANGELOG.md000066400000000000000000006607561527077133000142330ustar00rootroot00000000000000## Release v2.29.5 (2026-10-30) ### Bug Fixes - Preserve archive subdirectories when writing or exporting pylock.toml. ([#3964](https://github.com/pdm-project/pdm/issues/3964)) - Preserve extras and environment markers on local, URL, Git, and workspace file requirements when translating dependencies for uv. ([#3965](https://github.com/pdm-project/pdm/issues/3965)) - Preserve Git source subdirectories and encoded refs when generating, reusing, and reading uv lockfiles. ([#3966](https://github.com/pdm-project/pdm/issues/3966)) - Allow sorting installed packages by optional metadata such as homepage when some values are missing or unknown. ([#3967](https://github.com/pdm-project/pdm/issues/3967)) - Fill the Homepage in `pdm show` from the `Homepage` Project-URL, and stop `pdm show` failing on a Project-URL that contains a comma. ([#3968](https://github.com/pdm-project/pdm/issues/3968)) - Quote the activation script path that `pdm venv activate` prints for PowerShell, so `Invoke-Expression (pdm venv activate)` works when the path contains spaces or apostrophes. ([#3970](https://github.com/pdm-project/pdm/issues/3970)) - On Windows, quote the extra arguments of a `shell` script, and the `{args}` placeholder in it, for `cmd.exe` instead of with POSIX single quotes. ([#3971](https://github.com/pdm-project/pdm/issues/3971)) - Omit missing package versions when exporting to `pylock.toml`. ([#3972](https://github.com/pdm-project/pdm/issues/3972)) - Fill the Homepage in `pdm list` from the `Homepage` Project-URL when `Home-page` is missing or unknown. ([#3973](https://github.com/pdm-project/pdm/issues/3973)) ## Release v2.29.4 (2026-10-27) ### Features & Improvements - Allow specifying `lock.format` in `pyproject.toml` via the `[tool.pdm.lock]` table. ([#3958](https://github.com/pdm-project/pdm/issues/3958)) ### Bug Fixes - Import a requirements file that starts with a UTF-8 BOM, which failed with a `RequirementError`. ([#3937](https://github.com/pdm-project/pdm/issues/3937)) - Treat a `Pipfile` version without an operator, such as `requests = "2.31.0"`, as an exact `==` pin when importing, like pipenv does, instead of failing with an invalid specifier error. ([#3939](https://github.com/pdm-project/pdm/issues/3939)) - Preserve Poetry include entries targeting both source and wheel distributions when importing a project. ([#3941](https://github.com/pdm-project/pdm/issues/3941)) - Preserve version and description when importing Flit projects with a `src/` layout or an annotated `__version__`. ([#3942](https://github.com/pdm-project/pdm/issues/3942)) - Require `certifi>=2026.10.19`, which removes the `emSign ECC Root CA - G3` root whose eMudhra intermediates had their private keys compromised. ([#3944](https://github.com/pdm-project/pdm/issues/3944)) - `pdm outdated` no longer lists a package whose installed version is newer than the latest one found on the index, such as an installed pre-release or local build. ([#3945](https://github.com/pdm-project/pdm/issues/3945)) - Fix `pdm lock --check` reporting an outdated lockfile when a group is declared in both `[dependency-groups]` and `[tool.pdm.dev-dependencies]`. ([#3947](https://github.com/pdm-project/pdm/issues/3947)) - Show the license from `License-Expression` (PEP 639) in `pdm show` and `pdm list --fields licenses`. ([#3948](https://github.com/pdm-project/pdm/issues/3948)) - Stop `pdm lock` from excluding packages from a lock target when another target shares its OS and architecture, e.g. manylinux and musllinux. ([#3950](https://github.com/pdm-project/pdm/issues/3950)) - Fix a crash when a `python_version` marker compares against a wildcard version such as `python_version == "3.*"`. ([#3951](https://github.com/pdm-project/pdm/issues/3951)) - Send `License-Expression` and `License-File` with the upload in `pdm publish`, so PyPI shows the license of PEP 639 packages. ([#3952](https://github.com/pdm-project/pdm/issues/3952)) - Preserve the subdirectory fragment in source archive requirements when resolving dependencies and serializing requirement URLs. ([#3954](https://github.com/pdm-project/pdm/issues/3954)) - Preserve archive hashes when reading pylock.toml so they remain available for exports. ([#3956](https://github.com/pdm-project/pdm/issues/3956)) - Fix detection of responses served from the HTTP cache, so cached downloads and index pages are reported as cached again. ([#3961](https://github.com/pdm-project/pdm/issues/3961)) ### Dependencies - Install the download dependencies of pbs-installer so Python installation works with its latest releases. ([#3959](https://github.com/pdm-project/pdm/issues/3959)) - Upgrade `unearth` to `>=0.19` and migrate the HTTP client from `httpx` to `httpx2`. `pdm.models.session.PDMPyPIClient` and the transports in `pdm.pytest` are now built on `httpx2`, so plugins interacting with them should import `httpx2` instead of `httpx`. ([#3962](https://github.com/pdm-project/pdm/issues/3962)) ## Release v2.29.3 (2026-10-19) ### Features & Improvements - Add the `--venv` option to `pdm outdated`, like the other commands that read the installed packages. ([#3904](https://github.com/pdm-project/pdm/issues/3904)) ### Bug Fixes - Fix isolated PEP 517 builds skipping packages that are only visible via the host venv's `--system-site-packages`. ([#3895](https://github.com/pdm-project/pdm/issues/3895)) - Fix `pdm import` of Poetry projects dropping optional dependencies whose extras entry is spelled differently, and importing optional dependencies with multiple constraints as required ones. ([#3899](https://github.com/pdm-project/pdm/issues/3899)) - Keep the plain requirement in `pdm export` when the same package is also locked with extras under a narrower marker, so it is no longer missing from `requirements.txt` on the other platforms. ([#3900](https://github.com/pdm-project/pdm/issues/3900)) - Fix `python_version <= "X.Y"` markers excluding the patch releases of `X.Y`, so `pdm install` skipped such dependencies. ([#3902](https://github.com/pdm-project/pdm/issues/3902)) - Fix environment variables set by one task of a composite script, via `env` or `env_file`, leaking into the tasks that run after it. ([#3903](https://github.com/pdm-project/pdm/issues/3903)) - Convert flit's comma-separated `keywords` and obsolete `dev-requires` into valid PEP 621 fields when importing a flit project. ([#3907](https://github.com/pdm-project/pdm/issues/3907)) - Import custom Pipfile package categories, such as `[docs]`, as dependency groups instead of dropping them. ([#3909](https://github.com/pdm-project/pdm/issues/3909)) - Keep editable requirements in `[tool.pdm.dev-dependencies]` on `pdm import`, so the written `[dependency-groups]` table stays valid per PEP 735. ([#3910](https://github.com/pdm-project/pdm/issues/3910)) - Keep Poetry's `develop = true` as an editable requirement when importing dependency groups. ([#3913](https://github.com/pdm-project/pdm/issues/3913)) - Fix `pdm import` of the project's own Poetry `pyproject.toml` writing each dependency group to both `[tool.pdm.dev-dependencies]` and `[dependency-groups]`. ([#3915](https://github.com/pdm-project/pdm/issues/3915)) - Import Pipfile packages declared with a `file` URL, such as `{file = "https://..."}`, as URL requirements instead of dropping the URL. ([#3918](https://github.com/pdm-project/pdm/issues/3918)) - Preserve Poetry platform restrictions as environment markers when importing dependencies. ([#3920](https://github.com/pdm-project/pdm/issues/3920)) - Read an `exclude-newer` timestamp without a UTC offset as UTC, so `pdm lock` no longer fails with a `TypeError` comparing naive and aware datetimes. ([#3922](https://github.com/pdm-project/pdm/issues/3922)) - Do not write empty dependency groups, such as `dev = []` from an empty `[dev-packages]` table, when importing from another format. ([#3925](https://github.com/pdm-project/pdm/issues/3925)) - Strip every leading and trailing `.`, `_` and `-` when `pdm init` derives the project name from the directory, so a folder like `__demo__` no longer produces the invalid name `_demo_`. ([#3927](https://github.com/pdm-project/pdm/issues/3927)) - `pdm init` now writes `project.license` as a license expression string instead of a `{text = ...}` table, and no longer rewrites an existing `{file = ...}` table or license expression into a value the build backend rejects. ([#3929](https://github.com/pdm-project/pdm/issues/3929)) - Read the inline metadata of a script that starts with a UTF-8 BOM, which `pdm run` ignored. ([#3931](https://github.com/pdm-project/pdm/issues/3931)) - Convert a space-separated Poetry version constraint such as `>=1.0 <2.0` like the comma-separated form instead of aborting the import. ([#3934](https://github.com/pdm-project/pdm/issues/3934)) - Resolve relative `path` entries in a `Pipfile` against the directory of the `Pipfile` when importing, instead of the current working directory. ([#3935](https://github.com/pdm-project/pdm/issues/3935)) ### Documentation - Document what to cache and which install command to use when running PDM on CI platforms other than GitHub Actions. ([#2472](https://github.com/pdm-project/pdm/issues/2472)) ## Release v2.29.2 (2026-09-17) ### Bug Fixes - Fix writing lock files specified as bare relative filenames with `pdm lock --lockfile`. ([#3891](https://github.com/pdm-project/pdm/issues/3891)) - Preserve local paths containing spaces and their extras and environment markers when importing requirements files. ([#3894](https://github.com/pdm-project/pdm/issues/3894)) ### Documentation - List the install-pdm.py options the script actually accepts. ([#3889](https://github.com/pdm-project/pdm/issues/3889)) ## Release v2.29.1 (2026-09-14) ### Features & Improvements - Explain missing lockfile groups and provide group-selection recovery guidance when installing, syncing, or updating groups. ([#2682](https://github.com/pdm-project/pdm/issues/2682)) - Allow package-specific overrides for `exclude-newer` resolution limits. ([#3809](https://github.com/pdm-project/pdm/issues/3809)) ### Bug Fixes - Keep the separating comma out of the operator and accept a `v` prefix when converting Poetry version constraints. ([#3860](https://github.com/pdm-project/pdm/issues/3860)) - Escape glob characters in the virtualenv lookup prefix, so a project whose directory name contains `[` or `]` can find its own virtualenv. ([#3869](https://github.com/pdm-project/pdm/issues/3869)) - Write `pyproject.toml` and lockfiles atomically to prevent interrupted writes from truncating them. ([#3870](https://github.com/pdm-project/pdm/issues/3870)) - Resolve the workspace root before making member paths relative, so a root given as a relative path or reached through a symlink no longer raises `ValueError`. ([#3874](https://github.com/pdm-project/pdm/issues/3874)) - Replace the destination of an atomic write instead of unlinking it first, so an interrupted write can no longer destroy `pyproject.toml` or the lockfile. ([#3878](https://github.com/pdm-project/pdm/issues/3878)) - Report the version part that could not be read, instead of blaming a postrelease for every parse failure. ([#3880](https://github.com/pdm-project/pdm/issues/3880)) - Keep quoted local paths that contain `` - `` when parsing requirements files. ([#3885](https://github.com/pdm-project/pdm/issues/3885)) ### Documentation - Clarify dependency command effects on project declarations, lock metadata, and installed packages in the guide and CLI help. ([#2681](https://github.com/pdm-project/pdm/issues/2681)) ## Release v2.29.0 (2026-08-29) ### Features & Improvements - Export editable local dependencies with relative paths in requirements files. ([#3294](https://github.com/pdm-project/pdm/issues/3294)) - Extend `pdm run` with `--env`, `--env-file` and `--working-dir` options to set or override the corresponding script options dynamically. ([#3829](https://github.com/pdm-project/pdm/issues/3829)) ### Bug Fixes - Restrict a locked package to the platform it was resolved for when it doesn't belong to every lock target, so `pdm lock --platform ... --append` no longer adds entries that get installed on the other targets. ([#3261](https://github.com/pdm-project/pdm/issues/3261)) - Keep Poetry `include` entries restricted to the sdist format when importing, writing them to `tool.pdm.build.source-includes` instead of dropping them. ([#3854](https://github.com/pdm-project/pdm/issues/3854)) - Accept `--no-verify-ssl` on `pdm publish`, which was misspelled as `--no-very-ssl`. The old spelling keeps working as an alias. ([#3857](https://github.com/pdm-project/pdm/issues/3857)) - Convert Poetry tilde constraints with fewer than three components to the bounds Poetry means: `~1.2` becomes `<1.3` rather than `<2.0`, and `~1` no longer produces an invalid `~=1` specifier that aborts the import. ([#3858](https://github.com/pdm-project/pdm/issues/3858)) - Keep the separating comma out of the operator and accept a `v` prefix when converting Poetry version constraints. ([#3860](https://github.com/pdm-project/pdm/issues/3860)) - Keep importing a Poetry project when an author or maintainer entry does not fit the `Name ` pattern. ([#3861](https://github.com/pdm-project/pdm/issues/3861)) - Skip `requires-python` when a Pipfile `[requires]` table has no python version, instead of writing `>=None`. ([#3862](https://github.com/pdm-project/pdm/issues/3862)) - Leave the version and description empty instead of aborting when a flit module cannot be parsed. ([#3864](https://github.com/pdm-project/pdm/issues/3864)) - Respect dependency group selection options when exporting to `pylock.toml`, producing a single-use lock file that contains only the selected packages. ([#3866](https://github.com/pdm-project/pdm/issues/3866)) ## Release v2.28.2 (2026-08-18) ### Bug Fixes - Keep environment inspection working for Python 3.9 targets when PDM uses dep-logic 0.7 or newer. ([#3838](https://github.com/pdm-project/pdm/issues/3838)) - Cache the update check timestamp even when the version lookup fails, so that pdm no longer appears to hang on every command when PyPI is unreachable. ([#3840](https://github.com/pdm-project/pdm/issues/3840)) - Don't crash with an `IndexError` when listing scripts and one of them is blank. A blank script is now listed as ``. ([#3842](https://github.com/pdm-project/pdm/issues/3842)) - Keep the whole template URL when `pdm new` is given an `ssh://` or credentialed Git URL, instead of truncating it at the userinfo `@`. ([#3843](https://github.com/pdm-project/pdm/issues/3843)) - Strip comments preceded by any whitespace, not only a plain space, when importing a `requirements.txt` file. ([#3844](https://github.com/pdm-project/pdm/issues/3844)) - Match `--trusted-host` on host and port when importing a `requirements.txt` file, and keep the port when exporting one. ([#3845](https://github.com/pdm-project/pdm/issues/3845)) - Expand a `~` prefix in the `venv.location` config so `pdm venv list/remove/activate/purge` find virtualenvs created under it. ([#3847](https://github.com/pdm-project/pdm/issues/3847)) - Convert a Poetry caret constraint on a `0.x` version to the upper bound Poetry documents, so `^0.2.3` becomes `<0.3.0` and `^0.0.3` becomes `<0.0.4` instead of `<1.0.0`. ([#3848](https://github.com/pdm-project/pdm/issues/3848)) - Fill in a placeholder `project.name` and `project.version` for the `pyproject.toml` generated for `uv`, so `pdm lock`/`pdm install` work with `use_uv` on a project that declares neither. ([#3849](https://github.com/pdm-project/pdm/issues/3849)) - Resolve nested requirement paths relative to remote requirements file URLs. ([#3850](https://github.com/pdm-project/pdm/issues/3850)) ## Release v2.28.1 (2026-08-11) ### Features & Improvements - Defer command action and Python installer imports until their corresponding runtime paths execute. ([#3673](https://github.com/pdm-project/pdm/issues/3673)) - Add `{run_cwd}` placeholder for scripts to reference the original working directory. ([#3734](https://github.com/pdm-project/pdm/issues/3734)) - Add opt-in canonical lock input freshness via `tool.pdm.resolution.lock_inputs` while retaining sticky lockfile behavior and legacy hash fallback for existing lock files. ([#3821](https://github.com/pdm-project/pdm/issues/3821)) - Integrate `argcomplete` for simplified command-line completion scripts. ([#3823](https://github.com/pdm-project/pdm/issues/3823)) ### Bug Fixes - Keep workspace members in their explicitly declared dependency groups instead of adding them to ``default`` in the lockfile. ([#3816](https://github.com/pdm-project/pdm/issues/3816)) - Keep the cached parsed version intact when stripping the local segment in `comparable_version()`. ([#3817](https://github.com/pdm-project/pdm/issues/3817)) - Make `use_uv` support adding local files. ([#3822](https://github.com/pdm-project/pdm/issues/3822)) - Add a Poetry optional dependency to every extra that lists it when importing, instead of only the first one. ([#3831](https://github.com/pdm-project/pdm/issues/3831)) - Do not write null values into the generated `pyproject.toml` when importing a flit project that omits `author-email`/`maintainer-email` or sets only one of `include` and `exclude` in `[tool.flit.sdist]`. ([#3832](https://github.com/pdm-project/pdm/issues/3832)) ### Miscellany - Add Python 3.15 preview version to the CI matrix. ([#3827](https://github.com/pdm-project/pdm/issues/3827)) ## Release v2.28.0 (2026-06-23) ### Features & Improvements - Add experimental workspace support for managing local member projects in a shared root lock file. ([#1505](https://github.com/pdm-project/pdm/issues/1505)) - Defer startup-time imports for Python, virtualenv, and self-management commands. ([#3673](https://github.com/pdm-project/pdm/issues/3673)) ### Bug Fixes - Fix `pdm completion bash` printing `__ltrim_colon_completions: command not found` (and a similar error for `_get_comp_words_by_ref`) when the generated script is sourced in a bash without the `bash-completion` package loaded, such as Git Bash on Windows or minimal Linux containers. The script now defines small fallbacks for both helpers when they are not already available. ([#3793](https://github.com/pdm-project/pdm/issues/3793)) - Avoid forwarding duplicate SIGINT in pdm run on POSIX. ([#3808](https://github.com/pdm-project/pdm/issues/3808)) ### Documentation - Fix the Windows installation instructions for a specific version. `Invoke-Expression` (`iex`) does not accept an `-Args` parameter and cannot forward arguments to a piped script, so the documented command failed. Use the `$env:PDM_VERSION` environment variable, which the install script reads, instead. ([#3792](https://github.com/pdm-project/pdm/issues/3792)) ## Release v2.27.0 (2026-05-21) ### Breaking Changes - Update the minimum required Python version to 3.10. ([#3787](https://github.com/pdm-project/pdm/issues/3787)) ### Features & Improvements - Respect existing values of `pyproject.toml` when running `pdm init` or `pdm new`. ([#3786](https://github.com/pdm-project/pdm/issues/3786)) - Move project plugin installations from `.pdm-plugins` under the project root to an isolated cache directory, and add a fixer to migrate existing plugin directories. ([#3790](https://github.com/pdm-project/pdm/issues/3790)) - Remove legacy importlib compatibility wrappers and use standard-library `importlib.metadata` and `importlib.resources` APIs directly. ([#3796](https://github.com/pdm-project/pdm/issues/3796)) ### Bug Fixes - Fix a security issue with the installer to disallow installing to paths outside of the scheme directory. ([#3787](https://github.com/pdm-project/pdm/issues/3787)) - Refuse to write project-local config and state files (`pdm.toml`, `.pdm-python`, `.python-version`) when the destination is a symlink, preventing an untrusted repository from clobbering files outside the project root. ([#3788](https://github.com/pdm-project/pdm/issues/3788)) - Fix a regression issue that `PDM_LOCKFILE` env var is not respected. ([#3794](https://github.com/pdm-project/pdm/issues/3794)) - Allow configuring the default lock `--exclude-newer` value with `strategy.exclude-newer`. ([#3795](https://github.com/pdm-project/pdm/issues/3795)) ## Release v2.26.9 (2026-05-10) ### Features & Improvements - Support `exclude-newer` in `pyproject.toml` in the `[tool.pdm.resolution]` table ([#3776](https://github.com/pdm-project/pdm/issues/3776)) ### Bug Fixes - Preserve pylock package markers when refreshing lockfile hashes. ([#3773](https://github.com/pdm-project/pdm/issues/3773)) ## Release v2.26.8 (2026-04-21) ### Features & Improvements - `pdm lock --exclude-newer` now accepts relative durations in the format `N{d|h|w}`, such as `7d`, `12h`, and `3w`, in addition to absolute UTC dates and timestamps. ([#3760](https://github.com/pdm-project/pdm/issues/3760)) ### Bug Fixes - Fixed `pdm add --frozen-lockfile --no-sync` to skip dependency resolution and update only `pyproject.toml` without attempting to write the lockfile. ([#3755](https://github.com/pdm-project/pdm/issues/3755)) - Fix `[tool.pdm.options]` being loaded from the current working directory instead of the target project when `-p`/`--project` is used. ([#3756](https://github.com/pdm-project/pdm/issues/3756)) - Put `make_file_executable` into `pdm.utils` to replace the method of the same name in `installer`. To fix a breakage introduced by `installer` v1. ([#3764](https://github.com/pdm-project/pdm/issues/3764)) - Fix `pdm init