Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions packages/cli/src/pywrangler/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,18 @@ def _install_requirements_to_vendor(requirements: list[str]) -> str | None:
f"Installing packages into [bold]{relative_vendor_path}[/bold]...",
extra={"markup": True},
)

# Clear pyodide venv site-packages so stale packages from previous syncs
# don't carry over into python_modules.
pyv = get_python_version()
site_packages_path = (
f"lib/python{pyv}/site-packages" if os.name != "nt" else "Lib/site-packages"
)
pyodide_site_packages = get_pyodide_venv_path() / site_packages_path
if pyodide_site_packages.is_dir():
shutil.rmtree(pyodide_site_packages)
Comment thread
ryanking13 marked this conversation as resolved.
pyodide_site_packages.mkdir()

with temp_requirements_file(requirements) as requirements_file:
result = run_command(
[
Expand All @@ -209,13 +221,8 @@ def _install_requirements_to_vendor(requirements: list[str]) -> str | None:
if result.returncode != 0:
return result.stdout.strip()

pyv = get_python_version()
shutil.rmtree(vendor_path)

site_packages_path = (
f"lib/python{pyv}/site-packages" if os.name != "nt" else "Lib/site-packages"
)
shutil.copytree(get_pyodide_venv_path() / site_packages_path, vendor_path)
shutil.copytree(pyodide_site_packages, vendor_path)

# Create a pyvenv.cfg file in python_modules to mark it as a virtual environment
(vendor_path / "pyvenv.cfg").touch()
Expand Down
35 changes: 35 additions & 0 deletions packages/cli/tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,41 @@ def test_sync_command_integration(dependencies, test_dir): # noqa: C901 (test c
)


def test_sync_removes_stale_packages(test_dir):
"""Test that removing a dependency from pyproject.toml cleans it up from python_modules."""
create_test_wrangler_jsonc(test_dir, "src/worker.py")
sync_cmd = ["uv", "run", "pywrangler", "sync"]

# First sync: install click + six
create_test_pyproject(test_dir, ["click", "six"])
result = subprocess.run(
sync_cmd, capture_output=True, text=True, cwd=test_dir, check=False
)
assert result.returncode == 0, (
f"First sync failed: {result.stdout}\n{result.stderr}"
)

vendor_path = test_dir / "python_modules"
assert is_package_installed(vendor_path, "click")
assert is_package_installed(vendor_path, "six")

# Second sync: remove six, keep click
create_test_pyproject(test_dir, ["click"])
result = subprocess.run(
sync_cmd, capture_output=True, text=True, cwd=test_dir, check=False
)
assert result.returncode == 0, (
f"Second sync failed: {result.stdout}\n{result.stderr}"
)

assert is_package_installed(vendor_path, "click"), (
"click should still be installed after second sync"
)
assert not is_package_installed(vendor_path, "six"), (
"six should have been removed from python_modules after being dropped from dependencies"
)


def test_sync_command_handles_missing_pyproject():
"""Test that the sync command correctly handles a missing pyproject.toml file."""
import tempfile
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/tests/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,5 @@ def test_types(tmp_path):
result = run(["uv", "run", "mypy"], capture_output=True, text=True, check=False)
assert 'Revealed type is "js.Env"' in result.stdout
assert 'Revealed type is "js.KVNamespace_iface"' in result.stdout
assert 'Revealed type is "builtins.str"' in result.stdout
assert 'Revealed type is "str"' in result.stdout
Comment thread
ryanking13 marked this conversation as resolved.
assert "Success: no issues found" in result.stdout
Loading