From d4e32207874a45a906532c2db69fecae1d51260c Mon Sep 17 00:00:00 2001 From: MarcusArdelean Date: Mon, 5 Feb 2024 12:50:06 +0200 Subject: [PATCH] fix: python circular deps --- pysrc/pip_resolve.py | 7 +++ test/system/inspect.spec.ts | 48 +++++++++++++++++-- .../pip-app-circular-deps/requirements.txt | 1 + 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 test/workspaces/pip-app-circular-deps/requirements.txt diff --git a/pysrc/pip_resolve.py b/pysrc/pip_resolve.py index 4ab11297..8d0e32b0 100644 --- a/pysrc/pip_resolve.py +++ b/pysrc/pip_resolve.py @@ -59,6 +59,11 @@ def create_tree_of_packages_dependencies( def create_children_recursive(root_package, key_tree, ancestors, all_packages_map): root_name = canonicalize_package_name(root_package[NAME]) + # Checks if there is a circular dependency within the packages. + # Circular package example: apache.airflow and + if root_name in ancestors: + return root_package + if root_name not in key_tree: msg = 'Required packages missing: ' + root_name if allow_missing: @@ -70,8 +75,10 @@ def create_children_recursive(root_package, key_tree, ancestors, all_packages_ma ancestors = ancestors.copy() ancestors.add(root_name) children_packages_as_dist = key_tree[root_name] + for child_dist in children_packages_as_dist: child_project_name = child_dist.project_name.lower() + if child_project_name in ancestors: continue diff --git a/test/system/inspect.spec.ts b/test/system/inspect.spec.ts index f3b4bf0a..b9af61db 100644 --- a/test/system/inspect.spec.ts +++ b/test/system/inspect.spec.ts @@ -117,7 +117,7 @@ describe('inspect', () => { { pkg: { name: 'markupsafe', - version: '2.1.4', + version: '2.1.5', }, directDeps: ['jinja2'], }, @@ -131,7 +131,7 @@ describe('inspect', () => { { pkg: { name: 'markupsafe', - version: '2.1.4', + version: '2.1.5', }, directDeps: ['jinja2'], }, @@ -173,7 +173,7 @@ describe('inspect', () => { { pkg: { name: 'markupsafe', - version: '2.1.4', + version: '2.1.5', }, directDeps: ['jinja2'], }, @@ -289,6 +289,46 @@ describe('inspect', () => { }); }); + describe('Circular deps', () => { + let tearDown; + afterEach(() => { + tearDown(); + }); + + it('Should get a valid dependency graph for circular dependencies', async () => { + const test_case = { + workspace: 'pip-app-circular-deps', + uninstallPackages: [], + pluginOpts: { allowEmpty: true }, // For Python 3.12 + expected: [ + { + pkg: { + name: 'apache-airflow', + version: '2.8.1', + }, + directDeps: ['apache-airflow'], + }, + ], + }; + testUtils.chdirWorkspaces(test_case.workspace); + testUtils.ensureVirtualenv(test_case.workspace); + tearDown = testUtils.activateVirtualenv(test_case.workspace); + testUtils.pipInstall(); + if (test_case.uninstallPackages) { + test_case.uninstallPackages.forEach((pkg) => { + testUtils.pipUninstall(pkg); + }); + } + + const result = await inspect( + '.', + FILENAMES.pip.manifest, + test_case.pluginOpts + ); + expect(result).toHaveProperty('dependencyGraph'); + }); + }); + describe('poetry projects', () => { it('should return expected dependencies for poetry-app', async () => { const workspace = 'poetry-app'; @@ -402,7 +442,7 @@ describe('inspect', () => { { pkg: { name: 'markupsafe', - version: '2.1.4', + version: '2.1.5', }, directDeps: ['jinja2'], }, diff --git a/test/workspaces/pip-app-circular-deps/requirements.txt b/test/workspaces/pip-app-circular-deps/requirements.txt new file mode 100644 index 00000000..7b0c0f05 --- /dev/null +++ b/test/workspaces/pip-app-circular-deps/requirements.txt @@ -0,0 +1 @@ +apache-airflow==2.8.1; python_version<"3.12"