Skip to content

Commit

Permalink
feat: Supporting adding extra annotations to the exported `requirem…
Browse files Browse the repository at this point in the history
…ents` file (#2928)

Resolves #2519

Signed-off-by: Frost Ming <me@frostming.com>
  • Loading branch information
frostming committed Jun 7, 2024
1 parent 3275dfd commit 34d1ad5
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 10 deletions.
1 change: 1 addition & 0 deletions news/2519.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `--no-extras` to `pdm export` to strip extras from the requirements. Now the default behavior is to keep extras.
20 changes: 16 additions & 4 deletions src/pdm/cli/commands/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pdm.exceptions import PdmUsageError
from pdm.formats import FORMATS
from pdm.models.candidates import Candidate
from pdm.models.requirements import Requirement
from pdm.models.requirements import Requirement, strip_extras
from pdm.project import Project


Expand Down Expand Up @@ -39,6 +39,9 @@ def add_arguments(self, parser: argparse.ArgumentParser) -> None:
parser.add_argument(
"--no-markers", action="store_false", default=True, dest="markers", help="Don't include platform markers"
)
parser.add_argument(
"--no-extras", action="store_false", default=True, dest="extras", help="Strip extras from the requirements"
)
parser.add_argument(
"-o",
"--output",
Expand Down Expand Up @@ -73,9 +76,18 @@ def handle(self, project: Project, options: argparse.Namespace) -> None:
candidates = resolve_candidates_from_lockfile(
project, requirements.values(), groups=set(selection), cross_platform=options.markers
)
# Remove candidates with [extras] because the bare candidates are already
# included
packages = (candidate for candidate in candidates.values() if not candidate.req.extras)

filtered_candidates: dict[str, Candidate] = {}
for k, candidate in candidates.items():
if options.extras:
if candidate.req.extras:
k = strip_extras(k)[0]
elif k in filtered_candidates:
continue
elif candidate.req.extras:
continue
filtered_candidates[k] = candidate
packages = filtered_candidates.values()

content = FORMATS[options.format].export(project, packages, options)
if options.output:
Expand Down
2 changes: 1 addition & 1 deletion src/pdm/cli/completions/pdm.bash
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ _pdm_a919b69078acdf0a_complete()
;;

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

(fix)
Expand Down
1 change: 1 addition & 0 deletions src/pdm/cli/completions/pdm.fish
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ complete -c pdm -A -n '__fish_seen_subcommand_from export' -l group -d 'Select g
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l help -d 'Show this help message and exit.'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l lockfile -d 'Specify another lockfile path. Default: pdm.lock. [env var: PDM_LOCKFILE]'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l no-default -d 'Don\'t include dependencies from the default group'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l no-extras -d 'Strip extras from the requirements'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l no-markers -d 'Don\'t include platform markers'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l output -d 'Write output to the given file, or print to stdout if not given'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l production -d 'Unselect dev dependencies'
Expand Down
2 changes: 1 addition & 1 deletion src/pdm/cli/completions/pdm.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ function TabExpansion($line, $lastWord) {
$completer.AddOpts(@(
[Option]::new(@(
"--dev", "--output", "--global", "--no-default", "--expandvars", "--prod", "--production", "-g", "-d", "-o",
"--no-hashes", "--no-markers", "-L", "--lockfile", "--self", "--editable-self"
"--no-hashes", "--no-markers", "-L", "--lockfile", "--self", "--editable-self", "--no-extras"
)),
$formatOption,
$sectionOption,
Expand Down
1 change: 1 addition & 0 deletions src/pdm/cli/completions/pdm.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ _pdm() {
{-f+,--format+}"[Only requirements.txt is supported for now.]:format:(requirements)"
"--no-hashes[Don't include artifact hashes]"
"--no-markers[Don't include platform markers]"
"--no-extras[Strip extras from the requirements]"
"--expandvars[Expand environment variables in requirements]"
"--self[Include the project itself]"
"--editable-self[Include the project itself as an editable dependency]"
Expand Down
11 changes: 7 additions & 4 deletions tests/cli/test_others.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,16 @@ def test_export_to_requirements_txt(pdm, fixture_project):
assert (project.root / "requirements_output.txt").read_text() == requirements_txt.read_text()


def test_export_doesnt_include_dep_with_extras(pdm, fixture_project):
@pytest.mark.parametrize("extra_opt", [[], ["--no-extras"]])
def test_export_doesnt_include_dep_with_extras(pdm, fixture_project, extra_opt):
project = fixture_project("demo-package-has-dep-with-extras")
requirements_txt = project.root / "requirements.txt"

result = pdm(["export", "--without-hashes"], obj=project)
result = pdm(["export", "--without-hashes", *extra_opt], obj=project)
assert result.exit_code == 0
assert result.output.strip() == requirements_txt.read_text().strip()
if extra_opt:
assert "requests==2.26.0" in result.output.splitlines()
else:
assert "requests[security]==2.26.0" in result.output.splitlines()


def test_completion_command(pdm):
Expand Down

0 comments on commit 34d1ad5

Please sign in to comment.