We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Improve error message to EmptyTableNameError
- **Poetry version**: 1.7.1
- **Python version**: 3.11.5
- **OS version and name**: win32 nt
- **pyproject.toml**: (https://gist.github.com/biofsphere/89895e6ff22f01cc7ce63100d9fc5ede)

- [X] I am on the [latest](https://github.com/python-poetry/poetry/releases/latest) stable Poetry version, installed using a [recommended method](https://python-poetry.org/docs/#installation).
- [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 (suggestion)
While adding packages, I run into an EmptyTableNameError message **Empty table name at line 1 col 19**. I spent a whole afternoon searching for a solution. It was only when I decided to open this issue that, by testing and retesting my shell commands I realized what was going on. This did not happen to most packages I installed, but it did to django-debug-toolbar and ipython. I went off to search communalities between both packages and tried to understand **poetry debug info --verbose output**, digging something for quite a while. When I gave up and decided to make a gist and open a new issue, voala!! I noticed I run **poetry add django-debug-toolbar --group==local**... ...yes, with double equal signs!!!! 

I am just sharing this so you know the error message threw me way off the mark, for a mere misspelling mistake. If you could improve the EmptyTableNameError message to alert beginners with something like "Check your spelling" or something, that would have me saved hours!. My bad. Checking spelling is pretty basic and I did for letter, but missing the double equal signs was such a bummer.

Anyway, just a quick note. I am really enjoying this package manager. I don't think I will ever get back to pip alone again.  
 
<!-- Thanks!! 🙌 ❤ -->

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/poetry/console/commands/add.py`
Content:
```
1 from __future__ import annotations
2 
3 import contextlib
4 
5 from typing import TYPE_CHECKING
6 from typing import Any
7 from typing import ClassVar
8 
9 from cleo.helpers import argument
10 from cleo.helpers import option
11 from packaging.utils import canonicalize_name
12 from poetry.core.packages.dependency_group import MAIN_GROUP
13 from tomlkit.toml_document import TOMLDocument
14 
15 from poetry.console.commands.init import InitCommand
16 from poetry.console.commands.installer_command import InstallerCommand
17 
18 
19 if TYPE_CHECKING:
20     from cleo.io.inputs.argument import Argument
21     from cleo.io.inputs.option import Option
22 
23 
24 class AddCommand(InstallerCommand, InitCommand):
25     name = "add"
26     description = "Adds a new dependency to <comment>pyproject.toml</> and installs it."
27 
28     arguments: ClassVar[list[Argument]] = [
29         argument("name", "The packages to add.", multiple=True)
30     ]
31     options: ClassVar[list[Option]] = [
32         option(
33             "group",
34             "-G",
35             "The group to add the dependency to.",
36             flag=False,
37             default=MAIN_GROUP,
38         ),
39         option(
40             "dev",
41             "D",
42             "Add as a development dependency. (<warning>Deprecated</warning>) Use"
43             " --group=dev instead.",
44         ),
45         option("editable", "e", "Add vcs/path dependencies as editable."),
46         option(
47             "extras",
48             "E",
49             "Extras to activate for the dependency.",
50             flag=False,
51             multiple=True,
52         ),
53         option("optional", None, "Add as an optional dependency."),
54         option(
55             "python",
56             None,
57             "Python version for which the dependency must be installed.",
58             flag=False,
59         ),
60         option(
61             "platform",
62             None,
63             "Platforms for which the dependency must be installed.",
64             flag=False,
65         ),
66         option(
67             "source",
68             None,
69             "Name of the source to use to install the package.",
70             flag=False,
71         ),
72         option("allow-prereleases", None, "Accept prereleases."),
73         option(
74             "dry-run",
75             None,
76             "Output the operations but do not execute anything (implicitly enables"
77             " --verbose).",
78         ),
79         option("lock", None, "Do not perform operations (only update the lockfile)."),
80     ]
81     examples = """\
82 If you do not specify a version constraint, poetry will choose a suitable one based on\
83  the available package versions.
84 
85 You can specify a package in the following forms:
86   - A single name (<b>requests</b>)
87   - A name and a constraint (<b>requests@^2.23.0</b>)
88   - A git url (<b>git+https://github.com/python-poetry/poetry.git</b>)
89   - A git url with a revision\
90  (<b>git+https://github.com/python-poetry/poetry.git#develop</b>)
91   - A subdirectory of a git repository\
92  (<b>git+https://github.com/python-poetry/poetry.git#subdirectory=tests/fixtures/sample_project</b>)
93   - A git SSH url (<b>git+ssh://github.com/python-poetry/poetry.git</b>)
94   - A git SSH url with a revision\
95  (<b>git+ssh://github.com/python-poetry/poetry.git#develop</b>)
96   - A file path (<b>../my-package/my-package.whl</b>)
97   - A directory (<b>../my-package/</b>)
98   - A url (<b>https://example.com/packages/my-package-0.1.0.tar.gz</b>)
99 """
100     help = f"""\
101 The add command adds required packages to your <comment>pyproject.toml</> and installs\
102  them.
103 
104 {examples}
105 """
106 
107     loggers: ClassVar[list[str]] = [
108         "poetry.repositories.pypi_repository",
109         "poetry.inspection.info",
110     ]
111 
112     def handle(self) -> int:
113         from poetry.core.constraints.version import parse_constraint
114         from tomlkit import inline_table
115         from tomlkit import parse as parse_toml
116         from tomlkit import table
117 
118         from poetry.factory import Factory
119 
120         packages = self.argument("name")
121         if self.option("dev"):
122             self.line_error(
123                 "<warning>The --dev option is deprecated, "
124                 "use the `--group dev` notation instead.</warning>"
125             )
126             group = "dev"
127         else:
128             group = self.option("group", self.default_group or MAIN_GROUP)
129 
130         if self.option("extras") and len(packages) > 1:
131             raise ValueError(
132                 "You can only specify one package when using the --extras option"
133             )
134 
135         # tomlkit types are awkward to work with, treat content as a mostly untyped
136         # dictionary.
137         content: dict[str, Any] = self.poetry.file.read()
138         poetry_content = content["tool"]["poetry"]
139         project_name = (
140             canonicalize_name(name) if (name := poetry_content.get("name")) else None
141         )
142 
143         if group == MAIN_GROUP:
144             if "dependencies" not in poetry_content:
145                 poetry_content["dependencies"] = table()
146 
147             section = poetry_content["dependencies"]
148         else:
149             if "group" not in poetry_content:
150                 poetry_content["group"] = table(is_super_table=True)
151 
152             groups = poetry_content["group"]
153             if group not in groups:
154                 dependencies_toml: dict[str, Any] = parse_toml(
155                     f"[tool.poetry.group.{group}.dependencies]\n\n"
156                 )
157                 group_table = dependencies_toml["tool"]["poetry"]["group"][group]
158                 poetry_content["group"][group] = group_table
159 
160             if "dependencies" not in poetry_content["group"][group]:
161                 poetry_content["group"][group]["dependencies"] = table()
162 
163             section = poetry_content["group"][group]["dependencies"]
164 
165         existing_packages = self.get_existing_packages_from_input(packages, section)
166 
167         if existing_packages:
168             self.notify_about_existing_packages(existing_packages)
169 
170         packages = [name for name in packages if name not in existing_packages]
171 
172         if not packages:
173             self.line("Nothing to add.")
174             return 0
175 
176         requirements = self._determine_requirements(
177             packages,
178             allow_prereleases=self.option("allow-prereleases"),
179             source=self.option("source"),
180         )
181 
182         for _constraint in requirements:
183             version = _constraint.get("version")
184             if version is not None:
185                 # Validate version constraint
186                 assert isinstance(version, str)
187                 parse_constraint(version)
188 
189             constraint: dict[str, Any] = inline_table()
190             for name, value in _constraint.items():
191                 if name == "name":
192                     continue
193 
194                 constraint[name] = value
195 
196             if self.option("optional"):
197                 constraint["optional"] = True
198 
199             if self.option("allow-prereleases"):
200                 constraint["allow-prereleases"] = True
201 
202             if self.option("extras"):
203                 extras = []
204                 for extra in self.option("extras"):
205                     extras += extra.split()
206 
207                 constraint["extras"] = extras
208 
209             if self.option("editable"):
210                 if "git" in _constraint or "path" in _constraint:
211                     constraint["develop"] = True
212                 else:
213                     self.line_error(
214                         "\n"
215                         "<error>Failed to add packages. "
216                         "Only vcs/path dependencies support editable installs. "
217                         f"<c1>{_constraint['name']}</c1> is neither."
218                     )
219                     self.line_error("\nNo changes were applied.")
220                     return 1
221 
222             if self.option("python"):
223                 constraint["python"] = self.option("python")
224 
225             if self.option("platform"):
226                 constraint["platform"] = self.option("platform")
227 
228             if self.option("source"):
229                 constraint["source"] = self.option("source")
230 
231             if len(constraint) == 1 and "version" in constraint:
232                 constraint = constraint["version"]
233 
234             constraint_name = _constraint["name"]
235             assert isinstance(constraint_name, str)
236 
237             canonical_constraint_name = canonicalize_name(constraint_name)
238 
239             if canonical_constraint_name == project_name:
240                 self.line_error(
241                     f"<error>Cannot add dependency on <c1>{constraint_name}</c1> to"
242                     " project with the same name."
243                 )
244                 self.line_error("\nNo changes were applied.")
245                 return 1
246 
247             for key in section:
248                 if canonicalize_name(key) == canonical_constraint_name:
249                     section[key] = constraint
250                     break
251             else:
252                 section[constraint_name] = constraint
253 
254             with contextlib.suppress(ValueError):
255                 self.poetry.package.dependency_group(group).remove_dependency(
256                     constraint_name
257                 )
258 
259             self.poetry.package.add_dependency(
260                 Factory.create_dependency(
261                     constraint_name,
262                     constraint,
263                     groups=[group],
264                     root_dir=self.poetry.file.path.parent,
265                 )
266             )
267 
268         # Refresh the locker
269         content["tool"]["poetry"] = poetry_content
270         self.poetry.locker.set_pyproject_data(content)
271         self.installer.set_locker(self.poetry.locker)
272 
273         # Cosmetic new line
274         self.line("")
275 
276         self.installer.set_package(self.poetry.package)
277         self.installer.dry_run(self.option("dry-run"))
278         self.installer.verbose(self.io.is_verbose())
279         self.installer.update(True)
280         self.installer.execute_operations(not self.option("lock"))
281 
282         self.installer.whitelist([r["name"] for r in requirements])
283 
284         status = self.installer.run()
285 
286         if status == 0 and not self.option("dry-run"):
287             assert isinstance(content, TOMLDocument)
288             self.poetry.file.write(content)
289 
290         return status
291 
292     def get_existing_packages_from_input(
293         self, packages: list[str], section: dict[str, Any]
294     ) -> list[str]:
295         existing_packages = []
296 
297         for name in packages:
298             for key in section:
299                 if canonicalize_name(key) == canonicalize_name(name):
300                     existing_packages.append(name)
301 
302         return existing_packages
303 
304     @property
305     def _hint_update_packages(self) -> str:
306         return (
307             "\nIf you want to update it to the latest compatible version, you can use"
308             " `poetry update package`.\nIf you prefer to upgrade it to the latest"
309             " available version, you can use `poetry add package@latest`.\n"
310         )
311 
312     def notify_about_existing_packages(self, existing_packages: list[str]) -> None:
313         self.line(
314             "The following packages are already present in the pyproject.toml and will"
315             " be skipped:\n"
316         )
317         for name in existing_packages:
318             self.line(f"  - <c1>{name}</c1>")
319         self.line(self._hint_update_packages)
320
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/poetry/console/commands/add.py b/src/poetry/console/commands/add.py
--- a/src/poetry/console/commands/add.py
+++ b/src/poetry/console/commands/add.py
@@ -112,7 +112,7 @@
     def handle(self) -> int:
         from poetry.core.constraints.version import parse_constraint
         from tomlkit import inline_table
-        from tomlkit import parse as parse_toml
+        from tomlkit import nl
         from tomlkit import table
 
         from poetry.factory import Factory
@@ -150,17 +150,17 @@
                 poetry_content["group"] = table(is_super_table=True)
 
             groups = poetry_content["group"]
+
             if group not in groups:
-                dependencies_toml: dict[str, Any] = parse_toml(
-                    f"[tool.poetry.group.{group}.dependencies]\n\n"
-                )
-                group_table = dependencies_toml["tool"]["poetry"]["group"][group]
-                poetry_content["group"][group] = group_table
+                groups[group] = table()
+                groups.add(nl())
+
+            this_group = groups[group]
 
-            if "dependencies" not in poetry_content["group"][group]:
-                poetry_content["group"][group]["dependencies"] = table()
+            if "dependencies" not in this_group:
+                this_group["dependencies"] = table()
 
-            section = poetry_content["group"][group]["dependencies"]
+            section = this_group["dependencies"]
 
         existing_packages = self.get_existing_packages_from_input(packages, section)
 
@@ -266,7 +266,6 @@
             )
 
         # Refresh the locker
-        content["tool"]["poetry"] = poetry_content
         self.poetry.locker.set_pyproject_data(content)
         self.installer.set_locker(self.poetry.locker)

{"golden_diff": "diff --git a/src/poetry/console/commands/add.py b/src/poetry/console/commands/add.py\n--- a/src/poetry/console/commands/add.py\n+++ b/src/poetry/console/commands/add.py\n@@ -112,7 +112,7 @@\n     def handle(self) -> int:\n         from poetry.core.constraints.version import parse_constraint\n         from tomlkit import inline_table\n-        from tomlkit import parse as parse_toml\n+        from tomlkit import nl\n         from tomlkit import table\n \n         from poetry.factory import Factory\n@@ -150,17 +150,17 @@\n                 poetry_content[\"group\"] = table(is_super_table=True)\n \n             groups = poetry_content[\"group\"]\n+\n             if group not in groups:\n-                dependencies_toml: dict[str, Any] = parse_toml(\n-                    f\"[tool.poetry.group.{group}.dependencies]\\n\\n\"\n-                )\n-                group_table = dependencies_toml[\"tool\"][\"poetry\"][\"group\"][group]\n-                poetry_content[\"group\"][group] = group_table\n+                groups[group] = table()\n+                groups.add(nl())\n+\n+            this_group = groups[group]\n \n-            if \"dependencies\" not in poetry_content[\"group\"][group]:\n-                poetry_content[\"group\"][group][\"dependencies\"] = table()\n+            if \"dependencies\" not in this_group:\n+                this_group[\"dependencies\"] = table()\n \n-            section = poetry_content[\"group\"][group][\"dependencies\"]\n+            section = this_group[\"dependencies\"]\n \n         existing_packages = self.get_existing_packages_from_input(packages, section)\n \n@@ -266,7 +266,6 @@\n             )\n \n         # Refresh the locker\n-        content[\"tool\"][\"poetry\"] = poetry_content\n         self.poetry.locker.set_pyproject_data(content)\n         self.installer.set_locker(self.poetry.locker)\n", "issue": "Improve error message to EmptyTableNameError\n- **Poetry version**: 1.7.1\r\n- **Python version**: 3.11.5\r\n- **OS version and name**: win32 nt\r\n- **pyproject.toml**: (https://gist.github.com/biofsphere/89895e6ff22f01cc7ce63100d9fc5ede)\r\n\r\n- [X] I am on the [latest](https://github.com/python-poetry/poetry/releases/latest) stable Poetry version, installed using a [recommended method](https://python-poetry.org/docs/#installation).\r\n- [X] I have searched the [issues](https://github.com/python-poetry/poetry/issues) of this repo and believe that this is not a duplicate.\r\n- [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.\r\n- [X] If an exception occurs when executing a command, I executed it again in debug mode (`-vvv` option) and have included the output below.\r\n\r\n## Issue (suggestion)\r\nWhile adding packages, I run into an EmptyTableNameError message **Empty table name at line 1 col 19**. I spent a whole afternoon searching for a solution. It was only when I decided to open this issue that, by testing and retesting my shell commands I realized what was going on. This did not happen to most packages I installed, but it did to django-debug-toolbar and ipython. I went off to search communalities between both packages and tried to understand **poetry debug info --verbose output**, digging something for quite a while. When I gave up and decided to make a gist and open a new issue, voala!! I noticed I run **poetry add django-debug-toolbar --group==local**... ...yes, with double equal signs!!!! \r\n\r\nI am just sharing this so you know the error message threw me way off the mark, for a mere misspelling mistake. If you could improve the EmptyTableNameError message to alert beginners with something like \"Check your spelling\" or something, that would have me saved hours!. My bad. Checking spelling is pretty basic and I did for letter, but missing the double equal signs was such a bummer.\r\n\r\nAnyway, just a quick note. I am really enjoying this package manager. I don't think I will ever get back to pip alone again.  \r\n \r\n<!-- Thanks!! \ud83d\ude4c \u2764 -->\n", "before_files": [{"content": "from __future__ import annotations\n\nimport contextlib\n\nfrom typing import TYPE_CHECKING\nfrom typing import Any\nfrom typing import ClassVar\n\nfrom cleo.helpers import argument\nfrom cleo.helpers import option\nfrom packaging.utils import canonicalize_name\nfrom poetry.core.packages.dependency_group import MAIN_GROUP\nfrom tomlkit.toml_document import TOMLDocument\n\nfrom poetry.console.commands.init import InitCommand\nfrom poetry.console.commands.installer_command import InstallerCommand\n\n\nif TYPE_CHECKING:\n    from cleo.io.inputs.argument import Argument\n    from cleo.io.inputs.option import Option\n\n\nclass AddCommand(InstallerCommand, InitCommand):\n    name = \"add\"\n    description = \"Adds a new dependency to <comment>pyproject.toml</> and installs it.\"\n\n    arguments: ClassVar[list[Argument]] = [\n        argument(\"name\", \"The packages to add.\", multiple=True)\n    ]\n    options: ClassVar[list[Option]] = [\n        option(\n            \"group\",\n            \"-G\",\n            \"The group to add the dependency to.\",\n            flag=False,\n            default=MAIN_GROUP,\n        ),\n        option(\n            \"dev\",\n            \"D\",\n            \"Add as a development dependency. (<warning>Deprecated</warning>) Use\"\n            \" --group=dev instead.\",\n        ),\n        option(\"editable\", \"e\", \"Add vcs/path dependencies as editable.\"),\n        option(\n            \"extras\",\n            \"E\",\n            \"Extras to activate for the dependency.\",\n            flag=False,\n            multiple=True,\n        ),\n        option(\"optional\", None, \"Add as an optional dependency.\"),\n        option(\n            \"python\",\n            None,\n            \"Python version for which the dependency must be installed.\",\n            flag=False,\n        ),\n        option(\n            \"platform\",\n            None,\n            \"Platforms for which the dependency must be installed.\",\n            flag=False,\n        ),\n        option(\n            \"source\",\n            None,\n            \"Name of the source to use to install the package.\",\n            flag=False,\n        ),\n        option(\"allow-prereleases\", None, \"Accept prereleases.\"),\n        option(\n            \"dry-run\",\n            None,\n            \"Output the operations but do not execute anything (implicitly enables\"\n            \" --verbose).\",\n        ),\n        option(\"lock\", None, \"Do not perform operations (only update the lockfile).\"),\n    ]\n    examples = \"\"\"\\\nIf you do not specify a version constraint, poetry will choose a suitable one based on\\\n the available package versions.\n\nYou can specify a package in the following forms:\n  - A single name (<b>requests</b>)\n  - A name and a constraint (<b>requests@^2.23.0</b>)\n  - A git url (<b>git+https://github.com/python-poetry/poetry.git</b>)\n  - A git url with a revision\\\n (<b>git+https://github.com/python-poetry/poetry.git#develop</b>)\n  - A subdirectory of a git repository\\\n (<b>git+https://github.com/python-poetry/poetry.git#subdirectory=tests/fixtures/sample_project</b>)\n  - A git SSH url (<b>git+ssh://github.com/python-poetry/poetry.git</b>)\n  - A git SSH url with a revision\\\n (<b>git+ssh://github.com/python-poetry/poetry.git#develop</b>)\n  - A file path (<b>../my-package/my-package.whl</b>)\n  - A directory (<b>../my-package/</b>)\n  - A url (<b>https://example.com/packages/my-package-0.1.0.tar.gz</b>)\n\"\"\"\n    help = f\"\"\"\\\nThe add command adds required packages to your <comment>pyproject.toml</> and installs\\\n them.\n\n{examples}\n\"\"\"\n\n    loggers: ClassVar[list[str]] = [\n        \"poetry.repositories.pypi_repository\",\n        \"poetry.inspection.info\",\n    ]\n\n    def handle(self) -> int:\n        from poetry.core.constraints.version import parse_constraint\n        from tomlkit import inline_table\n        from tomlkit import parse as parse_toml\n        from tomlkit import table\n\n        from poetry.factory import Factory\n\n        packages = self.argument(\"name\")\n        if self.option(\"dev\"):\n            self.line_error(\n                \"<warning>The --dev option is deprecated, \"\n                \"use the `--group dev` notation instead.</warning>\"\n            )\n            group = \"dev\"\n        else:\n            group = self.option(\"group\", self.default_group or MAIN_GROUP)\n\n        if self.option(\"extras\") and len(packages) > 1:\n            raise ValueError(\n                \"You can only specify one package when using the --extras option\"\n            )\n\n        # tomlkit types are awkward to work with, treat content as a mostly untyped\n        # dictionary.\n        content: dict[str, Any] = self.poetry.file.read()\n        poetry_content = content[\"tool\"][\"poetry\"]\n        project_name = (\n            canonicalize_name(name) if (name := poetry_content.get(\"name\")) else None\n        )\n\n        if group == MAIN_GROUP:\n            if \"dependencies\" not in poetry_content:\n                poetry_content[\"dependencies\"] = table()\n\n            section = poetry_content[\"dependencies\"]\n        else:\n            if \"group\" not in poetry_content:\n                poetry_content[\"group\"] = table(is_super_table=True)\n\n            groups = poetry_content[\"group\"]\n            if group not in groups:\n                dependencies_toml: dict[str, Any] = parse_toml(\n                    f\"[tool.poetry.group.{group}.dependencies]\\n\\n\"\n                )\n                group_table = dependencies_toml[\"tool\"][\"poetry\"][\"group\"][group]\n                poetry_content[\"group\"][group] = group_table\n\n            if \"dependencies\" not in poetry_content[\"group\"][group]:\n                poetry_content[\"group\"][group][\"dependencies\"] = table()\n\n            section = poetry_content[\"group\"][group][\"dependencies\"]\n\n        existing_packages = self.get_existing_packages_from_input(packages, section)\n\n        if existing_packages:\n            self.notify_about_existing_packages(existing_packages)\n\n        packages = [name for name in packages if name not in existing_packages]\n\n        if not packages:\n            self.line(\"Nothing to add.\")\n            return 0\n\n        requirements = self._determine_requirements(\n            packages,\n            allow_prereleases=self.option(\"allow-prereleases\"),\n            source=self.option(\"source\"),\n        )\n\n        for _constraint in requirements:\n            version = _constraint.get(\"version\")\n            if version is not None:\n                # Validate version constraint\n                assert isinstance(version, str)\n                parse_constraint(version)\n\n            constraint: dict[str, Any] = inline_table()\n            for name, value in _constraint.items():\n                if name == \"name\":\n                    continue\n\n                constraint[name] = value\n\n            if self.option(\"optional\"):\n                constraint[\"optional\"] = True\n\n            if self.option(\"allow-prereleases\"):\n                constraint[\"allow-prereleases\"] = True\n\n            if self.option(\"extras\"):\n                extras = []\n                for extra in self.option(\"extras\"):\n                    extras += extra.split()\n\n                constraint[\"extras\"] = extras\n\n            if self.option(\"editable\"):\n                if \"git\" in _constraint or \"path\" in _constraint:\n                    constraint[\"develop\"] = True\n                else:\n                    self.line_error(\n                        \"\\n\"\n                        \"<error>Failed to add packages. \"\n                        \"Only vcs/path dependencies support editable installs. \"\n                        f\"<c1>{_constraint['name']}</c1> is neither.\"\n                    )\n                    self.line_error(\"\\nNo changes were applied.\")\n                    return 1\n\n            if self.option(\"python\"):\n                constraint[\"python\"] = self.option(\"python\")\n\n            if self.option(\"platform\"):\n                constraint[\"platform\"] = self.option(\"platform\")\n\n            if self.option(\"source\"):\n                constraint[\"source\"] = self.option(\"source\")\n\n            if len(constraint) == 1 and \"version\" in constraint:\n                constraint = constraint[\"version\"]\n\n            constraint_name = _constraint[\"name\"]\n            assert isinstance(constraint_name, str)\n\n            canonical_constraint_name = canonicalize_name(constraint_name)\n\n            if canonical_constraint_name == project_name:\n                self.line_error(\n                    f\"<error>Cannot add dependency on <c1>{constraint_name}</c1> to\"\n                    \" project with the same name.\"\n                )\n                self.line_error(\"\\nNo changes were applied.\")\n                return 1\n\n            for key in section:\n                if canonicalize_name(key) == canonical_constraint_name:\n                    section[key] = constraint\n                    break\n            else:\n                section[constraint_name] = constraint\n\n            with contextlib.suppress(ValueError):\n                self.poetry.package.dependency_group(group).remove_dependency(\n                    constraint_name\n                )\n\n            self.poetry.package.add_dependency(\n                Factory.create_dependency(\n                    constraint_name,\n                    constraint,\n                    groups=[group],\n                    root_dir=self.poetry.file.path.parent,\n                )\n            )\n\n        # Refresh the locker\n        content[\"tool\"][\"poetry\"] = poetry_content\n        self.poetry.locker.set_pyproject_data(content)\n        self.installer.set_locker(self.poetry.locker)\n\n        # Cosmetic new line\n        self.line(\"\")\n\n        self.installer.set_package(self.poetry.package)\n        self.installer.dry_run(self.option(\"dry-run\"))\n        self.installer.verbose(self.io.is_verbose())\n        self.installer.update(True)\n        self.installer.execute_operations(not self.option(\"lock\"))\n\n        self.installer.whitelist([r[\"name\"] for r in requirements])\n\n        status = self.installer.run()\n\n        if status == 0 and not self.option(\"dry-run\"):\n            assert isinstance(content, TOMLDocument)\n            self.poetry.file.write(content)\n\n        return status\n\n    def get_existing_packages_from_input(\n        self, packages: list[str], section: dict[str, Any]\n    ) -> list[str]:\n        existing_packages = []\n\n        for name in packages:\n            for key in section:\n                if canonicalize_name(key) == canonicalize_name(name):\n                    existing_packages.append(name)\n\n        return existing_packages\n\n    @property\n    def _hint_update_packages(self) -> str:\n        return (\n            \"\\nIf you want to update it to the latest compatible version, you can use\"\n            \" `poetry update package`.\\nIf you prefer to upgrade it to the latest\"\n            \" available version, you can use `poetry add package@latest`.\\n\"\n        )\n\n    def notify_about_existing_packages(self, existing_packages: list[str]) -> None:\n        self.line(\n            \"The following packages are already present in the pyproject.toml and will\"\n            \" be skipped:\\n\"\n        )\n        for name in existing_packages:\n            self.line(f\"  - <c1>{name}</c1>\")\n        self.line(self._hint_update_packages)\n", "path": "src/poetry/console/commands/add.py"}], "after_files": [{"content": "from __future__ import annotations\n\nimport contextlib\n\nfrom typing import TYPE_CHECKING\nfrom typing import Any\nfrom typing import ClassVar\n\nfrom cleo.helpers import argument\nfrom cleo.helpers import option\nfrom packaging.utils import canonicalize_name\nfrom poetry.core.packages.dependency_group import MAIN_GROUP\nfrom tomlkit.toml_document import TOMLDocument\n\nfrom poetry.console.commands.init import InitCommand\nfrom poetry.console.commands.installer_command import InstallerCommand\n\n\nif TYPE_CHECKING:\n    from cleo.io.inputs.argument import Argument\n    from cleo.io.inputs.option import Option\n\n\nclass AddCommand(InstallerCommand, InitCommand):\n    name = \"add\"\n    description = \"Adds a new dependency to <comment>pyproject.toml</> and installs it.\"\n\n    arguments: ClassVar[list[Argument]] = [\n        argument(\"name\", \"The packages to add.\", multiple=True)\n    ]\n    options: ClassVar[list[Option]] = [\n        option(\n            \"group\",\n            \"-G\",\n            \"The group to add the dependency to.\",\n            flag=False,\n            default=MAIN_GROUP,\n        ),\n        option(\n            \"dev\",\n            \"D\",\n            \"Add as a development dependency. (<warning>Deprecated</warning>) Use\"\n            \" --group=dev instead.\",\n        ),\n        option(\"editable\", \"e\", \"Add vcs/path dependencies as editable.\"),\n        option(\n            \"extras\",\n            \"E\",\n            \"Extras to activate for the dependency.\",\n            flag=False,\n            multiple=True,\n        ),\n        option(\"optional\", None, \"Add as an optional dependency.\"),\n        option(\n            \"python\",\n            None,\n            \"Python version for which the dependency must be installed.\",\n            flag=False,\n        ),\n        option(\n            \"platform\",\n            None,\n            \"Platforms for which the dependency must be installed.\",\n            flag=False,\n        ),\n        option(\n            \"source\",\n            None,\n            \"Name of the source to use to install the package.\",\n            flag=False,\n        ),\n        option(\"allow-prereleases\", None, \"Accept prereleases.\"),\n        option(\n            \"dry-run\",\n            None,\n            \"Output the operations but do not execute anything (implicitly enables\"\n            \" --verbose).\",\n        ),\n        option(\"lock\", None, \"Do not perform operations (only update the lockfile).\"),\n    ]\n    examples = \"\"\"\\\nIf you do not specify a version constraint, poetry will choose a suitable one based on\\\n the available package versions.\n\nYou can specify a package in the following forms:\n  - A single name (<b>requests</b>)\n  - A name and a constraint (<b>requests@^2.23.0</b>)\n  - A git url (<b>git+https://github.com/python-poetry/poetry.git</b>)\n  - A git url with a revision\\\n (<b>git+https://github.com/python-poetry/poetry.git#develop</b>)\n  - A subdirectory of a git repository\\\n (<b>git+https://github.com/python-poetry/poetry.git#subdirectory=tests/fixtures/sample_project</b>)\n  - A git SSH url (<b>git+ssh://github.com/python-poetry/poetry.git</b>)\n  - A git SSH url with a revision\\\n (<b>git+ssh://github.com/python-poetry/poetry.git#develop</b>)\n  - A file path (<b>../my-package/my-package.whl</b>)\n  - A directory (<b>../my-package/</b>)\n  - A url (<b>https://example.com/packages/my-package-0.1.0.tar.gz</b>)\n\"\"\"\n    help = f\"\"\"\\\nThe add command adds required packages to your <comment>pyproject.toml</> and installs\\\n them.\n\n{examples}\n\"\"\"\n\n    loggers: ClassVar[list[str]] = [\n        \"poetry.repositories.pypi_repository\",\n        \"poetry.inspection.info\",\n    ]\n\n    def handle(self) -> int:\n        from poetry.core.constraints.version import parse_constraint\n        from tomlkit import inline_table\n        from tomlkit import nl\n        from tomlkit import table\n\n        from poetry.factory import Factory\n\n        packages = self.argument(\"name\")\n        if self.option(\"dev\"):\n            self.line_error(\n                \"<warning>The --dev option is deprecated, \"\n                \"use the `--group dev` notation instead.</warning>\"\n            )\n            group = \"dev\"\n        else:\n            group = self.option(\"group\", self.default_group or MAIN_GROUP)\n\n        if self.option(\"extras\") and len(packages) > 1:\n            raise ValueError(\n                \"You can only specify one package when using the --extras option\"\n            )\n\n        # tomlkit types are awkward to work with, treat content as a mostly untyped\n        # dictionary.\n        content: dict[str, Any] = self.poetry.file.read()\n        poetry_content = content[\"tool\"][\"poetry\"]\n        project_name = (\n            canonicalize_name(name) if (name := poetry_content.get(\"name\")) else None\n        )\n\n        if group == MAIN_GROUP:\n            if \"dependencies\" not in poetry_content:\n                poetry_content[\"dependencies\"] = table()\n\n            section = poetry_content[\"dependencies\"]\n        else:\n            if \"group\" not in poetry_content:\n                poetry_content[\"group\"] = table(is_super_table=True)\n\n            groups = poetry_content[\"group\"]\n\n            if group not in groups:\n                groups[group] = table()\n                groups.add(nl())\n\n            this_group = groups[group]\n\n            if \"dependencies\" not in this_group:\n                this_group[\"dependencies\"] = table()\n\n            section = this_group[\"dependencies\"]\n\n        existing_packages = self.get_existing_packages_from_input(packages, section)\n\n        if existing_packages:\n            self.notify_about_existing_packages(existing_packages)\n\n        packages = [name for name in packages if name not in existing_packages]\n\n        if not packages:\n            self.line(\"Nothing to add.\")\n            return 0\n\n        requirements = self._determine_requirements(\n            packages,\n            allow_prereleases=self.option(\"allow-prereleases\"),\n            source=self.option(\"source\"),\n        )\n\n        for _constraint in requirements:\n            version = _constraint.get(\"version\")\n            if version is not None:\n                # Validate version constraint\n                assert isinstance(version, str)\n                parse_constraint(version)\n\n            constraint: dict[str, Any] = inline_table()\n            for name, value in _constraint.items():\n                if name == \"name\":\n                    continue\n\n                constraint[name] = value\n\n            if self.option(\"optional\"):\n                constraint[\"optional\"] = True\n\n            if self.option(\"allow-prereleases\"):\n                constraint[\"allow-prereleases\"] = True\n\n            if self.option(\"extras\"):\n                extras = []\n                for extra in self.option(\"extras\"):\n                    extras += extra.split()\n\n                constraint[\"extras\"] = extras\n\n            if self.option(\"editable\"):\n                if \"git\" in _constraint or \"path\" in _constraint:\n                    constraint[\"develop\"] = True\n                else:\n                    self.line_error(\n                        \"\\n\"\n                        \"<error>Failed to add packages. \"\n                        \"Only vcs/path dependencies support editable installs. \"\n                        f\"<c1>{_constraint['name']}</c1> is neither.\"\n                    )\n                    self.line_error(\"\\nNo changes were applied.\")\n                    return 1\n\n            if self.option(\"python\"):\n                constraint[\"python\"] = self.option(\"python\")\n\n            if self.option(\"platform\"):\n                constraint[\"platform\"] = self.option(\"platform\")\n\n            if self.option(\"source\"):\n                constraint[\"source\"] = self.option(\"source\")\n\n            if len(constraint) == 1 and \"version\" in constraint:\n                constraint = constraint[\"version\"]\n\n            constraint_name = _constraint[\"name\"]\n            assert isinstance(constraint_name, str)\n\n            canonical_constraint_name = canonicalize_name(constraint_name)\n\n            if canonical_constraint_name == project_name:\n                self.line_error(\n                    f\"<error>Cannot add dependency on <c1>{constraint_name}</c1> to\"\n                    \" project with the same name.\"\n                )\n                self.line_error(\"\\nNo changes were applied.\")\n                return 1\n\n            for key in section:\n                if canonicalize_name(key) == canonical_constraint_name:\n                    section[key] = constraint\n                    break\n            else:\n                section[constraint_name] = constraint\n\n            with contextlib.suppress(ValueError):\n                self.poetry.package.dependency_group(group).remove_dependency(\n                    constraint_name\n                )\n\n            self.poetry.package.add_dependency(\n                Factory.create_dependency(\n                    constraint_name,\n                    constraint,\n                    groups=[group],\n                    root_dir=self.poetry.file.path.parent,\n                )\n            )\n\n        # Refresh the locker\n        self.poetry.locker.set_pyproject_data(content)\n        self.installer.set_locker(self.poetry.locker)\n\n        # Cosmetic new line\n        self.line(\"\")\n\n        self.installer.set_package(self.poetry.package)\n        self.installer.dry_run(self.option(\"dry-run\"))\n        self.installer.verbose(self.io.is_verbose())\n        self.installer.update(True)\n        self.installer.execute_operations(not self.option(\"lock\"))\n\n        self.installer.whitelist([r[\"name\"] for r in requirements])\n\n        status = self.installer.run()\n\n        if status == 0 and not self.option(\"dry-run\"):\n            assert isinstance(content, TOMLDocument)\n            self.poetry.file.write(content)\n\n        return status\n\n    def get_existing_packages_from_input(\n        self, packages: list[str], section: dict[str, Any]\n    ) -> list[str]:\n        existing_packages = []\n\n        for name in packages:\n            for key in section:\n                if canonicalize_name(key) == canonicalize_name(name):\n                    existing_packages.append(name)\n\n        return existing_packages\n\n    @property\n    def _hint_update_packages(self) -> str:\n        return (\n            \"\\nIf you want to update it to the latest compatible version, you can use\"\n            \" `poetry update package`.\\nIf you prefer to upgrade it to the latest\"\n            \" available version, you can use `poetry add package@latest`.\\n\"\n        )\n\n    def notify_about_existing_packages(self, existing_packages: list[str]) -> None:\n        self.line(\n            \"The following packages are already present in the pyproject.toml and will\"\n            \" be skipped:\\n\"\n        )\n        for name in existing_packages:\n            self.line(f\"  - <c1>{name}</c1>\")\n        self.line(self._hint_update_packages)\n", "path": "src/poetry/console/commands/add.py"}]}