python-poetry / poetry

Python packaging and dependency management made easy
https://python-poetry.org
MIT License
31.59k stars 2.26k forks source link

Unclear error report: KeyError 'name' #8122

Closed td-anne closed 11 months ago

td-anne commented 1 year ago

Issue

When I try poetry commands I get a failure with unhelpful output:

$ poetry debug info

Poetry

'name'

If I use -vvv it seems this is a KeyError emanating from inside poetry:

$ poetry debug info -vvv

Poetry

  Stack trace:

  12  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/cleo/application.py:327 in run
       325│ 
       326│             try:
     → 327│                 exit_code = self._run(io)
       328│             except BrokenPipeError:
       329│                 # If we are piped to another process, it may close early and send a

  11  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/poetry/console/application.py:190 in _run
       188│         self._load_plugins(io)
       189│ 
     → 190│         exit_code: int = super()._run(io)
       191│         return exit_code
       192│ 

  10  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/cleo/application.py:431 in _run
       429│             io.input.interactive(interactive)
       430│ 
     → 431│         exit_code = self._run_command(command, io)
       432│         self._running_command = None
       433│ 

   9  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/cleo/application.py:473 in _run_command
       471│ 
       472│         if error is not None:
     → 473│             raise error
       474│ 
       475│         return terminate_event.exit_code

   8  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/cleo/application.py:457 in _run_command
       455│ 
       456│             if command_event.command_should_run():
     → 457│                 exit_code = command.run(io)
       458│             else:
       459│                 exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED

   7  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/cleo/commands/base_command.py:119 in run
       117│         io.input.validate()
       118│ 
     → 119│         status_code = self.execute(io)
       120│ 
       121│         if status_code is None:

   6  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/cleo/commands/command.py:62 in execute
        60│ 
        61│         try:
     →  62│             return self.handle()
        63│         except KeyboardInterrupt:
        64│             return 1

   5  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/poetry/console/commands/debug/info.py:20 in handle
        18│             "\n".join(
        19│                 [
     →  20│                     f"Version: {self.poetry.VERSION}",
        21│                     f"Python:  {poetry_python_version}",
        22│                 ]

   4  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/poetry/console/commands/command.py:23 in poetry
        21│     def poetry(self) -> Poetry:
        22│         if self._poetry is None:
     →  23│             return self.get_application().poetry
        24│ 
        25│         return self._poetry

   3  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/poetry/console/application.py:129 in poetry
       127│             project_path = self._io.input.option("directory")
       128│ 
     → 129│         self._poetry = Factory().create_poetry(
       130│             cwd=project_path,
       131│             io=self._io,

   2  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/poetry/factory.py:58 in create_poetry
        56│             io = NullIO()
        57│ 
     →  58│         base_poetry = super().create_poetry(cwd=cwd, with_groups=with_groups)
        59│ 
        60│         poetry_file = base_poetry.pyproject_path

   1  ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/poetry/core/factory.py:52 in create_poetry
        50│ 
        51│         # Checking validity
     →  52│         check_result = self.validate(local_config)
        53│         if check_result["errors"]:
        54│             message = ""

  KeyError

  'name'

  at ~/.local/share/pypoetry/venv/lib/python3.8/site-packages/poetry/factory.py:370 in validate
      366│             dependencies.update(group.get("dependencies", {}).keys())
      367│ 
      368│         dependencies = {canonicalize_name(d) for d in dependencies}
      369│ 
    → 370│         if canonicalize_name(config["name"]) in dependencies:
      371│             results["errors"].append(
      372│                 f"Project name ({config['name']}) is same as one of its dependencies"
      373│             )
      374│ 

This is probably because of something amiss in my pyproject.toml but the error message provides no indication of what.

dimbleby commented 1 year ago
diff --git a/src/poetry/factory.py b/src/poetry/factory.py
index 5e926b61..be6870f3 100644
--- a/src/poetry/factory.py
+++ b/src/poetry/factory.py
@@ -367,9 +367,10 @@ class Factory(BaseFactory):

         dependencies = {canonicalize_name(d) for d in dependencies}

-        if canonicalize_name(config["name"]) in dependencies:
+        project_name = config.get("name")
+        if project_name is not None and canonicalize_name(project_name) in dependencies:
             results["errors"].append(
-                f"Project name ({config['name']}) is same as one of its dependencies"
+                f"Project name ({project_name}) is same as one of its dependencies"
             )

         return results

should fix it

pull requests welcome, I'm sure

kevinzeidler commented 1 year ago

I'm experiencing a similar issue, except the KeyError is triggered by different conditions and appears to trace back to a poetry dependency called locker.py. I encounter this error when running poetry lock, poetry add <dep>, and poetry update. In the case of poetry lock the dependency resolution step appears to run successfully, and the error is encountered only afterward when trying to read data from the existing lockfile:

poetry lock -vvv
Configuration file exists at /Users/kz/Library/Preferences/pypoetry, reusing this directory.

Consider moving TOML configuration files to /Users/kz/Library/Application Support/pypoetry, as support for the legacy directory will be removed in an upcoming release.
Using virtualenv: /Users/kz/vcs/my_poetry_project/.venv
Updating dependencies
Resolving dependencies...
   1: fact: my_poetry_project is 0.1.0
   1: derived: my_poetry_project
   0: Duplicate dependencies for coverage
   0: Merging constraints for coverage for marker
   0: Merging requirements for coverage (>=7.2.5,<8.0.0)
   1: fact: e2l-lambda depends on pydantic (^1.9.2)
   1: fact: e2l-lambda depends on boto3 (^1.24.51)
   ... # dependency resolution log messages omitted
 214: selecting botocore (1.29.160)
 214: fact: s3transfer (0.6.1) depends on botocore (>=1.12.36,<2.0a.0)
 214: selecting s3transfer (0.6.1)
 214: selecting jmespath (1.0.1)
 214: selecting tomli (2.0.1)
 214: selecting exceptiongroup (1.1.1)
 214: selecting idna (3.4)
 214: selecting greenlet (2.0.2)
 214: selecting colorama (0.4.6)
 214: Version solving took 30.745 seconds.
 214: Tried 214 solutions.

  Stack trace:

  14  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/cleo/application.py:327 in run
       325│
       326│             try:
     → 327│                 exit_code = self._run(io)
       328│             except BrokenPipeError:
       329│                 # If we are piped to another process, it may close early and send a

  13  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/poetry/console/application.py:190 in _run
       188│         self._load_plugins(io)
       189│
     → 190│         exit_code: int = super()._run(io)
       191│         return exit_code
       192│

  12  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/cleo/application.py:431 in _run
       429│             io.input.interactive(interactive)
       430│
     → 431│         exit_code = self._run_command(command, io)
       432│         self._running_command = None
       433│

  11  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/cleo/application.py:473 in _run_command
       471│
       472│         if error is not None:
     → 473│             raise error
       474│
       475│         return terminate_event.exit_code

  10  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/cleo/application.py:457 in _run_command
       455│
       456│             if command_event.command_should_run():
     → 457│                 exit_code = command.run(io)
       458│             else:
       459│                 exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED

   9  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/cleo/commands/base_command.py:119 in run
       117│         io.input.validate()
       118│
     → 119│         status_code = self.execute(io)
       120│
       121│         if status_code is None:

   8  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/cleo/commands/command.py:62 in execute
        60│
        61│         try:
     →  62│             return self.handle()
        63│         except KeyboardInterrupt:
        64│             return 1

   7  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/poetry/console/commands/lock.py:52 in handle
        50│         self.installer.lock(update=not self.option("no-update"))
        51│
     →  52│         return self.installer.run()
        53│

   6  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/poetry/installation/installer.py:104 in run
       102│             self.verbose(True)
       103│
     → 104│         return self._do_install()
       105│
       106│     def dry_run(self, dry_run: bool = True) -> Installer:

   5  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/poetry/installation/installer.py:274 in _do_install
       272│         if not self.executor.enabled:
       273│             # If we are only in lock mode, no need to go any further
     → 274│             self._write_lock_file(lockfile_repo)
       275│             return 0
       276│

   4  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/poetry/installation/installer.py:359 in _write_lock_file
       357│     def _write_lock_file(self, repo: LockfileRepository, force: bool = False) -> None:
       358│         if not self.is_dry_run() and (force or self._update):
     → 359│             updated_lock = self._locker.set_lock_data(self._package, repo.packages)
       360│
       361│             if updated_lock:

   3  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/poetry/packages/locker.py:233 in set_lock_data
       231│         lock = self._compute_lock_data(root, packages)
       232│
     → 233│         if self._should_write(lock):
       234│             self._write_lock_data(lock)
       235│             return True

   2  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/poetry/packages/locker.py:279 in _should_write
       277│         if self.is_locked():
       278│             try:
     → 279│                 lock_data = self.lock_data
       280│             except RuntimeError:
       281│                 # incompatible, invalid or no lock file

   1  ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/poetry/packages/locker.py:69 in lock_data
        67│     def lock_data(self) -> dict[str, Any]:
        68│         if self._lock_data is None:
     →  69│             self._lock_data = self._get_lock_data()
        70│
        71│         return self._lock_data

  KeyError

  'metadata'

  at ~/.pyenv/versions/3.10.11/lib/python3.10/site-packages/poetry/packages/locker.py:320 in _get_lock_data
      316│                 lock_data = tomllib.load(f)
      317│             except tomllib.TOMLDecodeError as e:
      318│                 raise RuntimeError(f"Unable to read the lock file ({e}).")
      319│
    → 320│         metadata = lock_data["metadata"]
      321│         lock_version = Version.parse(metadata.get("lock-version", "1.0"))
      322│         current_version = Version.parse(self._VERSION)
      323│         accepted_versions = parse_constraint(self._READ_VERSION_RANGE)
      324│         lock_version_allowed = accepted_versions.allows(lock_version)

No issues with the pyproject.toml as far as I can tell:

poetry debug info -vvv
Configuration file exists at /Users/kz/Library/Preferences/pypoetry, reusing this directory.

Consider moving TOML configuration files to /Users/kz/Library/Application Support/pypoetry, as support for the legacy directory will be removed in an upcoming release.

Poetry
Loading configuration file /Users/kz/Library/Preferences/pypoetry/config.toml
Loading configuration file /Users/kz/vcs/my_poetry_project/poetry.toml
Version: 1.5.1
Python:  3.10.11

Virtualenv
Python:         3.10.11
Implementation: CPython
Path:           /Users/kz/vcs/my_poetry_project/.venv
Executable:     /Users/kz/vcs/my_poetry_project/.venv/bin/python
Valid:          True

System
Platform:   darwin
OS:         posix
Python:     3.10.11
Path:       /Users/kz/.pyenv/versions/3.10.11
Executable: /Users/kz/.pyenv/versions/3.10.11/bin/python3.10

In this case, removing the poetry.lock file appears to fix the error.

dimbleby commented 1 year ago

@kevinzeidler that is completely different, please don't hijack this issue

kevinzeidler commented 1 year ago

You're right, my bad. Wasn't reading the stack traces carefully enough.

GAC-BSP commented 1 year ago

Same here! Not sure how to workaround the issue.

TravisBumgarner commented 11 months ago

Whelp getting this error too.

TravisBumgarner commented 11 months ago

Alright so what I gathered is

[project]
name = "gcode2dplotterart"
version = "0.0.1"
description = "Easily generate plotter art with your 2D Plotter or 3D Printer. This library abstracts away G-Code so you can focus on making art."
authors = [
  { name="Travis Bumgarner", email="travis@sillysideprojects.com" },
]

[build-system]
requires = ["hatchling", "setuptools", "wheel"]
build-backend = "hatchling.build"

[tool.poetry.dependencies]
python = "^3.11.5"
mypy="^1.7.0"
black="^23.10.1"
flake8="^6.1.0"
pytest="^7.4.3"
matplotlib="^3.8.1"
numpy="^1.26.1"
setuptools = "^68.2.2"
wheel = "^0.41.3"
pydoc-markdown = "^4.8.2"

[project.urls]
"Homepage" = "https://github.com/TravisBumgarner/gcode2dplotterart"
"Bug Tracker" = "https://github.com/TravisBumgarner/gcode2dplotterart/issues"

This was my pyproject.toml.

I added the section

[tool.poetry]
name = "gcode2dplotterart"
authors = ["Travis Bumgarner"]
version = "0.0.1"
description = "Easily generate plotter art with your 2D Plotter or 3D Printer. This library abstracts away G-Code so you can focus on making art."

Which is really just a duplicate of the [project] section. But the error went away.

github-actions[bot] commented 8 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.