py_proto_library uses workspace and pkg paths

All python imports currently are added to the runfiles under __main__
which is only the default when no workspace name is provided. This
change supports both empty workspace names, and specified workspace
names.

This also supports python libs not anchored at root
pull/22800/head
Matt Wilson 5 years ago
parent 65451fe93c
commit 594e1f6a64
  1. 4
      bazel/python_rules.bzl
  2. 2
      bazel/test/python_test_repo/BUILD
  3. 3
      bazel/test/python_test_repo/WORKSPACE
  4. 149
      bazel/test/python_test_repo/namespaced/upper/example/BUILD
  5. 21
      bazel/test/python_test_repo/namespaced/upper/example/import_no_strip_test.py
  6. 21
      bazel/test/python_test_repo/namespaced/upper/example/import_strip_test.py
  7. 17
      bazel/test/python_test_repo/namespaced/upper/example/namespace_test.py
  8. 27
      bazel/test/python_test_repo/namespaced/upper/example/namespaced_dependency.proto
  9. 38
      bazel/test/python_test_repo/namespaced/upper/example/namespaced_example.proto
  10. 21
      bazel/test/python_test_repo/namespaced/upper/example/no_import_no_strip_test.py
  11. 21
      bazel/test/python_test_repo/namespaced/upper/example/no_import_strip_test.py

