hatch icon indicating copy to clipboard operation
hatch copied to clipboard

"hatch test -py 3.14 --cover" crashes with IndexError

Open jwatson0 opened this issue 2 months ago • 1 comments

Even though I have 3.14 included in tool.hatch.envs.test.matrix in pyproject.toml, I get a crash when running hatch test -py 3.14 --cover. It's specific to 3.14 and --cover.

$ hatch --version
Hatch, version 1.14.2
[[tool.hatch.envs.test.matrix]]
python = ["3.12", "3.13", "3.14"]
$ hatch test -py 3.14 --cover
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/jwatson/.pyenv/versions/3.14.0/lib/python3.14/site-packages/hatch/cli/__init__.py:221 in   │
│ main                                                                                             │
│                                                                                                  │
│   218                                                                                            │
│   219 def main():  # no cov                                                                      │
│   220 │   try:                                                                                   │
│ ❱ 221 │   │   hatch(prog_name='hatch', windows_expand_args=False)                                │
│   222 │   except Exception:  # noqa: BLE001                                                      │
│   223 │   │   import sys                                                                         │
│   224                                                                                            │
│                                                                                                  │
│ /home/jwatson/.pyenv/versions/3.14.0/lib/python3.14/site-packages/click/core.py:1462 in __call__ │
│                                                                                                  │
│ /home/jwatson/.pyenv/versions/3.14.0/lib/python3.14/site-packages/click/core.py:1383 in main     │
│                                                                                                  │
│ /home/jwatson/.pyenv/versions/3.14.0/lib/python3.14/site-packages/click/core.py:1850 in invoke   │
│                                                                                                  │
│ /home/jwatson/.pyenv/versions/3.14.0/lib/python3.14/site-packages/click/core.py:1246 in invoke   │
│                                                                                                  │
│ /home/jwatson/.pyenv/versions/3.14.0/lib/python3.14/site-packages/click/core.py:814 in invoke    │
│                                                                                                  │
│ /home/jwatson/.pyenv/versions/3.14.0/lib/python3.14/site-packages/click/decorators.py:34 in      │
│ new_func                                                                                         │
│                                                                                                  │
│ /home/jwatson/.pyenv/versions/3.14.0/lib/python3.14/site-packages/hatch/cli/test/__init__.py:199 │
│ in test                                                                                          │
│                                                                                                  │
│   196 │   │   │   context.env_vars['COVERAGE_PROCESS_START'] = coverage_config_file              │
│   197 │                                                                                          │
│   198 │   if cover:                                                                              │
│ ❱ 199 │   │   for context in app.runner_context([selected_envs[0]]):                             │
│   200 │   │   │   context.add_shell_command('cov-combine')                                       │
│   201 │   │                                                                                      │
│   202 │   │   if not cover_quiet:                                                                │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
IndexError: list index out of range

PR https://github.com/pypa/hatch/pull/2080 fixes it for me.

jwatson0 avatar Oct 09 '25 18:10 jwatson0

Further testing shows that hatch test -py 3.14 (without --cover) just exits without doing anything. Same fix.

jwatson0 avatar Oct 09 '25 18:10 jwatson0

With hatch hatch-1.16.2 I also have issue with 3.14.2 installed via py with the installed python (and scripts) not in path.

