Skip to content

Commit

Permalink
feat: config setting option for other commands that may build packages (
Browse files Browse the repository at this point in the history
#2688)

* feat: share config settings in installation

Signed-off-by: Frost Ming <[email protected]>

* feat: add --config-setting option to add/update/remove/lock/sync/install/export comands

Signed-off-by: Frost Ming <[email protected]>

* add news

Signed-off-by: Frost Ming <[email protected]>

* tweak the test case

Signed-off-by: Frost Ming <[email protected]>
  • Loading branch information
frostming authored Mar 13, 2024
1 parent 2343a8d commit c80696b
Show file tree
Hide file tree
Showing 15 changed files with 165 additions and 131 deletions.
1 change: 1 addition & 0 deletions news/2636.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `--config-setting` option to `add/install/sync/update/remove/export` commands, the config settings dictionary will be shared by all packages.
6 changes: 1 addition & 5 deletions src/pdm/builders/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,4 @@
from pdm.builders.sdist import SdistBuilder
from pdm.builders.wheel import WheelBuilder

__all__ = (
EditableBuilder.__name__,
SdistBuilder.__name__,
WheelBuilder.__name__,
)
__all__ = ["EditableBuilder", "SdistBuilder", "WheelBuilder"]
12 changes: 4 additions & 8 deletions src/pdm/builders/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import threading
from logging import Logger
from pathlib import Path
from typing import TYPE_CHECKING, Any, ClassVar, Iterable, Mapping, cast
from typing import TYPE_CHECKING, Any, ClassVar, Iterable, cast

from pyproject_hooks import BuildBackendHookCaller

Expand Down Expand Up @@ -182,6 +182,7 @@ def __init__(self, src_dir: str | Path, environment: BaseEnvironment) -> None:
self.executable = self._env.interpreter.executable.as_posix()
self.src_dir = src_dir
self.isolated = environment.project.config["build_isolation"]
self.config_settings = environment.project.core.config_settings
mode = "Isolated" if self.isolated else "Non-isolated"
logger.info("Preparing environment(%s mode) for PEP 517 build...", mode)
try:
Expand Down Expand Up @@ -301,19 +302,14 @@ def install(self, requirements: Iterable[str], shared: bool = False) -> None:
if key not in self._shared_envs:
self._shared_envs[key] = path

def prepare_metadata(self, out_dir: str, config_settings: Mapping[str, Any] | None = None) -> str:
def prepare_metadata(self, out_dir: str) -> str:
"""Prepare metadata and store in the out_dir.
Some backends doesn't provide that API, in that case the metadata will be
retrieved from the built result.
"""
raise NotImplementedError("Should be implemented in subclass")

def build(
self,
out_dir: str,
config_settings: Mapping[str, Any] | None = None,
metadata_directory: str | None = None,
) -> str:
def build(self, out_dir: str, metadata_directory: str | None = None) -> str:
"""Build and store the artifact in out_dir,
return the absolute path of the built result.
"""
Expand Down
23 changes: 9 additions & 14 deletions src/pdm/builders/editable.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import os
from typing import Any, ClassVar, Mapping
from typing import Any, ClassVar

from pyproject_hooks import HookMissing

Expand All @@ -17,30 +17,25 @@ class EditableBuilder(EnvBuilder):
"requires": ["setuptools_pep660"],
}

def prepare_metadata(self, out_dir: str, config_settings: Mapping[str, Any] | None = None) -> str:
def prepare_metadata(self, out_dir: str) -> str:
self.install(self._requires, shared=True)
try:
requires = self._hook.get_requires_for_build_editable(config_settings)
requires = self._hook.get_requires_for_build_editable(self.config_settings)
self.install(requires)
filename = self._hook.prepare_metadata_for_build_editable(out_dir, config_settings)
filename = self._hook.prepare_metadata_for_build_editable(out_dir, self.config_settings)
except HookMissing:
self.init_build_system(self.FALLBACK_BACKEND)
return self.prepare_metadata(out_dir, config_settings)
return self.prepare_metadata(out_dir)
return os.path.join(out_dir, filename)

def build(
self,
out_dir: str,
config_settings: Mapping[str, Any] | None = None,
metadata_directory: str | None = None,
) -> str:
def build(self, out_dir: str, metadata_directory: str | None = None) -> str:
self.install(self._requires, shared=True)
try:
requires = self._hook.get_requires_for_build_editable(config_settings)
requires = self._hook.get_requires_for_build_editable(self.config_settings)
self.install(requires)
filename = self._hook.build_editable(out_dir, config_settings, metadata_directory)
filename = self._hook.build_editable(out_dir, self.config_settings, metadata_directory)
except HookMissing:
logger.warning("The build backend doesn't support PEP 660, falling back to setuptools-pep660")
self.init_build_system(self.FALLBACK_BACKEND)
return self.build(out_dir, config_settings, metadata_directory)
return self.build(out_dir, metadata_directory=metadata_directory)
return os.path.join(out_dir, filename)
12 changes: 3 additions & 9 deletions src/pdm/builders/sdist.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
from __future__ import annotations

import os
from typing import Any, Mapping

from pdm.builders.base import EnvBuilder


class SdistBuilder(EnvBuilder):
"""Build sdist in isolated env with managed Python."""

def build(
self,
out_dir: str,
config_settings: Mapping[str, Any] | None = None,
metadata_directory: str | None = None,
) -> str:
def build(self, out_dir: str, metadata_directory: str | None = None) -> str:
self.install(self._requires, shared=True)
requires = self._hook.get_requires_for_build_sdist(config_settings)
requires = self._hook.get_requires_for_build_sdist(self.config_settings)
self.install(requires)
filename = self._hook.build_sdist(out_dir, config_settings)
filename = self._hook.build_sdist(out_dir, self.config_settings)
return os.path.join(out_dir, filename)
18 changes: 6 additions & 12 deletions src/pdm/builders/wheel.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
from __future__ import annotations

import os
from typing import Any, Mapping

from pdm.builders.base import EnvBuilder


class WheelBuilder(EnvBuilder):
"""Build wheel in isolated env with managed Python."""

def prepare_metadata(self, out_dir: str, config_settings: Mapping[str, Any] | None = None) -> str:
def prepare_metadata(self, out_dir: str) -> str:
self.install(self._requires, shared=True)
requires = self._hook.get_requires_for_build_wheel(config_settings)
requires = self._hook.get_requires_for_build_wheel(self.config_settings)
self.install(requires)
filename = self._hook.prepare_metadata_for_build_wheel(out_dir, config_settings)
filename = self._hook.prepare_metadata_for_build_wheel(out_dir, self.config_settings)
return os.path.join(out_dir, filename)

def build(
self,
out_dir: str,
config_settings: Mapping[str, Any] | None = None,
metadata_directory: str | None = None,
) -> str:
def build(self, out_dir: str, metadata_directory: str | None = None) -> str:
self.install(self._requires, shared=True)
requires = self._hook.get_requires_for_build_wheel(config_settings)
requires = self._hook.get_requires_for_build_wheel(self.config_settings)
self.install(requires)
filename = self._hook.build_wheel(out_dir, config_settings, metadata_directory)
filename = self._hook.build_wheel(out_dir, self.config_settings, metadata_directory)
return os.path.join(out_dir, filename)
28 changes: 5 additions & 23 deletions src/pdm/cli/commands/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pdm.cli.commands.base import BaseCommand
from pdm.cli.hooks import HookManager
from pdm.cli.options import (
config_setting_option,
no_isolation_option,
project_option,
skip_option,
Expand All @@ -20,7 +21,7 @@
class Command(BaseCommand):
"""Build artifacts for distribution"""

arguments = (verbose_option, project_option, no_isolation_option, skip_option)
arguments = (verbose_option, project_option, no_isolation_option, skip_option, config_setting_option)

@staticmethod
def do_build(
Expand All @@ -36,6 +37,7 @@ def do_build(
from pdm.builders import SdistBuilder, WheelBuilder

hooks = hooks or HookManager(project)
config_settings = project.core.config_settings

if project.is_global:
raise ProjectError("Not allowed to build based on the global project.")
Expand All @@ -55,12 +57,12 @@ def do_build(
with project.core.ui.logging("build"):
if sdist:
project.core.ui.echo("Building sdist...")
loc = SdistBuilder(project.root, project.environment).build(dest, config_settings)
loc = SdistBuilder(project.root, project.environment).build(dest)
project.core.ui.echo(f"Built sdist at {loc}")
artifacts.append(loc)
if wheel:
project.core.ui.echo("Building wheel...")
loc = WheelBuilder(project.root, project.environment).build(dest, config_settings)
loc = WheelBuilder(project.root, project.environment).build(dest)
project.core.ui.echo(f"Built wheel at {loc}")
artifacts.append(loc)
hooks.try_emit("post_build", artifacts=artifacts, config_settings=config_settings)
Expand Down Expand Up @@ -88,33 +90,13 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None:
action="store_false",
help="Do not clean the target directory",
)
parser.add_argument(
"--config-setting",
"-C",
action="append",
help="Pass options to the backend. options with a value must be "
'specified after "=": `--config-setting=--opt(=value)` '
"or `-C--opt(=value)`",
)

def handle(self, project: Project, options: argparse.Namespace) -> None:
config_settings = None
if options.config_setting:
config_settings = {}
for item in options.config_setting:
name, _, value = item.partition("=")
if name not in config_settings:
config_settings[name] = value
else:
if not isinstance(config_settings[name], list):
config_settings[name] = [config_settings[name]]
config_settings[name].append(value)
self.do_build(
project,
sdist=options.sdist,
wheel=options.wheel,
dest=options.dest,
clean=options.clean,
config_settings=config_settings,
hooks=HookManager(project, options.skip),
)
10 changes: 9 additions & 1 deletion src/pdm/cli/commands/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
from pdm.cli.commands.base import BaseCommand
from pdm.cli.filters import GroupSelection
from pdm.cli.hooks import HookManager
from pdm.cli.options import groups_group, lock_strategy_group, lockfile_option, no_isolation_option, skip_option
from pdm.cli.options import (
config_setting_option,
groups_group,
lock_strategy_group,
lockfile_option,
no_isolation_option,
skip_option,
)
from pdm.project import Project


Expand All @@ -17,6 +24,7 @@ class Command(BaseCommand):
*BaseCommand.arguments,
lockfile_option,
no_isolation_option,
config_setting_option,
skip_option,
groups_group,
lock_strategy_group,
Expand Down
18 changes: 9 additions & 9 deletions src/pdm/cli/completions/pdm.bash
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# BASH completion script for pdm
# Generated by pycomplete 0.4.0

_pdm_41ba8a56174f8367_complete()
_pdm_a919b69078acdf0a_complete()
{
local cur script coms opts com
COMPREPLY=()
Expand Down Expand Up @@ -29,7 +29,7 @@ _pdm_41ba8a56174f8367_complete()
case "$com" in

(add)
opts="--dev --dry-run --editable --fail-fast --frozen-lockfile --global --group --help --lockfile --no-editable --no-isolation --no-self --no-sync --prerelease --project --quiet --save-compatible --save-exact --save-minimum --save-wildcard --skip --stable --unconstrained --update-all --update-eager --update-reuse --update-reuse-installed --venv --verbose"
opts="--config-setting --dev --dry-run --editable --fail-fast --frozen-lockfile --global --group --help --lockfile --no-editable --no-isolation --no-self --no-sync --prerelease --project --quiet --save-compatible --save-exact --save-minimum --save-wildcard --skip --stable --unconstrained --update-all --update-eager --update-reuse --update-reuse-installed --venv --verbose"
;;

(build)
Expand All @@ -49,7 +49,7 @@ _pdm_41ba8a56174f8367_complete()
;;

(export)
opts="--dev --editable-self --expandvars --format --global --group --help --lockfile --no-default --no-markers --output --production --project --pyproject --quiet --self --verbose --without-hashes"
opts="--dev --editable-self --expandvars --format --global --group --help --lockfile --no-default --no-markers --output --production --project --pyproject --quiet --self --verbose --without --without-hashes"
;;

(fix)
Expand All @@ -69,15 +69,15 @@ _pdm_41ba8a56174f8367_complete()
;;

(install)
opts="--check --dev --dry-run --fail-fast --frozen-lockfile --global --group --help --lockfile --no-default --no-editable --no-isolation --no-self --plugins --production --project --quiet --skip --venv --verbose"
opts="--check --config-setting --dev --dry-run --fail-fast --frozen-lockfile --global --group --help --lockfile --no-default --no-editable --no-isolation --no-self --plugins --production --project --quiet --skip --venv --verbose --without"
;;

(list)
opts="--csv --exclude --fields --freeze --global --graph --help --include --json --markdown --project --quiet --resolve --reverse --sort --venv --verbose"
;;

(lock)
opts="--check --dev --global --group --help --lockfile --no-cross-platform --no-default --no-isolation --no-static-urls --production --project --quiet --refresh --skip --static-urls --strategy --update-reuse --update-reuse-installed --verbose"
opts="--check --config-setting --dev --global --group --help --lockfile --no-cross-platform --no-default --no-isolation --no-static-urls --production --project --quiet --refresh --skip --static-urls --strategy --update-reuse --update-reuse-installed --verbose --without"
;;

(plugin)
Expand All @@ -89,7 +89,7 @@ _pdm_41ba8a56174f8367_complete()
;;

(remove)
opts="--dev --dry-run --fail-fast --frozen-lockfile --global --group --help --lockfile --no-editable --no-isolation --no-self --no-sync --project --quiet --skip --venv --verbose"
opts="--config-setting --dev --dry-run --fail-fast --frozen-lockfile --global --group --help --lockfile --no-editable --no-isolation --no-self --no-sync --project --quiet --skip --venv --verbose"
;;

(run)
Expand All @@ -109,11 +109,11 @@ _pdm_41ba8a56174f8367_complete()
;;

(sync)
opts="--clean --dev --dry-run --fail-fast --global --group --help --lockfile --no-default --no-editable --no-isolation --no-self --only-keep --production --project --quiet --reinstall --skip --venv --verbose"
opts="--clean --config-setting --dev --dry-run --fail-fast --global --group --help --lockfile --no-default --no-editable --no-isolation --no-self --only-keep --production --project --quiet --reinstall --skip --venv --verbose --without"
;;

(update)
opts="--dev --fail-fast --frozen-lockfile --global --group --help --lockfile --no-default --no-editable --no-isolation --no-self --no-sync --outdated --prerelease --production --project --quiet --save-compatible --save-exact --save-minimum --save-wildcard --skip --stable --top --unconstrained --update-all --update-eager --update-reuse --update-reuse-installed --venv --verbose"
opts="--config-setting --dev --fail-fast --frozen-lockfile --global --group --help --lockfile --no-default --no-editable --no-isolation --no-self --no-sync --outdated --prerelease --production --project --quiet --save-compatible --save-exact --save-minimum --save-wildcard --skip --stable --top --unconstrained --update-all --update-eager --update-reuse --update-reuse-installed --venv --verbose --without"
;;

(use)
Expand Down Expand Up @@ -143,4 +143,4 @@ _pdm_41ba8a56174f8367_complete()
fi
}

complete -o default -F _pdm_41ba8a56174f8367_complete pdm
complete -o default -F _pdm_a919b69078acdf0a_complete pdm
Loading

0 comments on commit c80696b

Please sign in to comment.