Skip to content

Commit

Permalink
Avoid extra . in from .. import parent imports in Rust Python dep…
Browse files Browse the repository at this point in the history
… inference (Cherry-pick of #19175) (#19177)

This fixes #19173 by generalising the `from . import a` special case to
also handle `from .. import a` etc.: _any_ module path that ends with a
`.` doesn't need an extra `.` to separate the module path from the
name(s).

Before this fix, `from . import a` was special cased to avoid an extra
dot (becoming `.a` as desired), while `from .. import a` was not special
cased. It became `...a` (extra `.`), by joining the module path (`..`)
and the name (`a`) with the usual `.` separator. This separator is only
appropriate for normal names like `from x import a`.

Co-authored-by: Huon Wilson <huon@exoflare.io>
  • Loading branch information
WorkerPants and huonw authored May 28, 2023
1 parent 1abb154 commit 6d1ebab
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 5 deletions.
10 changes: 5 additions & 5 deletions src/rust/engine/dep_inference/src/python/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,11 @@ impl ImportCollector<'_> {
};
let full_name = match module_name {
Some(module_name) => {
let mut mod_text = self.code_at(module_name.range());
if mod_text == "." {
mod_text = "";
}
[mod_text, name_ref].join(".")
let mod_text = self.code_at(module_name.range());
// `from ... import a` => `...a` mod_text alone, but `from x import a` => `x.a` needs to
// insert a .
let joiner = if mod_text.ends_with('.') { "" } else { "." };
[mod_text, name_ref].join(joiner)
}
None => name_ref.to_string(),
};
Expand Down
7 changes: 7 additions & 0 deletions src/rust/engine/dep_inference/src/python/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ from a.b import (

assert_imports("from . import b", &[".b"]);
assert_imports("from .a import b", &[".a.b"]);
assert_imports("from .. import b", &["..b"]);
assert_imports("from ..a import b", &["..a.b"]);
assert_imports("from ..a import b.c", &["..a.b.c"]);
assert_imports("from ... import b.c", &["...b.c"]);
assert_imports("from ...a import b.c", &["...a.b.c"]);
assert_imports("from ....a import b.c", &["....a.b.c"]);
assert_imports("from ....a import b, c", &["....a.b", "....a.c"]);
Expand Down Expand Up @@ -488,17 +490,21 @@ fn relative_imports_resolution() {
let filename = "foo/bar/baz.py";
assert_relative_imports(filename, "from . import b", &["foo.bar.b"]);
assert_relative_imports(filename, "from .a import b", &["foo.bar.a.b"]);
assert_relative_imports(filename, "from .. import b", &["foo.b"]);
assert_relative_imports(filename, "from ..a import b", &["foo.a.b"]);
assert_relative_imports(filename, "from .. import b.c", &["foo.b.c"]);
assert_relative_imports(filename, "from ..a import b.c", &["foo.a.b.c"]);

let filename = "bingo/bango/bongo/himom.py";
assert_relative_imports(filename, "from . import b", &["bingo.bango.bongo.b"]);
assert_relative_imports(filename, "from .a import b", &["bingo.bango.bongo.a.b"]);
assert_relative_imports(filename, "from ..a import b", &["bingo.bango.a.b"]);
assert_relative_imports(filename, "from ..a import b.c", &["bingo.bango.a.b.c"]);
assert_relative_imports(filename, "from ... import b.c", &["bingo.b.c"]);
assert_relative_imports(filename, "from ...a import b.c", &["bingo.a.b.c"]);

// Left unchanged, since we blew through the top, let Pants error using this string as a message
assert_relative_imports(filename, "from .... import b.c", &["....b.c"]);
assert_relative_imports(filename, "from ....a import b.c", &["....a.b.c"]);
assert_relative_imports(filename, "from ....a import b, c", &["....a.b", "....a.c"]);
assert_relative_imports(
Expand All @@ -521,6 +527,7 @@ fn syntax_errors_and_other_fun() {
assert_imports("from a imp x", &[]);
assert_imports("from from import a as .as", &[]);
assert_imports("from a import ......g", &["a.g"]);
assert_imports("from a. import b", &[]);
assert_imports("try:...\nexcept:import a", &["a"]);
assert_imports("try:...\nexcept 1:import a", &["a"]);
assert_imports("try:...\nexcept x=1:import a", &["a"]);
Expand Down

0 comments on commit 6d1ebab

Please sign in to comment.