Now when I try to run py -m hatch test on pyawaitable to run the tests to debug why it fails in the github actions for meson I get this error as well: (Note: I do have 3.12 installed as well, but never installed 2.7...

PEP-514 violation in Windows Registry at HKEY_CURRENT_USER/PythonCore/3.12/InstallPath error: missing
PEP-514 violation in Windows Registry at HKEY_LOCAL_MACHINE/PythonCore/2.7/InstallPath error: missing
PEP-514 violation in Windows Registry at HKEY_CURRENT_USER/PythonCore/3.12/InstallPath error: missing
PEP-514 violation in Windows Registry at HKEY_LOCAL_MACHINE/PythonCore/2.7/InstallPath error: missing
PEP-514 violation in Windows Registry at HKEY_CURRENT_USER/PythonCore/3.12/InstallPath error: missing
PEP-514 violation in Windows Registry at HKEY_LOCAL_MACHINE/PythonCore/2.7/InstallPath error: missing
C:\Users\user\AppData\Roaming\Python\Python314\site-packages\anyio\from_thread.py:119: SyntaxWarning: 'return' in a 'finally' block
  return result
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\cli\__init__.py:2  │
│ 29 in main                                                                                       │
│                                                                                                  │
│   226                                                                                            │
│   227 def main():  # no cov                                                                      │
│   228 │   try:                                                                                   │
│ ❱ 229 │   │   hatch(prog_name="hatch", windows_expand_args=False)                                │
│   230 │   except Exception:  # noqa: BLE001                                                      │
│   231 │   │   import sys                                                                         │
│   232                                                                                            │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\click\core.py:1161 in __call__      │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\click\core.py:1082 in main          │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\click\core.py:1697 in invoke        │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\click\core.py:1443 in invoke        │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\click\core.py:788 in invoke         │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\click\decorators.py:33 in new_func  │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\cli\test\__init__  │
│ .py:163 in test                                                                                  │
│                                                                                                  │
│   160 │   if cover:                                                                              │
│   161 │   │   patched_coverage.write_config_file()                                               │
│   162 │                                                                                          │
│ ❱ 163 │   for context in app.runner_context(selected_envs, ignore_compat=multiple_possible, di   │
│   164 │   │   internal_arguments: list[str] = list(context.env.config.get("extra-args", []))     │
│   165 │   │                                                                                      │
│   166 │   │   if not context.env.config.get("randomize", randomize):                             │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\cli\application.p  │
│ y:120 in runner_context                                                                          │
│                                                                                                  │
│   117 │   │   │   │   context = ExecutionContext(environment)                                    │
│   118 │   │   │   │   yield context                                                              │
│   119 │   │   │   │                                                                              │
│ ❱ 120 │   │   │   │   self.prepare_environment(environment)                                      │
│   121 │   │   │   │   self.execute_context(context)                                              │
│   122 │   │                                                                                      │
│   123 │   │   if incompatible:                                                                   │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\cli\application.p  │
│ y:51 in prepare_environment                                                                      │
│                                                                                                  │
│    48 │   │   return self.project.get_environment(env_name)                                      │
│    49 │                                                                                          │
│    50 │   def prepare_environment(self, environment: EnvironmentInterface):                      │
│ ❱  51 │   │   self.project.prepare_environment(environment)                                      │
│    52 │                                                                                          │
│    53 │   def run_shell_commands(self, context: ExecutionContext) -> None:                       │
│    54 │   │   with context.env.command_context():                                                │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\project\core.py:1  │
│ 90 in prepare_environment                                                                        │
│                                                                                                  │
│   187 │   │   │   self.env_metadata.reset(environment)                                           │
│   188 │   │   │                                                                                  │
│   189 │   │   │   with environment.app_status_creation():                                        │
│ ❱ 190 │   │   │   │   environment.create()                                                       │
│   191 │   │   │                                                                                  │
│   192 │   │   │   if not environment.skip_install:                                               │
│   193 │   │   │   │   if environment.pre_install_commands:                                       │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\env\virtual.py:17  │
│ 0 in create                                                                                      │
│                                                                                                  │
│   167 │   │   │   │   )                                                                          │
│   168 │   │                                                                                      │
│   169 │   │   with self.expose_uv():                                                             │
│ ❱ 170 │   │   │   self.virtual_env.create(self.parent_python, allow_system_packages=self.confi   │
│   171 │                                                                                          │
│   172 │   def remove(self):                                                                      │
│   173 │   │   self.virtual_env.remove()                                                          │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\functools.py:1126 in __get__           │
│                                                                                                  │
│   1123 │   │   │   raise TypeError(msg) from None                                                │
│   1124 │   │   val = cache.get(self.attrname, _NOT_FOUND)                                        │
│   1125 │   │   if val is _NOT_FOUND:                                                             │
│ ❱ 1126 │   │   │   val = self.func(instance)                                                     │
│   1127 │   │   │   try:                                                                          │
│   1128 │   │   │   │   cache[self.attrname] = val                                                │
│   1129 │   │   │   except TypeError:                                                             │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\env\virtual.py:28  │
│ 7 in parent_python                                                                               │
│                                                                                                  │
│   284 │   @cached_property                                                                       │
│   285 │   def parent_python(self):                                                               │
│   286 │   │   if python_choice := self.config.get("python", ""):                                 │
│ ❱ 287 │   │   │   return self._get_concrete_interpreter_path(python_choice)                      │
│   288 │   │                                                                                      │
│   289 │   │   if explicit_default := os.environ.get(AppEnvVars.PYTHON):                          │
│   290 │   │   │   return sys.executable if explicit_default == "self" else explicit_default      │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\env\virtual.py:33  │
│ 6 in _get_concrete_interpreter_path                                                              │
│                                                                                                  │
│   333 │   │   resolvers = [known_resolvers[source] for source in self._python_sources]           │
│   334 │   │   if python_version:                                                                 │
│   335 │   │   │   for resolver in resolvers:                                                     │
│ ❱ 336 │   │   │   │   if (concrete_path := resolver(python_version)) is not None:                │
│   337 │   │   │   │   │   return concrete_path                                                   │
│   338 │   │   else:                                                                              │
│   339 │   │   │   # Prefer the Python version Hatch is currently using                           │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\env\virtual.py:36  │
│ 1 in _resolve_internal_interpreter_path                                                          │
│                                                                                                  │
│   358 │   def _resolve_internal_interpreter_path(self, python_version: str) -> str | None:       │
│   359 │   │   if (available_distribution := self._get_available_distribution(python_version))    │
│   360 │   │   │   with self.app.status(f"Installing Python distribution: {available_distributi   │
│ ❱ 361 │   │   │   │   dist = self.python_manager.install(available_distribution)                 │
│   362 │   │   │                                                                                  │
│   363 │   │   │   return str(dist.python_path)                                                   │
│   364                                                                                            │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\python\core.py:94  │
│ in install                                                                                       │
│                                                                                                  │
│    91 │   │   with temp_directory() as temp_dir:                                                 │
│    92 │   │   │   archive_path = temp_dir / dist.archive_name                                    │
│    93 │   │   │   unpack_path = temp_dir / identifier                                            │
│ ❱  94 │   │   │   download_file(archive_path, dist.source, follow_redirects=True)                │
│    95 │   │   │   dist.unpack(archive_path, unpack_path)                                         │
│    96 │   │   │                                                                                  │
│    97 │   │   │   backup_path = path.with_suffix(".bak")                                         │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\utils\network.py:  │
│ 48 in download_file                                                                              │
│                                                                                                  │
│   45 def download_file(path: Path, *args: Any, **kwargs: Any) -> None:                           │
│   46 │   kwargs.setdefault("timeout", DEFAULT_TIMEOUT)                                           │
│   47 │                                                                                           │
│ ❱ 48 │   with path.open(mode="wb", buffering=0) as f, streaming_response("GET", *args, **kwar    │
│   49 │   │   for chunk in response.iter_bytes(16384):                                            │
│   50 │   │   │   f.write(chunk)                                                                  │
│   51                                                                                             │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:141 in __enter__         │
│                                                                                                  │
│   138 │   │   # they are only needed for recreation, which is not possible anymore               │
│   139 │   │   del self.args, self.kwds, self.func                                                │
│   140 │   │   try:                                                                               │
│ ❱ 141 │   │   │   return next(self.gen)                                                          │
│   142 │   │   except StopIteration:                                                              │
│   143 │   │   │   raise RuntimeError("generator didn't yield") from None                         │
│   144                                                                                            │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages\hatch\utils\network.py:  │
│ 32 in streaming_response                                                                         │
│                                                                                                  │
│   29 │   while True:                                                                             │
│   30 │   │   attempts += 1                                                                       │
│   31 │   │   try:                                                                                │
│ ❱ 32 │   │   │   with httpx.stream(*args, **kwargs) as response:                                 │
│   33 │   │   │   │   response.raise_for_status()                                                 │
│   34 │   │   │   │   yield response                                                              │
│   35                                                                                             │
│                                                                                                  │
│ C:\Users\user\AppData\Local\Python\pythoncore-3.14-64\Lib\contextlib.py:141 in __enter__         │
│                                                                                                  │
│   138 │   │   # they are only needed for recreation, which is not possible anymore               │
│   139 │   │   del self.args, self.kwds, self.func                                                │
│   140 │   │   try:                                                                               │
│ ❱ 141 │   │   │   return next(self.gen)                                                          │
│   142 │   │   except StopIteration:                                                              │
│   143 │   │   │   raise RuntimeError("generator didn't yield") from None                         │
│   144                                                                                            │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\httpx\_api.py:152 in stream         │
│                                                                                                  │
│   149 │                                                                                          │
│   150 │   [0]: /quickstart#streaming-responses                                                   │
│   151 │   """                                                                                    │
│ ❱ 152 │   with Client(                                                                           │
│   153 │   │   cookies=cookies,                                                                   │
│   154 │   │   proxy=proxy,                                                                       │
│   155 │   │   verify=verify,                                                                     │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\httpx\_client.py:688 in __init__    │
│                                                                                                  │
│    685 │   │   allow_env_proxies = trust_env and transport is None                               │
│    686 │   │   proxy_map = self._get_proxy_map(proxy, allow_env_proxies)                         │
│    687 │   │                                                                                     │
│ ❱  688 │   │   self._transport = self._init_transport(                                           │
│    689 │   │   │   verify=verify,                                                                │
│    690 │   │   │   cert=cert,                                                                    │
│    691 │   │   │   trust_env=trust_env,                                                          │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\httpx\_client.py:731 in             │
│ _init_transport                                                                                  │
│                                                                                                  │
│    728 │   │   if transport is not None:                                                         │
│    729 │   │   │   return transport                                                              │
│    730 │   │                                                                                     │
│ ❱  731 │   │   return HTTPTransport(                                                             │
│    732 │   │   │   verify=verify,                                                                │
│    733 │   │   │   cert=cert,                                                                    │
│    734 │   │   │   trust_env=trust_env,                                                          │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\httpx\_transports\default.py:150    │
│ in __init__                                                                                      │
│                                                                                                  │
│   147 │   │   retries: int = 0,                                                                  │
│   148 │   │   socket_options: typing.Iterable[SOCKET_OPTION] | None = None,                      │
│   149 │   ) -> None:                                                                             │
│ ❱ 150 │   │   import httpcore                                                                    │
│   151 │   │                                                                                      │
│   152 │   │   proxy = Proxy(url=proxy) if isinstance(proxy, (str, URL)) else proxy               │
│   153 │   │   ssl_context = create_ssl_context(verify=verify, cert=cert, trust_env=trust_env)    │
│                                                                                                  │
│ C:\Users\user\AppData\Roaming\Python\Python314\site-packages\httpcore\__init__.py:140 in         │
│ <module>                                                                                         │
│                                                                                                  │
│   137 __locals = locals()                                                                        │
│   138 for __name in __all__:                                                                     │
│   139 │   if not __name.startswith("__"):                                                        │
│ ❱ 140 │   │   setattr(__locals[__name], "__module__", "httpcore")  # noqa                        │
│   141                                                                                            │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'typing.Union' object has no attribute '__module__' and no __dict__ for setting new attributes

AraHaan avatar Dec 14 '25 15:12 AraHaan

On Windows I got this to work by first going into the Installed Apps within Settings and Uninstalling every single version of python that was NOT installed by the new Python Install Manager. After that go to %AppData%\Python\ within the bar right next to the search box in Windows explorer by pasting that text in EXACTLY. Once there delete every last one of the Python??? folders leaving only shared.

Once that is done type in py -m pip install --upgrade hatch to reinstall hatch and it's dependencies prior to running hatch test. I still run into issues however with -py 3.14 on it creating the environment but other than that it all works.

AraHaan avatar Dec 14 '25 21:12 AraHaan