Skip to content

Commit 04e2f32

Browse files
authored
feat(gazelle): Update resolve.go to provide more human-friendly error output (#2120)
Update the Resolver error messages in resolve.go to be easier to read. While enabling gazelle in an existing repo, I found it somewhat difficult to skim the error messages. This PR: 1. Adds a bit of whitespace to spread different pieces of information out 2. Provides an additional remediation action for ambiguous import resolution 3. Moves the filename and line number where the error is to the front of the line. 4. Provides more concrete "gazelle:resolve py" directive examples for each errored dep resolution. Additionally, update a testcase to showcase the ambiguous import resolution error case. See the `test.yaml` file diff for an example of the old vs new error output.
1 parent bdcf53a commit 04e2f32

File tree

6 files changed

+39
-12
lines changed

6 files changed

+39
-12
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ A brief description of the categories of changes:
2525
[x.x.x]: https://github.com/bazelbuild/rules_python/releases/tag/x.x.x
2626

2727
### Changed
28-
* Nothing yet
28+
* (gazelle): Update error messages when unable to resolve a dependency to be more human-friendly.
2929

3030
### Fixed
3131
* (gazelle): Fix incorrect use of `t.Fatal`/`t.Fatalf` in tests.

gazelle/python/resolve.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,11 @@ func (py *Resolver) Resolve(
206206
continue MODULES_LOOP
207207
} else if cfg.ValidateImportStatements() {
208208
err := fmt.Errorf(
209-
"%[1]q at line %[2]d from %[3]q is an invalid dependency: possible solutions:\n"+
209+
"%[1]q, line %[2]d: %[3]q is an invalid dependency: possible solutions:\n"+
210210
"\t1. Add it as a dependency in the requirements.txt file.\n"+
211-
"\t2. Instruct Gazelle to resolve to a known dependency using the gazelle:resolve directive.\n"+
212-
"\t3. Ignore it with a comment '# gazelle:ignore %[1]s' in the Python file.\n",
213-
moduleName, mod.LineNumber, mod.Filepath,
211+
"\t2. Use the '# gazelle:resolve py %[3]s TARGET_LABEL' BUILD file directive to resolve to a known dependency.\n"+
212+
"\t3. Ignore it with a comment '# gazelle:ignore %[3]s' in the Python file.\n",
213+
mod.Filepath, mod.LineNumber, moduleName,
214214
)
215215
errs = append(errs, err)
216216
continue POSSIBLE_MODULE_LOOP
@@ -236,9 +236,10 @@ func (py *Resolver) Resolve(
236236
}
237237
if len(sameRootMatches) != 1 {
238238
err := fmt.Errorf(
239-
"multiple targets (%s) may be imported with %q at line %d in %q "+
240-
"- this must be fixed using the \"gazelle:resolve\" directive",
241-
targetListFromResults(filteredMatches), moduleName, mod.LineNumber, mod.Filepath)
239+
"%[1]q, line %[2]d: multiple targets (%[3]s) may be imported with %[4]q: possible solutions:\n"+
240+
"\t1. Disambiguate the above multiple targets by removing duplicate srcs entries.\n"+
241+
"\t2. Use the '# gazelle:resolve py %[4]s TARGET_LABEL' BUILD file directive to resolve to one of the above targets.\n",
242+
mod.Filepath, mod.LineNumber, targetListFromResults(filteredMatches), moduleName)
242243
errs = append(errs, err)
243244
continue POSSIBLE_MODULE_LOOP
244245
}
@@ -263,7 +264,7 @@ func (py *Resolver) Resolve(
263264
for _, err := range errs {
264265
joinedErrs = fmt.Sprintf("%s%s\n", joinedErrs, err)
265266
}
266-
log.Printf("ERROR: failed to validate dependencies for target %q: %v\n", from.String(), joinedErrs)
267+
log.Printf("ERROR: failed to validate dependencies for target %q:\n\n%v", from.String(), joinedErrs)
267268
hasFatalError = true
268269
}
269270
}

gazelle/python/testdata/invalid_imported_module/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import foo.bar
16+
1517
try:
1618
import grpc
1719

1820
grpc_available = True
1921
except ImportError:
2022
grpc_available = False
2123

22-
_ = grpc
24+
_ = bar(grpc)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
load("@rules_python//python:defs.bzl", "py_library")
2+
3+
py_library(
4+
name = "bar_1",
5+
srcs = ["bar.py"],
6+
)
7+
8+
py_library(
9+
name = "bar_2",
10+
srcs = ["bar.py"],
11+
)

gazelle/python/testdata/invalid_imported_module/foo/bar.py

Whitespace-only changes.

gazelle/python/testdata/invalid_imported_module/test.yaml

+15-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,20 @@
1616
expect:
1717
exit_code: 1
1818
stderr: |
19-
gazelle: ERROR: failed to validate dependencies for target "//:invalid_imported_module": "grpc" at line 16 from "__init__.py" is an invalid dependency: possible solutions:
19+
gazelle: ERROR: failed to validate dependencies for target "//:invalid_imported_module":
20+
21+
"__init__.py", line 15: multiple targets (//foo:bar_1, //foo:bar_2) may be imported with "foo.bar": possible solutions:
22+
1. Disambiguate the above multiple targets by removing duplicate srcs entries.
23+
2. Use the '# gazelle:resolve py foo.bar TARGET_LABEL' BUILD file directive to resolve to one of the above targets.
24+
25+
"__init__.py", line 15: "foo" is an invalid dependency: possible solutions:
26+
1. Add it as a dependency in the requirements.txt file.
27+
2. Use the '# gazelle:resolve py foo TARGET_LABEL' BUILD file directive to resolve to a known dependency.
28+
3. Ignore it with a comment '# gazelle:ignore foo' in the Python file.
29+
30+
gazelle: ERROR: failed to validate dependencies for target "//:invalid_imported_module":
31+
32+
"__init__.py", line 18: "grpc" is an invalid dependency: possible solutions:
2033
1. Add it as a dependency in the requirements.txt file.
21-
2. Instruct Gazelle to resolve to a known dependency using the gazelle:resolve directive.
34+
2. Use the '# gazelle:resolve py grpc TARGET_LABEL' BUILD file directive to resolve to a known dependency.
2235
3. Ignore it with a comment '# gazelle:ignore grpc' in the Python file.

0 commit comments

Comments
 (0)