Repository: pdm-project/pdm

Issue:
Add project path argument while running pdm venv command
## Is your feature request related to a problem? Please describe.

I often find it frustrating when trying to run the pdm venv command without being able to specify the project path. Currently, the command assumes that the project is located in the current working directory, which can be inconvenient in certain scenarios.

## Describe the solution you'd like

I would like to propose adding a project path argument to the pdm venv command. This would allow users to specify the path to their project directory when creating a virtual environment. This feature would provide more flexibility and convenience, especially for projects that are not located in the current working directory.

By adding the project path argument, users can easily create virtual environments for projects located in different directories without having to navigate to each project's directory first. This would streamline the workflow and save time for developers working with multiple projects simultaneously.

Overall, the addition of the project path argument to the pdm venv command would greatly enhance the usability and flexibility of the PDM tool.


Discussion:

Patch:
diff --git a/news/2042.feature.md b/news/2042.feature.md
new file mode 100644
index 00000000..3df0d517
--- /dev/null
+++ b/news/2042.feature.md
@@ -0,0 +1,1 @@
+Add `--project` option to `pdm venv` to support another path as the project root.
diff --git a/src/pdm/cli/commands/venv/__init__.py b/src/pdm/cli/commands/venv/__init__.py
index 0e156d2e..b28e881f 100644
--- a/src/pdm/cli/commands/venv/__init__.py
+++ b/src/pdm/cli/commands/venv/__init__.py
@@ -9,7 +9,7 @@ from pdm.cli.commands.venv.list import ListCommand
 from pdm.cli.commands.venv.purge import PurgeCommand
 from pdm.cli.commands.venv.remove import RemoveCommand
 from pdm.cli.commands.venv.utils import get_venv_with_name
-from pdm.cli.options import Option
+from pdm.cli.options import project_option
 from pdm.project import Project
 
 
@@ -17,7 +17,7 @@ class Command(BaseCommand):
     """Virtualenv management"""
 
     name = "venv"
-    arguments: list[Option] = []
+    arguments = [project_option]
 
     def add_arguments(self, parser: argparse.ArgumentParser) -> None:
         group = parser.add_mutually_exclusive_group()


Test patch:
diff --git a/tests/cli/test_venv.py b/tests/cli/test_venv.py
index 046bf97f..49139194 100644
--- a/tests/cli/test_venv.py
+++ b/tests/cli/test_venv.py
@@ -50,6 +50,16 @@ def test_venv_create_in_project(pdm, project):
     assert "is not empty" in result.stderr
 
 
+@pytest.mark.usefixtures("fake_create")
+def test_venv_create_other_location(pdm, project):
+    pdm(["venv", "-p", project.root.as_posix(), "create"], strict=True)
+    venv_path = project.root / ".venv"
+    assert venv_path.exists()
+    result = pdm(["venv", "-p", project.root.as_posix(), "create"])
+    assert result.exit_code == 1
+    assert "is not empty" in result.stderr
+
+
 @pytest.mark.usefixtures("fake_create")
 def test_venv_show_path(pdm, project):
     project.project_config["venv.in_project"] = True