Repository: tox-dev/tox

Issue:
"IndexError: list index out of range" when using --devenv flag
## Issue
Got following error:

```
tox --devenv venv 

Traceback (most recent call last):
  File "/Users/xzk/.local/bin/tox", line 8, in <module>
    sys.exit(run())
  File "/Users/xzk/.local/pipx/venvs/tox/lib/python3.9/site-packages/tox/run.py", line 19, in run
    result = main(sys.argv[1:] if args is None else args)
  File "/Users/xzk/.local/pipx/venvs/tox/lib/python3.9/site-packages/tox/run.py", line 45, in main
    result = handler(state)
  File "/Users/xzk/.local/pipx/venvs/tox/lib/python3.9/site-packages/tox/session/cmd/legacy.py", line 108, in legacy
    return devenv(state)
  File "/Users/xzk/.local/pipx/venvs/tox/lib/python3.9/site-packages/tox/session/cmd/devenv.py", line 38, in devenv
    state.conf.memory_seed_loaders[list(opt.env)[0]].append(loader)
IndexError: list index out of range
```
```
╰─ which tox
/Users/xzk/.local/bin/tox
```

Tried to execute with `tox` installed in my virtual environment `myenv`

```
which python3                                                                                                                                                                                                                     ─╯
/Users/xzk/workplace/my_project/myenv/bin/python3
```

```console
╰─ python3 -m tox -vvvv --devenv venv-dev 
                                                                                                                                                                                           
ROOT: 275 D setup logging to NOTSET on pid 20334 [tox/report.py:221]
Traceback (most recent call last):
  File "/Users/xzk/opt/anaconda3/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/Users/xzk/opt/anaconda3/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/Users/xzk/workplace/my_project/myenv/lib/python3.9/site-packages/tox/__main__.py", line 6, in <module>
    run()
  File "/Users/xzk/workplace/my_project/myenv/lib/python3.9/site-packages/tox/run.py", line 19, in run
    result = main(sys.argv[1:] if args is None else args)
  File "/Users/xzk/workplace/my_project/myenv/lib/python3.9/site-packages/tox/run.py", line 45, in main
    result = handler(state)
  File "/Users/xzk/workplace/my_project/myenv/lib/python3.9/site-packages/tox/session/cmd/legacy.py", line 108, in legacy
    return devenv(state)
  File "/Users/xzk/workplace/my_project/myenv/lib/python3.9/site-packages/tox/session/cmd/devenv.py", line 38, in devenv
    state.conf.memory_seed_loaders[list(opt.env)[0]].append(loader)
IndexError: list index out of range

```

My `tox.ini`
```
[tox]
envlist = py39
skip_missing_interpreters = True

[testenv]
deps = -e.[test]
commands = pytest {posargs: ../tests/python_tests}
```

My setup.py
```
# setup.py
from setuptools import setup
from setuptools import find_packages

setup(
    name='my_pkg',
    version='0.1.0',
    python_requires=">=3.8.0",
    packages=find_packages(),
    install_requires=["numpy>=1.24.2", "pandas>=1.5.3", "torch>=1.13.1", "tqdm>=4.64.1", "matplotlib>=3.6.3",
                      "scikit-learn>=1.2.1", "pyarrow>=11.0.0"],
    extras_require=dict(
        test=[
            'pytest',
        ]
    ),
)

```

## Environment

Provide at least:

- OS: MacOS Monterry
- `pip list` of the host Python where `tox` is installed:

```console
╰─ pip list                                                                                                                                                                                                                          ─╯
Package           Version
----------------- --------
attrs             22.2.0
cachetools        5.3.0
chardet           5.1.0
colorama          0.4.6
contourpy         1.0.7
cycler            0.11.0
distlib           0.3.6
exceptiongroup    1.1.0
filelock          3.9.0
fonttools         4.38.0
iniconfig         2.0.0
joblib            1.2.0
kiwisolver        1.4.4
matplotlib        3.6.3
numpy             1.24.2
packaging         23.0
pandas            1.5.3
Pillow            9.4.0
pip               23.0
platformdirs      3.0.0
pluggy            1.0.0
pyarrow           11.0.0
pyparsing         3.0.9
pyproject_api     1.5.0
pytest            7.2.1
pytest-mock       3.10.0
python-dateutil   2.8.2
pytz              2022.7.1
scikit-learn      1.2.1
scipy             1.10.0
setuptools        58.1.0
six               1.16.0
threadpoolctl     3.1.0
tomli             2.0.1
torch             1.13.1
tox               4.4.5
tqdm              4.64.1
typing_extensions 4.4.0
virtualenv        20.19.
```

## Output of running tox

Provide the output of `tox -rvv`:
Please see above.


## Minimal example

If possible, provide a minimal reproducer for the issue:

```console

```


Discussion:

Patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 43128a4a..dac77aba 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -17,7 +17,7 @@ repos:
       - id: add-trailing-comma
         args: [--py36-plus]
   - repo: https://github.com/asottile/pyupgrade
-    rev: v3.3.1
+    rev: v3.4.0
     hooks:
       - id: pyupgrade
         args: ["--py37-plus"]
@@ -52,7 +52,7 @@ repos:
     hooks:
       - id: flake8
         additional_dependencies:
-          - flake8-bugbear==23.3.23
+          - flake8-bugbear==23.5.9
           - flake8-comprehensions==3.12
           - flake8-pytest-style==1.7.2
           - flake8-spellcheck==0.28
@@ -69,7 +69,7 @@ repos:
           - "@prettier/plugin-xml@2.2"
         args: ["--print-width=120", "--prose-wrap=always"]
   - repo: https://github.com/igorshubovych/markdownlint-cli
-    rev: v0.33.0
+    rev: v0.34.0
     hooks:
       - id: markdownlint
   - repo: local
diff --git a/docs/changelog/2925.bugfix.rst b/docs/changelog/2925.bugfix.rst
new file mode 100644
index 00000000..f74003a9
--- /dev/null
+++ b/docs/changelog/2925.bugfix.rst
@@ -0,0 +1,1 @@
+Fix ``tox --devenv venv`` invocation without ``-e`` - by :user:`asottile`.
diff --git a/pyproject.toml b/pyproject.toml
index 87c2ce55..82810864 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -2,7 +2,7 @@
 build-backend = "hatchling.build"
 requires = [
   "hatch-vcs>=0.3",
-  "hatchling>=1.14",
+  "hatchling>=1.17",
 ]
 
 [project]
@@ -51,23 +51,23 @@ dependencies = [
   "cachetools>=5.3",
   "chardet>=5.1",
   "colorama>=0.4.6",
-  "filelock>=3.11",
-  'importlib-metadata>=6.4.1; python_version < "3.8"',
+  "filelock>=3.12",
+  'importlib-metadata>=6.6; python_version < "3.8"',
   "packaging>=23.1",
-  "platformdirs>=3.2",
+  "platformdirs>=3.5.1",
   "pluggy>=1",
   "pyproject-api>=1.5.1",
   'tomli>=2.0.1; python_version < "3.11"',
-  'typing-extensions>=4.5; python_version < "3.8"',
-  "virtualenv>=20.21",
+  'typing-extensions>=4.6.2; python_version < "3.8"',
+  "virtualenv>=20.23",
 ]
 optional-dependencies.docs = [
-  "furo>=2023.3.27",
-  "sphinx>=6.1.3",
+  "furo>=2023.5.20",
+  "sphinx>=7.0.1",
   "sphinx-argparse-cli>=1.11",
   "sphinx-autodoc-typehints!=1.23.4,>=1.23",
   "sphinx-copybutton>=0.5.2",
-  "sphinx-inline-tabs>=2022.1.2b11",
+  "sphinx-inline-tabs>=2023.4.21",
   "sphinxcontrib-towncrier>=0.2.1a0",
   "towncrier>=22.12",
 ]
@@ -79,12 +79,12 @@ optional-dependencies.testing = [
   "distlib>=0.3.6",
   "flaky>=3.7",
   "hatch-vcs>=0.3",
-  "hatchling>=1.14",
-  "psutil>=5.9.4",
+  "hatchling>=1.17",
+  "psutil>=5.9.5",
   "pytest>=7.3.1",
-  "pytest-cov>=4",
+  "pytest-cov>=4.1",
   "pytest-mock>=3.10",
-  "pytest-xdist>=3.2.1",
+  "pytest-xdist>=3.3.1",
   "re-assert>=1.1",
   'time-machine>=2.9; implementation_name != "pypy"',
   "wheel>=0.40",
diff --git a/src/tox/session/cmd/legacy.py b/src/tox/session/cmd/legacy.py
index e92c3d27..82938d13 100644
--- a/src/tox/session/cmd/legacy.py
+++ b/src/tox/session/cmd/legacy.py
@@ -104,6 +104,8 @@ def legacy(state: State) -> int:
     if option.list_envs or option.list_envs_all:
         return list_env(state)
     if option.devenv_path:
+        if option.env.is_default_list:
+            option.env = CliEnv(["py"])
         option.devenv_path = Path(option.devenv_path)
         return devenv(state)
     if option.parallel != 0:  # only 0 means sequential
diff --git a/tox.ini b/tox.ini
index 13810f63..cf0a2b92 100644
--- a/tox.ini
+++ b/tox.ini
@@ -41,7 +41,7 @@ commands =
 description = format the code base to adhere to our styles, and complain about what we cannot do automatically
 skip_install = true
 deps =
-    pre-commit>=3.2.2
+    pre-commit>=3.3.2
 pass_env =
     {[testenv]passenv}
     PROGRAMDATA
@@ -52,9 +52,9 @@ commands =
 [testenv:type]
 description = run type check on code base
 deps =
-    mypy==1.2
+    mypy==1.3
     types-cachetools>=5.3.0.5
-    types-chardet>=5.0.4.3
+    types-chardet>=5.0.4.6
 commands =
     mypy src/tox
     mypy tests


Test patch:
diff --git a/tests/session/cmd/test_legacy.py b/tests/session/cmd/test_legacy.py
index 957149b6..73cc397a 100644
--- a/tests/session/cmd/test_legacy.py
+++ b/tests/session/cmd/test_legacy.py
@@ -78,14 +78,27 @@ def test_legacy_list_all(tox_project: ToxProjectCreator, mocker: MockerFixture,
     assert outcome.state.conf.options.show_core is False
 
 
-def test_legacy_devenv(tox_project: ToxProjectCreator, mocker: MockerFixture, tmp_path: Path) -> None:
-    devenv = mocker.patch("tox.session.cmd.legacy.devenv")
+@pytest.mark.parametrize(
+    "args",
+    [
+        pytest.param((), id="empty"),
+        pytest.param(("-e", "py"), id="select"),
+    ],
+)
+def test_legacy_devenv(
+    tox_project: ToxProjectCreator,
+    mocker: MockerFixture,
+    tmp_path: Path,
+    args: tuple[str, ...],
+) -> None:
+    run_sequential = mocker.patch("tox.session.cmd.devenv.run_sequential")
     into = tmp_path / "b"
 
-    outcome = tox_project({"tox.ini": ""}).run("le", "--devenv", str(into), "-e", "py")
+    outcome = tox_project({"tox.ini": ""}).run("le", "--devenv", str(into), *args)
 
-    assert devenv.call_count == 1
+    assert run_sequential.call_count == 1
     assert outcome.state.conf.options.devenv_path == into
+    assert set(outcome.state.conf.options.env) == {"py"}
 
 
 def test_legacy_run_parallel(tox_project: ToxProjectCreator, mocker: MockerFixture) -> None: