Skip to content
This repository has been archived by the owner on Feb 17, 2023. It is now read-only.

Commit

Permalink
Allow relative imports when entire prefix is stripped.
Browse files Browse the repository at this point in the history
When running under Python 3, PEP 0328 formalized `import package` as an
absolute import. This PEP introduced a new syntax, `import .package` as
a relative import (of a "sub" package). Finally, the syntax
`from . import bar` was made to import a "peer" package.

Python gRPC code generated by the gRPC compiler uses the gRPC package name
as the absolute import, which works great if you own that particular namespace,
and can afford to allocate that namespace to that protobuf globally, or are running
under the (now EOL) Python 2.

There are some existing reports of this problem on GitHub and elsewhere
on the internet such as
protocolbuffers/protobuf#881
https://www.bountysource.com/issues/27402421-python-generated-code-import-paths
https://stackoverflow.com/questions/57213543/grpc-generated-python-script-fails-to-find-a-local-modul
e-in-the-same-directory
that outline this issue, and tend to be
closed WONTFIX or people work around it by sed'ing the output protobuf files.

This change allows the use of the prefixes (and a previously broken codepath)
to work around this bug by doing something that semantically feels right-ish.

The gRPC Python plugin accepts arguments to strip prefixes via the
`--grpc_python_out` flag. For example:

    --grpc_python_out=grpc_2_0,mycorp.:.

will cause the generated imports to become:

    `from myservice.v1 import baz`

rather than

    `from mycorp.myservice.v1 import baz`

Now, when when this is taken to the extreme, and the *entire* prefix except
for the final dot is stripped -- for instance:

    --grpc_python_out=grpc_2_0,mycorp.myservice.v1:.

THe existing gRPC plugin will generate the (buggy) output of:

    `from  import baz`

This patch changes the behavior of that (buggy) output to become:
  • Loading branch information
paultag committed Feb 13, 2020
1 parent a28d67f commit c493134
Showing 1 changed file with 8 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/compiler/python_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,14 @@ bool PrivateGenerator::PrintPreamble(grpc_generator::Printer* out) {
if (last_dot_pos == grpc::string::npos) {
var["ImportStatement"] = "import " + module_name;
} else {
var["ImportStatement"] = "from " + module_name.substr(0, last_dot_pos) +
" import " +
auto import_module = module_name.substr(0, last_dot_pos);
if (import_module.size() == 0) {
// If `strip_prefixes` is set, and the entire prefix is stripped
// up to (but not including!) the dot, we'll leave the dot as
// written, which will turn this import into a relaitive import.
import_module = ".";
}
var["ImportStatement"] = "from " + import_module + " import " +
module_name.substr(last_dot_pos + 1);
}
out->Print(var, "$ImportStatement$ as $ModuleAlias$\n");
Expand Down

0 comments on commit c493134

Please sign in to comment.