Skip to content

Regression: hatch fails with strange error (ValueError: invalid scheme: '{root'. Only alphanumeric, "+", "-", and ".") on project that previously worked ok #2108

@manuel-koch

Description

@manuel-koch

Using:

  • Python 3.12
  • hatch 1.16.0
  • hatchling 1.28.0

Looks like a newer version of hatch is not backward compatible although only a minor version change has happened.
I can confirm that it is still working with hatch 1.15.1 locally, but in our CI/CD pipeline hatch 1.16.0 is failing.

We are using a feature of hatch that was working ok in previous version, but now breaks our project.
We use something like this to achieve nested projects / monorepo handling: https://github.com/manuel-koch/hatch-monorepo-sandbox/blob/720ee5f3007725a6db6faa0dd7cfd65cd5fb9986/src/pyproject.toml#L18

[project]
....
dependencies = [
  "my-sandbox-lib @ {root:parent:uri}/my-sandbox-lib",
  "my-sandbox-lib-addon @ {root:parent:uri}/my-sandbox-lib-addon",
]

But this {root:parent:uri} doesn't seem to work anymore, i.e. we get error like the following now when test env for our project is setup:

+ make lint test
cd src \
&& hatch run test:lint ; if [ "$(($? & 0x3))" != "0" ] ; then false ; else true ; fi
────────────────────────────────── test.py312 ──────────────────────────────────
Creating environment: test.py312
Installing project in development mode
Checking dependencies
╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/cli/__init__.py:229 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                                                                        │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ click/core.py:1485 in __call__                                               │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ click/core.py:1406 in main                                                   │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ click/core.py:1873 in invoke                                                 │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ click/core.py:1269 in invoke                                                 │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ click/core.py:824 in invoke                                                  │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ click/decorators.py:34 in new_func                                           │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/cli/run/__init__.py:147 in run                                         │
│                                                                              │
│   144 │   elif not env_name:                                                 │
│   145 │   │   env_name = "system"                                            │
│   146 │                                                                      │
│ ❱ 147 │   ctx.invoke(                                                        │
│   148 │   │   run_command,                                                   │
│   149 │   │   args=[command, *final_args],                                   │
│   150 │   │   env_names=[env_name],                                          │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ click/core.py:824 in invoke                                                  │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ click/decorators.py:46 in new_func                                           │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/cli/env/run.py:134 in run                                              │
│                                                                              │
│   131 │   elif not matrix_selected and (included_variables or excluded_varia │
│   132 │   │   app.abort(f"Variable selection is unsupported for non-matrix e │
│   133 │                                                                      │
│ ❱ 134 │   for context in app.runner_context(                                 │
│   135 │   │   environments,                                                  │
│   136 │   │   ignore_compat=ignore_compat or matrix_selected,                │
│   137 │   │   display_header=matrix_selected,                                │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/cli/application.py: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:                                               │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/cli/application.py: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():                            │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/project/core.py:227 in prepare_environment                             │
│                                                                              │
│   224 │   │   current_dep_hash = self.env_metadata.dependency_hash(environme │
│   225 │   │   if new_dep_hash != current_dep_hash:                           │
│   226 │   │   │   with environment.app_status_dependency_installation_check( │
│ ❱ 227 │   │   │   │   dependencies_in_sync = environment.dependencies_in_syn │
│   228 │   │   │                                                              │
│   229 │   │   │   if not dependencies_in_sync:                               │
│   230 │   │   │   │   with environment.app_status_dependency_synchronization │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/env/virtual.py:197 in dependencies_in_sync                             │
│                                                                              │
│   194 │                                                                      │
│   195 │   def dependencies_in_sync(self):                                    │
│   196 │   │   with self.safe_activation():                                   │
│ ❱ 197 │   │   │   return not self.missing_dependencies                       │
│   198 │                                                                      │
│   199 │   def sync_dependencies(self):                                       │
│   200 │   │   with self.safe_activation():                                   │
│                                                                              │
│ /usr/lib/python3.12/functools.py:995 in __get__                              │
│                                                                              │
│    992 │   │   │   raise TypeError(msg) from None                            │
│    993 │   │   val = cache.get(self.attrname, _NOT_FOUND)                    │
│    994 │   │   if val is _NOT_FOUND:                                         │
│ ❱  995 │   │   │   val = self.func(instance)                                 │
│    996 │   │   │   try:                                                      │
│    997 │   │   │   │   cache[self.attrname] = val                            │
│    998 │   │   │   except TypeError:                                         │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/env/virtual.py:140 in missing_dependencies                             │
│                                                                              │
│   137 │                                                                      │
│   138 │   @cached_property                                                   │
│   139 │   def missing_dependencies(self) -> list[Dependency]:                │
│ ❱ 140 │   │   return self.distributions.missing_dependencies(self.all_depend │
│   141 │                                                                      │
│   142 │   @staticmethod                                                      │
│   143 │   def get_option_types() -> dict:                                    │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/dep/sync.py:28 in missing_dependencies                                 │
│                                                                              │
│    25 │   │   return all(self.dependency_in_sync(dependency) for dependency  │
│    26 │                                                                      │
│    27 │   def missing_dependencies(self, dependencies: list[Dependency]) ->  │
│ ❱  28 │   │   return [dependency for dependency in dependencies if not self. │
│    29 │                                                                      │
│    30 │   def dependency_in_sync(self, dependency: Dependency, *, environmen │
│    31 │   │   if environment is None:                                        │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/dep/sync.py:85 in dependency_in_sync                                   │
│                                                                              │
│    82 │   │   │   │   if editable != dependency.editable:                    │
│    83 │   │   │   │   │   return False                                       │
│    84 │   │   │   │                                                          │
│ ❱  85 │   │   │   │   if Path.from_uri(url) != dependency.path:              │
│    86 │   │   │   │   │   return False                                       │
│    87 │   │   │                                                              │
│    88 │   │   │   if "vcs_info" in direct_url_data:                          │
│                                                                              │
│ /usr/lib/python3.12/functools.py:995 in __get__                              │
│                                                                              │
│    992 │   │   │   raise TypeError(msg) from None                            │
│    993 │   │   val = cache.get(self.attrname, _NOT_FOUND)                    │
│    994 │   │   if val is _NOT_FOUND:                                         │
│ ❱  995 │   │   │   val = self.func(instance)                                 │
│    996 │   │   │   try:                                                      │
│    997 │   │   │   │   cache[self.attrname] = val                            │
│    998 │   │   │   except TypeError:                                         │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hatch/dep/core.py:33 in path                                                 │
│                                                                              │
│   30 │   │                                                                   │
│   31 │   │   import hyperlink                                                │
│   32 │   │                                                                   │
│ ❱ 33 │   │   uri = hyperlink.parse(self.url)                                 │
│   34 │   │   if uri.scheme != "file":                                        │
│   35 │   │   │   return None                                                 │
│   36                                                                         │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hyperlink/_url.py:2444 in parse                                              │
│                                                                              │
│   2441 │                                                                     │
│   2442 │   .. versionadded:: 18.0.0                                          │
│   2443 │   """                                                               │
│ ❱ 2444 │   enc_url = EncodedURL.from_text(url)                               │
│   2445 │   if not decoded:                                                   │
│   2446 │   │   return enc_url                                                │
│   2447 │   dec_url = DecodedURL(enc_url, lazy=lazy)                          │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hyperlink/_url.py:1437 in from_text                                          │
│                                                                              │
│   1434 │   │   │   )  # type: QueryPairs                                     │
│   1435 │   │   else:                                                         │
│   1436 │   │   │   query = ()                                                │
│ ❱ 1437 │   │   return cls(                                                   │
│   1438 │   │   │   scheme,                                                   │
│   1439 │   │   │   host,                                                     │
│   1440 │   │   │   path,                                                     │
│                                                                              │
│ /opt/atlassian/pipelines/agent/build/venv-3.12/lib/python3.12/site-packages/ │
│ hyperlink/_url.py:1010 in __init__                                           │
│                                                                              │
│   1007 │   │   self._scheme = _textcheck("scheme", scheme)                   │
│   1008 │   │   if self._scheme:                                              │
│   1009 │   │   │   if not _SCHEME_RE.match(self._scheme):                    │
│ ❱ 1010 │   │   │   │   raise ValueError(                                     │
│   1011 │   │   │   │   │   'invalid scheme: %r. Only alphanumeric, "+",'     │
│   1012 │   │   │   │   │   ' "-", and "." allowed. Did you meant to call'    │
│   1013 │   │   │   │   │   " %s.from_text()?" % (self._scheme, self.__class_ │
╰──────────────────────────────────────────────────────────────────────────────╯
ValueError: invalid scheme: '{root'. Only alphanumeric, "+", "-", and "." 
allowed. Did you meant to call URL.from_text()?
make: *** [Makefile:65: lint] Error 1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions