Repository: python-poetry/poetry

Issue:
Unclear error report: KeyError 'name'
<!--
    Hi there! Thank you for submitting a bug report!

    Before you submit your issue, please review and follow the instructions at
    https://python-poetry.org/docs/contributing/#reporting-bugs. Fully fill out the template below; insufficient
    information or bad reproduction instructions will impair the ability of others to help you.
-->

<!-- All the below information must be provided for others to understand and help with your issue. -->
- **Poetry version**: Poetry (version 1.5.1)
- **Python version**: Python 3.8.10
- **OS version and name**: Ubuntu 20.04.6 LTS
- **pyproject.toml**: https://gist.github.com/td-anne/030e88ea2c564721d6d389fbebf3e16f

<!-- All the below steps should be completed before submitting your issue. Checked checkbox should look like this: [x] -->
- [x] I am on the [latest](https://github.com/python-poetry/poetry/releases/latest) stable Poetry version, installed using a recommended method.
- [x] I have searched the [issues](https://github.com/python-poetry/poetry/issues) of this repo and believe that this is not a duplicate.
- [x] I have consulted the [FAQ](https://python-poetry.org/docs/faq/) and [blog](https://python-poetry.org/blog/) for any relevant entries or release notes.
- [x] If an exception occurs when executing a command, I executed it again in debug mode (`-vvv` option) and have included the output below.

## Issue
<!-- Now feel free to write your issue, and please be as descriptive as possible! Make sure to include detailed reproduction steps. -->
<!-- Thanks again 🙌 ❤ -->

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.



Discussion:
```patch
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

Resolving patch:
diff --git a/src/poetry/factory.py b/src/poetry/factory.py
--- a/src/poetry/factory.py
+++ b/src/poetry/factory.py
@@ -370,9 +370,10 @@ def validate(
 
         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


Test patch:
diff --git a/tests/fixtures/nameless_pyproject/pyproject.toml b/tests/fixtures/nameless_pyproject/pyproject.toml
new file mode 100644
--- /dev/null
+++ b/tests/fixtures/nameless_pyproject/pyproject.toml
@@ -0,0 +1,8 @@
+[tool.poetry]
+version = "0.1.0"
+description = ""
+authors = ["Foo <foo@bar.com>"]
+readme = "README.md"
+
+[tool.poetry.dependencies]
+python = "^3.10"
diff --git a/tests/test_factory.py b/tests/test_factory.py
--- a/tests/test_factory.py
+++ b/tests/test_factory.py
@@ -524,20 +524,27 @@ def test_create_poetry_fails_on_invalid_configuration(
     with pytest.raises(RuntimeError) as e:
         Factory().create_poetry(fixture_dir("invalid_pyproject") / "pyproject.toml")
 
-    jsonschema_error = "'description' is a required property"
-    fastjsonschema_error = "data must contain ['description'] properties"
-
-    expected_template = """\
+    expected = """\
 The Poetry configuration is invalid:
-  - {schema_error}
+  - data must contain ['description'] properties
   - Project name (invalid) is same as one of its dependencies
 """
-    expected = {
-        expected_template.format(schema_error=schema_error)
-        for schema_error in (jsonschema_error, fastjsonschema_error)
-    }
 
-    assert str(e.value) in expected
+    assert str(e.value) == expected
+
+
+def test_create_poetry_fails_on_nameless_project(
+    fixture_dir: FixtureDirGetter,
+) -> None:
+    with pytest.raises(RuntimeError) as e:
+        Factory().create_poetry(fixture_dir("nameless_pyproject") / "pyproject.toml")
+
+    expected = """\
+The Poetry configuration is invalid:
+  - data must contain ['name'] properties
+"""
+
+    assert str(e.value) == expected
 
 
 def test_create_poetry_with_local_config(fixture_dir: FixtureDirGetter) -> None: