Repository: spack/spack

Issue:
Updating view ==> Error: not enough values to unpack (expected at least 1, got 0)
### Steps to reproduce

```console
docker run --rm -it spack/ubuntu-jammy:develop
spack env create timemory
spack env activate timemory
spack add timemory ~python
spack install 
```

### Error message

```console
==> Installing timemory-3.2.3-riy6uoxcmxns44ois6eig5mtv2j74t64 [18/18]
==> No binary for timemory-3.2.3-riy6uoxcmxns44ois6eig5mtv2j74t64 found: installing from source
==> No patches needed for timemory
==> timemory: Executing phase: 'cmake'
==> timemory: Executing phase: 'build'
==> timemory: Executing phase: 'install'
==> timemory: Successfully installed timemory-3.2.3-riy6uoxcmxns44ois6eig5mtv2j74t64
  Stage: 21.66s.  Cmake: 6.22s.  Build: 6m 3.51s.  Install: 0.42s.  Post-install: 0.32s.  Total: 6m 32.37s
[+] /opt/spack/opt/spack/linux-ubuntu22.04-skylake/gcc-11.4.0/timemory-3.2.3-riy6uoxcmxns44ois6eig5mtv2j74t64
==> Updating view at /opt/spack/var/spack/environments/timemory/.spack-env/view
==> Error: not enough values to unpack (expected at least 1, got 0)
```

### Information on your system

* **Spack:** 0.22.0.dev0 (762833a663ba67868ff2e715ec1ccd3c7538b3d9)
* **Python:** 3.10.12
* **Platform:** linux-ubuntu22.04-skylake
* **Concretizer:** clingo

### General information

- [X] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [X] I have searched the issues of this repo and believe this is not a duplicate
- [X] I have run the failing commands in debug mode and reported the output

### Debug output

```console
# $SPACK_ROOT/bin/spack -d env view regenerate
==> [2024-05-10-00:03:19.376388] Reading config from file /opt/spack/etc/spack/defaults/config.yaml
==> [2024-05-10-00:03:19.449045] Reading config from file /opt/spack/var/spack/environments/timemory/spack.yaml
==> [2024-05-10-00:03:19.495605] Using environment 'timemory'
==> [2024-05-10-00:03:19.513738] Imported env from built-in commands
==> [2024-05-10-00:03:19.525326] Imported env from built-in commands
==> [2024-05-10-00:03:19.527235] DATABASE LOCK TIMEOUT: 60s
==> [2024-05-10-00:03:19.527358] PACKAGE LOCK TIMEOUT: No timeout
==> [2024-05-10-00:03:19.535950] Reading config from file /opt/spack/etc/spack/defaults/repos.yaml
==> [2024-05-10-00:03:19.826738] Updating view at /opt/spack/var/spack/environments/timemory/.spack-env/view
==> [2024-05-10-00:03:19.992538] Reading config from file /opt/spack/etc/spack/defaults/packages.yaml
==> [2024-05-10-00:03:20.091565] Reading config from file /opt/spack/etc/spack/defaults/linux/packages.yaml
==> [2024-05-10-00:03:20.119020] Creating 79 dirs and 630 links
Traceback (most recent call last):
  File "/opt/spack/bin/spack", line 52, in <module>
    sys.exit(main())
  File "/opt/spack/lib/spack/spack_installable/main.py", line 42, in main
    sys.exit(spack.main.main(argv))
  File "/opt/spack/lib/spack/spack/main.py", line 1069, in main
    return _main(argv)
  File "/opt/spack/lib/spack/spack/main.py", line 1022, in _main
    return finish_parse_and_run(parser, cmd_name, args, env_format_error)
  File "/opt/spack/lib/spack/spack/main.py", line 1052, in finish_parse_and_run
    return _invoke_command(command, parser, args, unknown)
  File "/opt/spack/lib/spack/spack/main.py", line 649, in _invoke_command
    return_val = command(parser, args)
  File "/opt/spack/lib/spack/spack/cmd/env.py", line 925, in env
    action(args)
  File "/opt/spack/lib/spack/spack/cmd/env.py", line 651, in env_view
    env.regenerate_views()
  File "/opt/spack/lib/spack/spack/environment/environment.py", line 1780, in regenerate_views
    view.regenerate(self.concrete_roots())
  File "/opt/spack/lib/spack/spack/environment/environment.py", line 795, in regenerate
    view.add_specs(*specs)
  File "/opt/spack/lib/spack/spack/filesystem_view.py", line 708, in add_specs
    spec.package.add_files_to_view(self, merge_map, skip_if_exists=False)
  File "/opt/spack/lib/spack/spack/build_systems/python.py", line 149, in add_files_to_view
    python = self.python_spec
  File "/opt/spack/lib/spack/spack/build_systems/python.py", line 126, in python_spec
    python, *_ = self.spec.dependencies("python-venv") or self.spec.dependencies("python")
ValueError: not enough values to unpack (expected at least 1, got 0)
```


Discussion:
This appears caused by `timemory` being a `PythonExtension` package with default `~python` and therefore no `^python` to be used in https://github.com/spack/spack/blob/b79761b7eb5eb2e2d6b8174c3043524462772bf6/lib/spack/spack/build_systems/python.py#L126

Resolving patch:
diff --git a/lib/spack/spack/build_systems/python.py b/lib/spack/spack/build_systems/python.py
--- a/lib/spack/spack/build_systems/python.py
+++ b/lib/spack/spack/build_systems/python.py
@@ -120,12 +120,6 @@ def skip_modules(self) -> Iterable[str]:
         """
         return []
 
-    @property
-    def python_spec(self):
-        """Get python-venv if it exists or python otherwise."""
-        python, *_ = self.spec.dependencies("python-venv") or self.spec.dependencies("python")
-        return python
-
     def view_file_conflicts(self, view, merge_map):
         """Report all file conflicts, excepting special cases for python.
         Specifically, this does not report errors for duplicate
@@ -146,8 +140,12 @@ def view_file_conflicts(self, view, merge_map):
     def add_files_to_view(self, view, merge_map, skip_if_exists=True):
         # Patch up shebangs if the package extends Python and we put a Python interpreter in the
         # view.
-        python = self.python_spec
-        if not self.extendee_spec or python.external:
+        if not self.extendee_spec:
+            return super().add_files_to_view(view, merge_map, skip_if_exists)
+
+        python, *_ = self.spec.dependencies("python-venv") or self.spec.dependencies("python")
+
+        if python.external:
             return super().add_files_to_view(view, merge_map, skip_if_exists)
 
         # We only patch shebangs in the bin directory.
@@ -368,6 +366,12 @@ def list_url(cls) -> Optional[str]:  # type: ignore[override]
             return f"https://pypi.org/simple/{name}/"
         return None
 
+    @property
+    def python_spec(self):
+        """Get python-venv if it exists or python otherwise."""
+        python, *_ = self.spec.dependencies("python-venv") or self.spec.dependencies("python")
+        return python
+
     @property
     def headers(self) -> HeaderList:
         """Discover header files in platlib."""


Test patch: