From a4ec9e0b2ba38da9b1aff2807c8bdfbf4b92f7cb Mon Sep 17 00:00:00 2001 From: Maximilian Albert Date: Thu, 9 Jan 2025 20:36:10 +0000 Subject: [PATCH 1/6] Add example folder for testing implicit namespacepackage with subpackages --- .../ns1/pkg/pkgA/__init__.py | 0 .../ns2/pkg/pkgB/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/examples/implicit_namespace_package_with_subpackages/ns1/pkg/pkgA/__init__.py create mode 100644 test/examples/implicit_namespace_package_with_subpackages/ns2/pkg/pkgB/__init__.py diff --git a/test/examples/implicit_namespace_package_with_subpackages/ns1/pkg/pkgA/__init__.py b/test/examples/implicit_namespace_package_with_subpackages/ns1/pkg/pkgA/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/examples/implicit_namespace_package_with_subpackages/ns2/pkg/pkgB/__init__.py b/test/examples/implicit_namespace_package_with_subpackages/ns2/pkg/pkgB/__init__.py new file mode 100644 index 00000000..e69de29b From 61848afc7ce76ea59878e3b349413fba55c81999 Mon Sep 17 00:00:00 2001 From: Maximilian Albert Date: Mon, 13 Jan 2025 19:10:41 +0000 Subject: [PATCH 2/6] Add regression test for #2044 --- test/test_api/test_interpreter.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/test_api/test_interpreter.py b/test/test_api/test_interpreter.py index 1aa027bf..1141c7f0 100644 --- a/test/test_api/test_interpreter.py +++ b/test/test_api/test_interpreter.py @@ -9,8 +9,10 @@ import pytest import jedi import jedi.settings +from jedi import Project from jedi.inference.compiled import mixed from importlib import import_module +from test.helpers import get_example_dir class _GlobalNameSpace: @@ -591,6 +593,18 @@ def test_dict_completion(code, column, expected): assert [c.complete for c in comps] == expected +def test_implicit_namespace_package_with_subpackages(): + sys_path = [ + get_example_dir('implicit_namespace_package_with_subpackages', 'ns1'), + get_example_dir('implicit_namespace_package_with_subpackages', 'ns2'), + ] + project = Project('.', sys_path=sys_path) + interpreter = jedi.Interpreter("import pkg; pkg.", namespaces=[], project=project) + comps = interpreter.complete() + expected = ["pkgA", "pkgB"] + assert [c.complete for c in comps] == expected + + @pytest.mark.parametrize( 'code, types', [ ('dct[1]', ['int']), From 1ce0d00fb61d4c673805ccecd49e22288a66db09 Mon Sep 17 00:00:00 2001 From: Maximilian Albert Date: Tue, 14 Jan 2025 11:43:00 +0000 Subject: [PATCH 3/6] Modify test so that it actually reproduces the bug in #2044 --- test/test_api/test_interpreter.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/test_api/test_interpreter.py b/test/test_api/test_interpreter.py index 1141c7f0..c3d18f77 100644 --- a/test/test_api/test_interpreter.py +++ b/test/test_api/test_interpreter.py @@ -593,13 +593,14 @@ def test_dict_completion(code, column, expected): assert [c.complete for c in comps] == expected -def test_implicit_namespace_package_with_subpackages(): - sys_path = [ - get_example_dir('implicit_namespace_package_with_subpackages', 'ns1'), - get_example_dir('implicit_namespace_package_with_subpackages', 'ns2'), - ] - project = Project('.', sys_path=sys_path) - interpreter = jedi.Interpreter("import pkg; pkg.", namespaces=[], project=project) +def test_implicit_namespace_package_with_subpackages(monkeypatch): + sys_path_dir1 = get_example_dir('implicit_namespace_package_with_subpackages', 'ns1') + sys_path_dir2 = get_example_dir('implicit_namespace_package_with_subpackages', 'ns2') + monkeypatch.syspath_prepend(sys_path_dir1) + monkeypatch.syspath_prepend(sys_path_dir2) + + import pkg + interpreter = jedi.Interpreter("pkg.", namespaces=[locals()], project=Project('.')) comps = interpreter.complete() expected = ["pkgA", "pkgB"] assert [c.complete for c in comps] == expected From aa302c58dbe047609179f61c65d531a1ecf036fb Mon Sep 17 00:00:00 2001 From: Maximilian Albert Date: Tue, 14 Jan 2025 11:53:04 +0000 Subject: [PATCH 4/6] Rename test module to minimise risk of unexpected side-effects due to polluting sys.modules --- .../pkgA/__init__.py | 0 .../pkgB/__init__.py | 0 test/test_api/test_interpreter.py | 8 ++++++-- 3 files changed, 6 insertions(+), 2 deletions(-) rename test/examples/implicit_namespace_package_with_subpackages/ns1/{pkg => pkg_implicit_namespace_package_test}/pkgA/__init__.py (100%) rename test/examples/implicit_namespace_package_with_subpackages/ns2/{pkg => pkg_implicit_namespace_package_test}/pkgB/__init__.py (100%) diff --git a/test/examples/implicit_namespace_package_with_subpackages/ns1/pkg/pkgA/__init__.py b/test/examples/implicit_namespace_package_with_subpackages/ns1/pkg_implicit_namespace_package_test/pkgA/__init__.py similarity index 100% rename from test/examples/implicit_namespace_package_with_subpackages/ns1/pkg/pkgA/__init__.py rename to test/examples/implicit_namespace_package_with_subpackages/ns1/pkg_implicit_namespace_package_test/pkgA/__init__.py diff --git a/test/examples/implicit_namespace_package_with_subpackages/ns2/pkg/pkgB/__init__.py b/test/examples/implicit_namespace_package_with_subpackages/ns2/pkg_implicit_namespace_package_test/pkgB/__init__.py similarity index 100% rename from test/examples/implicit_namespace_package_with_subpackages/ns2/pkg/pkgB/__init__.py rename to test/examples/implicit_namespace_package_with_subpackages/ns2/pkg_implicit_namespace_package_test/pkgB/__init__.py diff --git a/test/test_api/test_interpreter.py b/test/test_api/test_interpreter.py index c3d18f77..8102d337 100644 --- a/test/test_api/test_interpreter.py +++ b/test/test_api/test_interpreter.py @@ -599,8 +599,12 @@ def test_implicit_namespace_package_with_subpackages(monkeypatch): monkeypatch.syspath_prepend(sys_path_dir1) monkeypatch.syspath_prepend(sys_path_dir2) - import pkg - interpreter = jedi.Interpreter("pkg.", namespaces=[locals()], project=Project('.')) + import pkg_implicit_namespace_package_test + interpreter = jedi.Interpreter( + "pkg_implicit_namespace_package_test.", + namespaces=[locals()], + project=Project('.') + ) comps = interpreter.complete() expected = ["pkgA", "pkgB"] assert [c.complete for c in comps] == expected From 0ad565b95b2ca0d743de2dab435617a4a5005554 Mon Sep 17 00:00:00 2001 From: Maximilian Albert Date: Wed, 15 Jan 2025 09:38:17 +0000 Subject: [PATCH 5/6] Add second test for implicit namespace package with subpackages (but direct import statement) --- test/test_api/test_interpreter.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/test/test_api/test_interpreter.py b/test/test_api/test_interpreter.py index 8102d337..8acbec1d 100644 --- a/test/test_api/test_interpreter.py +++ b/test/test_api/test_interpreter.py @@ -593,7 +593,7 @@ def test_dict_completion(code, column, expected): assert [c.complete for c in comps] == expected -def test_implicit_namespace_package_with_subpackages(monkeypatch): +def test_implicit_namespace_package_with_subpackages_v1(monkeypatch): sys_path_dir1 = get_example_dir('implicit_namespace_package_with_subpackages', 'ns1') sys_path_dir2 = get_example_dir('implicit_namespace_package_with_subpackages', 'ns2') monkeypatch.syspath_prepend(sys_path_dir1) @@ -610,6 +610,23 @@ def test_implicit_namespace_package_with_subpackages(monkeypatch): assert [c.complete for c in comps] == expected +def test_implicit_namespace_package_with_subpackages_v2(monkeypatch): + sys_path_dir1 = get_example_dir('implicit_namespace_package_with_subpackages', 'ns1') + sys_path_dir2 = get_example_dir('implicit_namespace_package_with_subpackages', 'ns2') + monkeypatch.syspath_prepend(sys_path_dir1) + monkeypatch.syspath_prepend(sys_path_dir2) + + # import pkg_implicit_namespace_package_test + interpreter = jedi.Interpreter( + "import pkg_implicit_namespace_package_test.", + namespaces=[locals()], + project=Project('.') + ) + comps = interpreter.complete() + expected = ["pkgA", "pkgB"] + assert [c.complete for c in comps] == expected + + @pytest.mark.parametrize( 'code, types', [ ('dct[1]', ['int']), From 383c596975008cf2fd9f8f38f7b62e96addc0104 Mon Sep 17 00:00:00 2001 From: Maximilian Albert Date: Sun, 19 Jan 2025 23:27:37 +0000 Subject: [PATCH 6/6] Fix crash (only convert __file__ attribute to a Path if it is not None) --- jedi/inference/compiled/access.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jedi/inference/compiled/access.py b/jedi/inference/compiled/access.py index 09ed1b64..fcad4887 100644 --- a/jedi/inference/compiled/access.py +++ b/jedi/inference/compiled/access.py @@ -183,10 +183,12 @@ class DirectObjectAccess: def py__file__(self) -> Optional[Path]: try: - return Path(self._obj.__file__) + __file__attribute = self._obj.__file__ except AttributeError: return None + return Path(__file__attribute) if __file__attribute is not None else None + def py__doc__(self): return inspect.getdoc(self._obj) or ''