@ -53,7 +53,7 @@ def _generate_py_impl(context):
imports = []
if out_dir.import_path:
imports.append("__main__/%s" % out_dir.import_path)
imports.append("%s/%s/%s" % (context.workspace_name, context.label.package, out_dir.import_path))
return [
DefaultInfo(files = depset(direct = out_files)),
@ -166,6 +166,8 @@ def _generate_pb2_grpc_src_impl(context):
imports = []
if out_dir.import_path:
#TODO: I believe this can be deleted, the rule requires a py_proto_library, and that rule will
# properly update imports.
imports.append("__main__/%s" % out_dir.import_path)
return [

@ -69,6 +69,8 @@ py2and3_test(
# Test compatibility of py_proto_library and py_grpc_library rules with
# proto_library targets as deps when the latter use import_prefix and/or
# strip_import_prefix arguments
#
# See namespaced/upper/example for more encompassing tests.
proto_library(
name = "helloworld_moved_proto",
srcs = ["helloworld.proto"],

@ -3,6 +3,9 @@ local_repository(
path = "../../..",
)
# Ensure rules don't rely on __main__ naming convention.
workspace(name = "python_test_repo")
load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
grpc_deps()

@ -0,0 +1,149 @@
load("@rules_proto//proto:defs.bzl", "proto_library")
load(
"@com_github_grpc_grpc//bazel:python_rules.bzl",
"py2and3_test",
"py_grpc_library",
"py_proto_library",
)
_IMPORT_PREFIX = "foo/bar"
_STRIP_PREFIX = "/%s" % package_name()
proto_library(
name = "import_no_strip_proto",
srcs = ["namespaced_example.proto"],
import_prefix = _IMPORT_PREFIX,
strip_import_prefix = None,
)
proto_library(
name = "import_strip_proto",
srcs = ["namespaced_example.proto"],
import_prefix = _IMPORT_PREFIX,
strip_import_prefix = _STRIP_PREFIX,
)
proto_library(
name = "no_import_no_strip_proto",
srcs = ["namespaced_example.proto"],
import_prefix = None,
strip_import_prefix = None,
)
proto_library(
name = "no_import_strip_proto",
srcs = ["namespaced_example.proto"],
import_prefix = None,
strip_import_prefix = _STRIP_PREFIX,
)
py_proto_library(
name = "import_no_strip_py_pb2",
deps = ["import_no_strip_proto"],
)
py_grpc_library(
name = "import_no_strip_py_pb2_grpc",
srcs = ["import_no_strip_proto"],
deps = ["import_no_strip_py_pb2"],
)
py_proto_library(
name = "import_strip_py_pb2",
deps = ["import_strip_proto"],
)
py_grpc_library(
name = "import_strip_py_pb2_grpc",
srcs = ["import_strip_proto"],
deps = ["import_strip_py_pb2"],
)
py_proto_library(
name = "no_import_no_strip_py_pb2",
deps = ["no_import_no_strip_proto"],
)
py_grpc_library(
name = "no_import_no_strip_py_pb2_grpc",
srcs = ["no_import_no_strip_proto"],
deps = ["no_import_no_strip_py_pb2"],
)
py_proto_library(
name = "no_import_strip_py_pb2",
deps = ["no_import_strip_proto"],
)
py_grpc_library(
name = "no_import_strip_py_pb2_grpc",
srcs = ["no_import_strip_proto"],
deps = ["no_import_strip_py_pb2"],
)
#################
# Namespace Tests
#################
# Most examples with protos have all proto packages rooted at the workspace root. i.e. google/api has
# a directory structure:
# - WORKSPACE
# - /google
# - /api
# - files.proto
#
# But if you can't anchor the protos at the root, you have to use strip and import prefixes. This results
# in the following directory layout for python, which needs to properly be added to the imports.
#
# No Import or Strip (Can't compile if there are any proto dependencies)
# bazel-out/darwin-fastbuild/bin/namespaced/upper/example/namespaced_example_pb2.py
#
# No import Prefix (Can't compile if there are any proto dependencies)
# bazel-out/darwin-fastbuild/bin/namespaced/upper/example/_virtual_imports/namespaced_example_proto/namespaced_example_pb2.py
#
# No strip prefix (Can't compile if there are any proto dependencies)
# bazel-out/darwin-fastbuild/bin/namespaced/upper/example/_virtual_imports/namespaced_example_proto/upper/example/namespaced/upper/example/namespaced_example_pb2.py
#
# Both Import and Strip
# bazel-out/darwin-fastbuild/bin/namespaced/upper/example/_virtual_imports/namespaced_example_proto/upper/example/namespaced_example_pb2.py
py2and3_test(
"import_no_strip_test",
srcs = ["import_no_strip_test.py"],
main = "import_no_strip_test.py",
deps = [
":import_no_strip_py_pb2",
":import_no_strip_py_pb2_grpc",
],
)
py2and3_test(
"import_strip_test",
srcs = ["import_strip_test.py"],
main = "import_strip_test.py",
deps = [
":import_strip_py_pb2",
":import_strip_py_pb2_grpc",
],
)
py2and3_test(
"no_import_no_strip_test",
srcs = ["no_import_no_strip_test.py"],
main = "no_import_no_strip_test.py",
deps = [
":no_import_no_strip_py_pb2",
":no_import_no_strip_py_pb2_grpc",
],
)
py2and3_test(
"no_import_strip_test",
srcs = ["no_import_strip_test.py"],
main = "no_import_strip_test.py",
deps = [
":no_import_strip_py_pb2",
":no_import_strip_py_pb2_grpc",
],
)

@ -0,0 +1,21 @@
import logging
import unittest
class ImportTest(unittest.TestCase):
def test_import(self):
from foo.bar.namespaced.upper.example.namespaced_example_pb2 import NamespacedExample
namespaced_example = NamespacedExample()
namespaced_example.value = "hello"
# Dummy assert, important part is namespaced example was imported.
self.assertEqual(namespaced_example.value, "hello")
def test_grpc(self):
from foo.bar.namespaced.upper.example.namespaced_example_pb2_grpc import NamespacedServiceStub
# No error from import
self.assertEqual(1, 1)
if __name__ == '__main__':
logging.basicConfig()
unittest.main()

@ -0,0 +1,21 @@
import logging
import unittest
class ImportTest(unittest.TestCase):
def test_import(self):
from foo.bar.namespaced_example_pb2 import NamespacedExample
namespaced_example = NamespacedExample()
namespaced_example.value = "hello"
# Dummy assert, important part is namespaced example was imported.
self.assertEqual(namespaced_example.value, "hello")
def test_grpc(self):
from foo.bar.namespaced_example_pb2_grpc import NamespacedServiceStub
# No error from import
self.assertEqual(1, 1)
if __name__ == '__main__':
logging.basicConfig()
unittest.main()

@ -0,0 +1,17 @@
import logging
import unittest
import NamespacedExample
class ImportTest(unittest.TestCase):
def test_import(self):
namespaced_example = NamespacedExample()
namespaced_example.value = "hello"
# Dummy assert, important part is namespaced example was imported.
self.assertEqual(namespaced_example.value, "hello")
if __name__ == '__main__':
logging.basicConfig()
unittest.main()

@ -0,0 +1,27 @@
// Copyright 2020 The gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.namespaced";
option java_outer_classname = "NamespacedDependencyProtos";
option objc_class_prefix = "NEP";
package upper.example;
message NamespacedDependency {
int32 value = 1;
}

@ -0,0 +1,38 @@
// Copyright 2020 The gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.namespaced";
option java_outer_classname = "NamespacedExampleProtos";
option objc_class_prefix = "NEP";
package upper.example;
// TODO: dependencies are still broken
// Need to do something like this: https://packaging.python.org/guides/packaging-namespace-packages/
// import "upper/example/namespaced_dependency.proto";
message NamespacedExample {
string value = 1;
// TODO: dependencies are still broken
// NamespacedDependency dependency = 2;
}
service NamespacedService {
rpc SayHello (NamespacedExample) returns (NamespacedExample) {}
}

@ -0,0 +1,21 @@
import logging
import unittest
class ImportTest(unittest.TestCase):
def test_import(self):
from namespaced.upper.example.namespaced_example_pb2 import NamespacedExample
namespaced_example = NamespacedExample()
namespaced_example.value = "hello"
# Dummy assert, important part is namespaced example was imported.
self.assertEqual(namespaced_example.value, "hello")
def test_grpc(self):
from namespaced.upper.example.namespaced_example_pb2_grpc import NamespacedServiceStub
# No error from import
self.assertEqual(1, 1)
if __name__ == '__main__':
logging.basicConfig()
unittest.main()

@ -0,0 +1,21 @@
import logging
import unittest
class ImportTest(unittest.TestCase):
def test_import(self):
from namespaced_example_pb2 import NamespacedExample
namespaced_example = NamespacedExample()
namespaced_example.value = "hello"
# Dummy assert, important part is namespaced example was imported.
self.assertEqual(namespaced_example.value, "hello")
def test_grpc(self):
from namespaced_example_pb2_grpc import NamespacedServiceStub
# No error from import
self.assertEqual(1, 1)
if __name__ == '__main__':
logging.basicConfig()
unittest.main()
Loading…
Cancel
Save