From 8b8b97a652178788bf5751ad8a372ceb161965be Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Fri, 28 Aug 2020 06:22:49 +0200 Subject: [PATCH] Handle circular dependencies when getting extras (#2787) Resolves: #2376 --- poetry/utils/extras.py | 12 ++++++++++-- tests/utils/test_extras.py | 12 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/poetry/utils/extras.py b/poetry/utils/extras.py index 32b02ee9b00..c97d6ee79e5 100644 --- a/poetry/utils/extras.py +++ b/poetry/utils/extras.py @@ -33,6 +33,9 @@ def get_extra_package_names( 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 @@ def _extra_packages(package_names): # 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) diff --git a/tests/utils/test_extras.py b/tests/utils/test_extras.py index 424ccc5ee9e..41307eab67a 100644 --- a/tests/utils/test_extras.py +++ b/tests/utils/test_extras.py @@ -9,6 +9,12 @@ _PACKAGE_BAR = Package("bar", "0.3.0") _PACKAGE_BAR.add_dependency("foo") +# recursive dependency +_PACKAGE_BAZ = Package("baz", "0.4.0") +_PACKAGE_BAZ.add_dependency("quix") +_PACKAGE_QUIX = Package("quix", "0.5.0") +_PACKAGE_QUIX.add_dependency("baz") + @pytest.mark.parametrize( "packages,extras,extra_names,expected_extra_package_names", @@ -40,6 +46,12 @@ ["group0", "group1"], ["bar", "foo", "spam"], ), + ( + [_PACKAGE_BAZ, _PACKAGE_QUIX], + {"group0": ["baz"], "group1": ["quix"]}, + ["group0", "group1"], + ["baz", "quix"], + ), ], ) def test_get_extra_package_names(