We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
RecursionError when installing mkdocs-material
<!-- Checked checkbox should look like this: [x] -->
- [x] I am on the [latest](https://github.com/python-poetry/poetry/releases/latest) Poetry version.
- [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] If an exception occurs when executing a command, I executed it again in debug mode (`-vvv` option).

- **OS version and name**: Windows 10 Pro 1909 18363.719
- **Poetry version**:  1.0.5
- **Link of a [Gist](https://gist.github.com/) with the contents of your pyproject.toml file**: https://gist.github.com/ndevln/f27b5b64251241d40e1b960ec96b8b68

## Issue
Hi,

when running: `poetry install -E docs_material` I get the following error:

```
[RecursionError]
maximum recursion depth exceeded
```

There are quite a few similar issues (like #2329), but it seems that this problem is package specific?!?

Thank you for poetry and your effort :)




--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `poetry/utils/extras.py`
Content:
```
1 from typing import Iterator
2 from typing import List
3 from typing import Mapping
4 from typing import Sequence
5 
6 from poetry.core.packages import Package
7 from poetry.utils.helpers import canonicalize_name
8 
9 
10 def get_extra_package_names(
11     packages,  # type: Sequence[Package]
12     extras,  # type: Mapping[str, List[str]]
13     extra_names,  # type: Sequence[str]
14 ):  # type: (...) -> Iterator[str]
15     """
16     Returns all package names required by the given extras.
17 
18     :param packages: A collection of packages, such as from Repository.packages
19     :param extras: A mapping of `extras` names to lists of package names, as defined
20         in the `extras` section of `poetry.lock`.
21     :param extra_names: A list of strings specifying names of extra groups to resolve.
22     """
23     if not extra_names:
24         return []
25 
26     # lookup for packages by name, faster than looping over packages repeatedly
27     packages_by_name = {package.name: package for package in packages}
28 
29     # get and flatten names of packages we've opted into as extras
30     extra_package_names = [
31         canonicalize_name(extra_package_name)
32         for extra_name in extra_names
33         for extra_package_name in extras.get(extra_name, ())
34     ]
35 
36     def _extra_packages(package_names):
37         """Recursively find dependencies for packages names"""
38         # for each extra pacakge name
39         for package_name in package_names:
40             # Find the actual Package object. A missing key indicates an implicit
41             # dependency (like setuptools), which should be ignored
42             package = packages_by_name.get(canonicalize_name(package_name))
43             if package:
44                 yield package.name
45                 # Recurse for dependencies
46                 for dependency_package_name in _extra_packages(
47                     dependency.name for dependency in package.requires
48                 ):
49                     yield dependency_package_name
50 
51     return _extra_packages(extra_package_names)
52
```
--- 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/poetry/utils/extras.py b/poetry/utils/extras.py
--- a/poetry/utils/extras.py
+++ b/poetry/utils/extras.py
@@ -33,6 +33,9 @@
         for extra_package_name in extras.get(extra_name, ())
     ]
 
+    # keep record of packages seen during recursion in order to avoid recursion error
+    seen_package_names = set()
+
     def _extra_packages(package_names):
         """Recursively find dependencies for packages names"""
         # for each extra pacakge name
@@ -41,11 +44,16 @@
             # dependency (like setuptools), which should be ignored
             package = packages_by_name.get(canonicalize_name(package_name))
             if package:
-                yield package.name
+                if package.name not in seen_package_names:
+                    seen_package_names.add(package.name)
+                    yield package.name
                 # Recurse for dependencies
                 for dependency_package_name in _extra_packages(
-                    dependency.name for dependency in package.requires
+                    dependency.name
+                    for dependency in package.requires
+                    if dependency.name not in seen_package_names
                 ):
+                    seen_package_names.add(dependency_package_name)
                     yield dependency_package_name
 
     return _extra_packages(extra_package_names)

{"golden_diff": "diff --git a/poetry/utils/extras.py b/poetry/utils/extras.py\n--- a/poetry/utils/extras.py\n+++ b/poetry/utils/extras.py\n@@ -33,6 +33,9 @@\n         for extra_package_name in extras.get(extra_name, ())\n     ]\n \n+    # keep record of packages seen during recursion in order to avoid recursion error\n+    seen_package_names = set()\n+\n     def _extra_packages(package_names):\n         \"\"\"Recursively find dependencies for packages names\"\"\"\n         # for each extra pacakge name\n@@ -41,11 +44,16 @@\n             # dependency (like setuptools), which should be ignored\n             package = packages_by_name.get(canonicalize_name(package_name))\n             if package:\n-                yield package.name\n+                if package.name not in seen_package_names:\n+                    seen_package_names.add(package.name)\n+                    yield package.name\n                 # Recurse for dependencies\n                 for dependency_package_name in _extra_packages(\n-                    dependency.name for dependency in package.requires\n+                    dependency.name\n+                    for dependency in package.requires\n+                    if dependency.name not in seen_package_names\n                 ):\n+                    seen_package_names.add(dependency_package_name)\n                     yield dependency_package_name\n \n     return _extra_packages(extra_package_names)\n", "issue": "RecursionError when installing mkdocs-material\n<!-- Checked checkbox should look like this: [x] -->\r\n- [x] I am on the [latest](https://github.com/python-poetry/poetry/releases/latest) Poetry version.\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] If an exception occurs when executing a command, I executed it again in debug mode (`-vvv` option).\r\n\r\n- **OS version and name**: Windows 10 Pro 1909 18363.719\r\n- **Poetry version**:  1.0.5\r\n- **Link of a [Gist](https://gist.github.com/) with the contents of your pyproject.toml file**: https://gist.github.com/ndevln/f27b5b64251241d40e1b960ec96b8b68\r\n\r\n## Issue\r\nHi,\r\n\r\nwhen running: `poetry install -E docs_material` I get the following error:\r\n\r\n```\r\n[RecursionError]\r\nmaximum recursion depth exceeded\r\n```\r\n\r\nThere are quite a few similar issues (like #2329), but it seems that this problem is package specific?!?\r\n\r\nThank you for poetry and your effort :)\r\n\r\n\r\n\n", "before_files": [{"content": "from typing import Iterator\nfrom typing import List\nfrom typing import Mapping\nfrom typing import Sequence\n\nfrom poetry.core.packages import Package\nfrom poetry.utils.helpers import canonicalize_name\n\n\ndef get_extra_package_names(\n    packages,  # type: Sequence[Package]\n    extras,  # type: Mapping[str, List[str]]\n    extra_names,  # type: Sequence[str]\n):  # type: (...) -> Iterator[str]\n    \"\"\"\n    Returns all package names required by the given extras.\n\n    :param packages: A collection of packages, such as from Repository.packages\n    :param extras: A mapping of `extras` names to lists of package names, as defined\n        in the `extras` section of `poetry.lock`.\n    :param extra_names: A list of strings specifying names of extra groups to resolve.\n    \"\"\"\n    if not extra_names:\n        return []\n\n    # lookup for packages by name, faster than looping over packages repeatedly\n    packages_by_name = {package.name: package for package in packages}\n\n    # get and flatten names of packages we've opted into as extras\n    extra_package_names = [\n        canonicalize_name(extra_package_name)\n        for extra_name in extra_names\n        for extra_package_name in extras.get(extra_name, ())\n    ]\n\n    def _extra_packages(package_names):\n        \"\"\"Recursively find dependencies for packages names\"\"\"\n        # for each extra pacakge name\n        for package_name in package_names:\n            # Find the actual Package object. A missing key indicates an implicit\n            # dependency (like setuptools), which should be ignored\n            package = packages_by_name.get(canonicalize_name(package_name))\n            if package:\n                yield package.name\n                # Recurse for dependencies\n                for dependency_package_name in _extra_packages(\n                    dependency.name for dependency in package.requires\n                ):\n                    yield dependency_package_name\n\n    return _extra_packages(extra_package_names)\n", "path": "poetry/utils/extras.py"}], "after_files": [{"content": "from typing import Iterator\nfrom typing import List\nfrom typing import Mapping\nfrom typing import Sequence\n\nfrom poetry.core.packages import Package\nfrom poetry.utils.helpers import canonicalize_name\n\n\ndef get_extra_package_names(\n    packages,  # type: Sequence[Package]\n    extras,  # type: Mapping[str, List[str]]\n    extra_names,  # type: Sequence[str]\n):  # type: (...) -> Iterator[str]\n    \"\"\"\n    Returns all package names required by the given extras.\n\n    :param packages: A collection of packages, such as from Repository.packages\n    :param extras: A mapping of `extras` names to lists of package names, as defined\n        in the `extras` section of `poetry.lock`.\n    :param extra_names: A list of strings specifying names of extra groups to resolve.\n    \"\"\"\n    if not extra_names:\n        return []\n\n    # lookup for packages by name, faster than looping over packages repeatedly\n    packages_by_name = {package.name: package for package in packages}\n\n    # get and flatten names of packages we've opted into as extras\n    extra_package_names = [\n        canonicalize_name(extra_package_name)\n        for extra_name in extra_names\n        for extra_package_name in extras.get(extra_name, ())\n    ]\n\n    # keep record of packages seen during recursion in order to avoid recursion error\n    seen_package_names = set()\n\n    def _extra_packages(package_names):\n        \"\"\"Recursively find dependencies for packages names\"\"\"\n        # for each extra pacakge name\n        for package_name in package_names:\n            # Find the actual Package object. A missing key indicates an implicit\n            # dependency (like setuptools), which should be ignored\n            package = packages_by_name.get(canonicalize_name(package_name))\n            if package:\n                if package.name not in seen_package_names:\n                    seen_package_names.add(package.name)\n                    yield package.name\n                # Recurse for dependencies\n                for dependency_package_name in _extra_packages(\n                    dependency.name\n                    for dependency in package.requires\n                    if dependency.name not in seen_package_names\n                ):\n                    seen_package_names.add(dependency_package_name)\n                    yield dependency_package_name\n\n    return _extra_packages(extra_package_names)\n", "path": "poetry/utils/extras.py"}]}