Skip to content

Commit

Permalink
fix: pre_install/post_install receiving a generator not a list (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
PKilcommons authored Sep 29, 2024
1 parent f184054 commit 8dc3ae7
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
1 change: 1 addition & 0 deletions news/3190.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix the `pre_install` and `post_install` signals receiving an exhausted generator, instead of a list of packages.
2 changes: 1 addition & 1 deletion src/pdm/cli/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def do_sync(
selection.validate()
for group in selection:
requirements.extend(project.get_dependencies(group))
packages = resolve_from_lockfile(project, requirements, groups=list(selection))
packages = list(resolve_from_lockfile(project, requirements, groups=list(selection)))
if tracked_names and dry_run:
packages = [p for p in packages if p.candidate.identify() in tracked_names]
synchronizer = project.get_synchronizer()(
Expand Down
83 changes: 83 additions & 0 deletions tests/test_signals.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from itertools import chain
from unittest import mock

import pytest

from pdm import signals
from pdm.models.candidates import Candidate
from pdm.models.repositories import Package
from pdm.models.requirements import Requirement


def test_post_init_signal(project_no_init, pdm):
Expand All @@ -26,3 +30,82 @@ def test_post_lock_and_install_signals(project, pdm):
signals.post_install.disconnect(post_install)
for mocker in (pre_lock, post_lock, pre_install, post_install):
mocker.assert_called_once()


@pytest.mark.usefixtures("working_set")
def test_lock_and_install_signals_injection_with_add(project, pdm):
pre_lock = signals.pre_lock.connect(mock.Mock(), weak=False)
post_lock = signals.post_lock.connect(mock.Mock(), weak=False)
pre_install = signals.pre_install.connect(mock.Mock(), weak=False)
post_install = signals.post_install.connect(mock.Mock(), weak=False)
pdm(["add", "requests"], obj=project, strict=True)
signals.pre_lock.disconnect(pre_lock)
signals.post_lock.disconnect(post_lock)
signals.pre_install.disconnect(pre_install)
signals.post_install.disconnect(post_install)

assert isinstance(pre_lock.call_args.kwargs["requirements"], list)
assert all(isinstance(e, Requirement) for e in pre_lock.call_args.kwargs["requirements"])
assert len(pre_lock.call_args.kwargs["requirements"]) == 1

assert isinstance(post_lock.call_args.kwargs["resolution"], dict)
assert all(isinstance(e, Candidate) for e in chain.from_iterable(post_lock.call_args.kwargs["resolution"].values()))
assert len(post_lock.call_args.kwargs["resolution"]) == 5

assert isinstance(pre_install.call_args.kwargs["packages"], list)
assert all(isinstance(e, Package) for e in pre_install.call_args.kwargs["packages"])
assert len(pre_install.call_args.kwargs["packages"]) == 5

assert isinstance(post_install.call_args.kwargs["packages"], list)
assert all(isinstance(e, Package) for e in post_install.call_args.kwargs["packages"])
assert len(post_install.call_args.kwargs["packages"]) == 5


@pytest.mark.usefixtures("working_set")
def test_lock_and_install_signals_injection_with_install(project, pdm):
project.add_dependencies(["requests"])

pre_lock = signals.pre_lock.connect(mock.Mock(), weak=False)
post_lock = signals.post_lock.connect(mock.Mock(), weak=False)
pre_install = signals.pre_install.connect(mock.Mock(), weak=False)
post_install = signals.post_install.connect(mock.Mock(), weak=False)
pdm(["install"], obj=project, strict=True)
signals.pre_lock.disconnect(pre_lock)
signals.post_lock.disconnect(post_lock)
signals.pre_install.disconnect(pre_install)
signals.post_install.disconnect(post_install)

assert isinstance(pre_lock.call_args.kwargs["requirements"], list)
assert all(isinstance(e, Requirement) for e in pre_lock.call_args.kwargs["requirements"])
assert len(pre_lock.call_args.kwargs["requirements"]) == 1

assert isinstance(post_lock.call_args.kwargs["resolution"], dict)
assert all(isinstance(e, Candidate) for e in chain.from_iterable(post_lock.call_args.kwargs["resolution"].values()))
assert len(post_lock.call_args.kwargs["resolution"]) == 5

assert isinstance(pre_install.call_args.kwargs["packages"], list)
assert all(isinstance(e, Package) for e in pre_install.call_args.kwargs["packages"])
assert len(pre_install.call_args.kwargs["packages"]) == 5

assert isinstance(post_install.call_args.kwargs["packages"], list)
assert all(isinstance(e, Package) for e in post_install.call_args.kwargs["packages"])
assert len(post_install.call_args.kwargs["packages"]) == 5


@pytest.mark.usefixtures("working_set")
def test_lock_signals_injection_with_update(project, pdm):
project.add_dependencies(["requests"])

pre_lock = signals.pre_lock.connect(mock.Mock(), weak=False)
post_lock = signals.post_lock.connect(mock.Mock(), weak=False)
pdm(["update"], obj=project, strict=True)
signals.pre_lock.disconnect(pre_lock)
signals.post_lock.disconnect(post_lock)

assert isinstance(pre_lock.call_args.kwargs["requirements"], list)
assert all(isinstance(e, Requirement) for e in pre_lock.call_args.kwargs["requirements"])
assert len(pre_lock.call_args.kwargs["requirements"]) == 1

assert isinstance(post_lock.call_args.kwargs["resolution"], dict)
assert all(isinstance(e, Candidate) for e in chain.from_iterable(post_lock.call_args.kwargs["resolution"].values()))
assert len(post_lock.call_args.kwargs["resolution"]) == 5

0 comments on commit 8dc3ae7

Please sign in to comment.