From bd42e8525dfbd47d51b4eda1303f679a8fd71a89 Mon Sep 17 00:00:00 2001 From: Marlon Costa Date: Sat, 31 Oct 2026 17:03:01 -0300 Subject: [PATCH 1/2] Classify autoimport project sources by path containment get_package_source treated a package as part of the project when the project address was a substring of its path, so a sibling directory such as "-other", or a path leaving the project through "..", was indexed as project source. Resolve the package path and require it to lie under the project root. (cherry picked from commit 5dcf5eede69ce26e2546ae407597af9d55afd1c8, project containment only) Co-Authored-By: Claude Opus 5.5 --- rope/contrib/autoimport/utils.py | 4 +++- ropetest/contrib/autoimport/utilstest.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/rope/contrib/autoimport/utils.py b/rope/contrib/autoimport/utils.py index 11ee6f20e..324ea3173 100644 --- a/rope/contrib/autoimport/utils.py +++ b/rope/contrib/autoimport/utils.py @@ -49,7 +49,9 @@ def get_package_source( """Detect the source of a given package. Rudimentary implementation.""" if name in sys.builtin_module_names: return Source.BUILTIN - if project is not None and project.address in str(package): + if project is not None and package.resolve().is_relative_to( + project.root.pathlib.resolve() + ): return Source.PROJECT if "site-packages" in package.parts: return Source.SITE_PACKAGE diff --git a/ropetest/contrib/autoimport/utilstest.py b/ropetest/contrib/autoimport/utilstest.py index 511e1a541..d807debe2 100644 --- a/ropetest/contrib/autoimport/utilstest.py +++ b/ropetest/contrib/autoimport/utilstest.py @@ -14,6 +14,25 @@ def test_get_package_source_not_project(mod1_path): assert utils.get_package_source(mod1_path, None, "") == Source.UNKNOWN +def test_get_package_source_project_prefix_is_not_ancestry(project): + sibling = Path(project.address + "-other") / "module.py" + assert utils.get_package_source(sibling, project, "module") == Source.UNKNOWN + + +def test_get_package_source_project_sibling(project): + sibling = project.root.pathlib.with_name(project.root.pathlib.name + "-other") + sibling.mkdir() + module = sibling / "outside.py" + module.touch() + try: + assert utils.get_package_source(module, project, "outside") == Source.UNKNOWN + escaped = project.root.pathlib / ".." / sibling.name / module.name + assert utils.get_package_source(escaped, project, "outside") == Source.UNKNOWN + finally: + module.unlink() + sibling.rmdir() + + def test_get_package_source_pytest(example_external_package_path): # pytest is not installed as part of the standard library # but should be installed into site_packages, From 3133dbc618bb9abfe627d70f06faa8a1a980e3e4 Mon Sep 17 00:00:00 2001 From: Marlon Costa Date: Sat, 31 Oct 2026 17:05:19 -0300 Subject: [PATCH 2/2] Add changelog entry Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee7ddf653..3a6d51ba8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - #895 patchedast Starred and keyword now consumes their syntactically expected and ** (@lieryan) - #896 patchedast cleanup and refactoring (@lieryan) - #905 Ignore `node_modules` directories by default when scanning project files and source folders. (@marcoeangeli) +- #922 Classify autoimport project sources by path containment (@marlon-costa-dc) # Release 1.15.0