Repository: bazelbuild/buildtools
Pull request #691 (2019-08-05 20:37:43)

Add native-py fix to buildifier
This is pretty much a copy/paste of #671 for Python rules. It migrates for the
incompatible change `--incompatible_load_python_rules_from_bzl` (bazelbuild/bazel#9006).

brandjon: Missing from this automated migration is adding `@rules_python` to the WORKSPACE. Does/should buildifier help automate that? If not, we should probably update the warnings file to document this and link to the rules_python readme (same for java and cc).

Patch:
diff --git a/WARNINGS.md b/WARNINGS.md
index a07c13a..b01963e 100644
--- a/WARNINGS.md
+++ b/WARNINGS.md
@@ -34,6 +34,7 @@ Warning categories supported by buildifier's linter:
   * [native-java](#native-java)
   * [native-package](#native-package)
   * [native-proto](#native-proto)
+  * [native-py](#native-py)
   * [no-effect](#no-effect)
   * [out-of-order-load](#out-of-order-load)
   * [output-group](#output-group)
@@ -525,6 +526,17 @@ rules [will be disabled](https://github.com/bazelbuild/bazel/issues/8922).
 
 --------------------------------------------------------------------------------
 
+## <a name="native-py"></a>All Python build rules should be loaded from Starlark
+
+  * Category name: `native-py`
+  * Flag in Bazel: [`--incompatible_load_python_rules_from_bzl`](https://github.com/bazelbuild/bazel/issues/9006)
+  * Automatic fix: yes
+
+The Python build rules should be loaded from Starlark. The native rules [will be
+disabled](https://github.com/bazelbuild/bazel/issues/9006).
+
+--------------------------------------------------------------------------------
+
 ## <a name="no-effect"></a>Expression result is not used
 
   * Category name: `no-effect`
diff --git a/tables/tables.go b/tables/tables.go
index 9382843..05bda4c 100644
--- a/tables/tables.go
+++ b/tables/tables.go
@@ -258,6 +258,17 @@ var JavaNativeRules = []string{
 // JavaLoadPath is the load path for the Starlark Java Rules.
 var JavaLoadPath = "@rules_java//java:defs.bzl"
 
+// PyNativeRules lists all Python rules that are being migrated from Native to Starlark.
+var PyNativeRules = []string{
+	"py_library",
+	"py_binary",
+	"py_test",
+	"py_runtime",
+}
+
+// PyLoadPath is the load path for the Starlark Python Rules.
+var PyLoadPath = "@rules_python//python:defs.bzl"
+
 // ProtoNativeRules lists all Proto rules that are being migrated from Native to Starlark.
 var ProtoNativeRules = []string{
 	"proto_lang_toolchain",
diff --git a/warn/warn.go b/warn/warn.go
index c029bdc..bcb0f3e 100644
--- a/warn/warn.go
+++ b/warn/warn.go
@@ -132,6 +132,7 @@ var FileWarningMap = map[string]func(f *build.File) []*LinterFinding{
 	"native-java":               nativeJavaRulesWarning,
 	"native-package":            nativePackageWarning,
 	"native-proto":              nativeProtoRulesWarning,
+	"native-py":                 nativePyRulesWarning,
 	"no-effect":                 noEffectWarning,
 	"output-group":              outputGroupWarning,
 	"out-of-order-load":         outOfOrderLoadWarning,
diff --git a/warn/warn_bazel_api.go b/warn/warn_bazel_api.go
index b23d992..7694811 100644
--- a/warn/warn_bazel_api.go
+++ b/warn/warn_bazel_api.go
@@ -641,6 +641,13 @@ func nativeJavaRulesWarning(f *build.File) []*LinterFinding {
 	return notLoadedFunctionUsageCheck(f, tables.JavaNativeRules, tables.JavaLoadPath)
 }
 
+func nativePyRulesWarning(f *build.File) []*LinterFinding {
+	if f.Type != build.TypeBzl && f.Type != build.TypeBuild {
+		return nil
+	}
+	return notLoadedFunctionUsageCheck(f, tables.PyNativeRules, tables.PyLoadPath)
+}
+
 func nativeProtoRulesWarning(f *build.File) []*LinterFinding {
 	if f.Type != build.TypeBzl && f.Type != build.TypeBuild {
 		return nil


Test patch:
diff --git a/warn/warn_bazel_api_test.go b/warn/warn_bazel_api_test.go
index eab1190..bc77081 100644
--- a/warn/warn_bazel_api_test.go
+++ b/warn/warn_bazel_api_test.go
@@ -580,6 +580,40 @@ java_test()
 		scopeBzl|scopeBuild)
 }
 
+func TestNativePyWarning(t *testing.T) {
+  checkFindingsAndFix(t, "native-py", `
+"""My file"""
+
+def macro():
+    py_library()
+    py_binary()
+    native.py_test()
+    native.py_runtime()
+
+py_test()
+`, fmt.Sprintf(`
+"""My file"""
+
+load(%q, "py_binary", "py_library", "py_runtime", "py_test")
+
+def macro():
+    py_library()
+    py_binary()
+    py_test()
+    py_runtime()
+
+py_test()
+`, tables.PyLoadPath),
+    []string{
+      fmt.Sprintf(`:4: Function "py_library" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
+      fmt.Sprintf(`:5: Function "py_binary" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
+      fmt.Sprintf(`:6: Function "py_test" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
+      fmt.Sprintf(`:7: Function "py_runtime" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
+      fmt.Sprintf(`:9: Function "py_test" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
+    },
+    scopeBzl|scopeBuild)
+}
+
 func TestNativeProtoWarning(t *testing.T) {
 	checkFindingsAndFix(t, "native-proto", `
 """My file"""