<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nioan</title>
    <description>The latest articles on DEV Community by Nioan (@nioan).</description>
    <link>https://dev.to/nioan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2622827%2Fcb42e404-80a6-459b-ab22-9208d471cb44.jpg</url>
      <title>DEV Community: Nioan</title>
      <link>https://dev.to/nioan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nioan"/>
    <language>en</language>
    <item>
      <title>How to Use Unreleased Features in Bazel Rule Sets with git_override</title>
      <dc:creator>Nioan</dc:creator>
      <pubDate>Mon, 30 Dec 2024 12:43:06 +0000</pubDate>
      <link>https://dev.to/nioan/how-to-use-unreleased-features-in-bazel-rule-sets-with-gitoverride-4p3f</link>
      <guid>https://dev.to/nioan/how-to-use-unreleased-features-in-bazel-rule-sets-with-gitoverride-4p3f</guid>
      <description>&lt;p&gt;Sometimes, you’ll encounter a feature in a rule set that’s already been completed, but the new release isn’t available yet. It’s frustrating to see that shiny feature sitting unused in the repo, just out of reach. Thankfully, with &lt;code&gt;git_override&lt;/code&gt;, you can check out any commit hash you want and start using it without waiting for a new release.&lt;/p&gt;

&lt;p&gt;I recently faced this issue while wanting to use the unreleased &lt;a href="https://github.com/grpc/grpc/issues/32564" rel="noopener noreferrer"&gt;pyi file generation feature&lt;/a&gt; in the &lt;a href="https://registry.bazel.build/modules/rules_proto_grpc_python" rel="noopener noreferrer"&gt;rules_proto_grpc_python&lt;/a&gt; rule set. &lt;/p&gt;

&lt;p&gt;In this post I'll explain how to override Bazel modules in a slightly complex rule set repo, using this example.&lt;/p&gt;

&lt;p&gt;To use a specific commit hash for this rule set, you can add the following to your &lt;code&gt;MODULE.bazel&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;bazel_dep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rules_proto_grpc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5.0.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;git_override&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;module_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rules_proto_grpc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;remote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://github.com/rules-proto-grpc/rules_proto_grpc.git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;d17b5b16c8b12143c6f1b78dabd6bbc228e89b58&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;strip_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;modules/core&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;bazel_dep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rules_proto_grpc_python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5.0.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;git_override&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;module_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rules_proto_grpc_python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;remote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://github.com/rules-proto-grpc/rules_proto_grpc.git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;d17b5b16c8b12143c6f1b78dabd6bbc228e89b58&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;strip_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;modules/python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two main complications with this rule set:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Multiple rule set modules exist under the &lt;code&gt;modules/&lt;/code&gt; directory of the repo.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rules_proto_grpc_python&lt;/code&gt; depends on &lt;code&gt;rules_proto_grpc&lt;/code&gt;, which lives in the same repo.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Multiple Modules in the repo
&lt;/h3&gt;

&lt;p&gt;The first complication arises from the multiple modules under the &lt;code&gt;modules/&lt;/code&gt; directory. When using &lt;code&gt;git_override&lt;/code&gt;, Bazel needs to know where to find the appropriate &lt;code&gt;MODULE.bazel&lt;/code&gt; for the override. If the module names don’t match, it will throw an error. That means that if you don’t use the &lt;code&gt;strip_prefix&lt;/code&gt; attribute, Bazel will try to use the root &lt;a href="https://github.com/rules-proto-grpc/rules_proto_grpc/blob/d17b5b16c8b12143c6f1b78dabd6bbc228e89b58/MODULE.bazel" rel="noopener noreferrer"&gt;MODULE.bazel&lt;/a&gt; (which doesn’t have the same name), and you’ll encounter an error like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR: Error computing the main repository mapping: in module dependency 
chain &amp;lt;root&amp;gt; -&amp;gt; rules_proto_grpc_python@_: the MODULE.bazel file of 
rules_proto_grpc_python@_ declares a different name ()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The solution is to use the &lt;code&gt;strip_prefix&lt;/code&gt; parameter to define the root of the module. This works because, under the hood, Bazel is using the &lt;a href="https://bazel.build/rules/lib/repo/git#git_repository-strip_prefix" rel="noopener noreferrer"&gt;git_repository&lt;/a&gt; rule. A bit cryptic, but it’s how Bazel rolls :).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The in-repo dependency
&lt;/h3&gt;

&lt;p&gt;The second complication is that &lt;code&gt;rules_proto_grpc_python&lt;/code&gt; depends on &lt;code&gt;rules_proto_grpc&lt;/code&gt;, that lives in the same repo. They also both are released toghether and use the same version. Even though you don’t need to add this dependency when not using &lt;code&gt;git_override&lt;/code&gt;, you must do so in this case. If you omit it, Bazel will throw an error like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR: Error computing the main repository mapping: module not found
in registries: rules_proto_grpc@0.0.0.rpg.version.placeholder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens because the &lt;a href="https://github.com/rules-proto-grpc/rules_proto_grpc/blob/d17b5b16c8b12143c6f1b78dabd6bbc228e89b58/modules/python/MODULE.bazel" rel="noopener noreferrer"&gt;MODULE.bazel&lt;/a&gt; for the Python ruleset contains a reference like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bazel_dep(name = "rules_proto_grpc", version = "0.0.0.rpg.version.placeholder")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The override registers &lt;code&gt;rules_proto_grpc&lt;/code&gt; with the placeholder version, allowing the dependency to resolve correctly.&lt;/p&gt;

</description>
      <category>bazel</category>
      <category>protocolbuff</category>
      <category>monorepo</category>
    </item>
    <item>
      <title>Resolving Python Import Failures in Bazel with `proto_library` Targets</title>
      <dc:creator>Nioan</dc:creator>
      <pubDate>Fri, 27 Dec 2024 20:22:06 +0000</pubDate>
      <link>https://dev.to/nioan/resolving-python-import-failures-in-bazel-with-protolibrary-targets-4i8i</link>
      <guid>https://dev.to/nioan/resolving-python-import-failures-in-bazel-with-protolibrary-targets-4i8i</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If Python imports fail when a package depends on multiple &lt;code&gt;proto_library&lt;/code&gt; targets, it's because Bazel generates non-namespace packages by default. &lt;/p&gt;

&lt;p&gt;Add the following flag to your &lt;code&gt;.bazelrc&lt;/code&gt; file to resolve this issue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build --incompatible_default_to_explicit_init_py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At some point in the future it &lt;a href="https://github.com/bazelbuild/bazel/issues/10076" rel="noopener noreferrer"&gt;might be enabled by default&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Problem Overview
&lt;/h3&gt;

&lt;p&gt;While working with Bazel to build Python code from Protocol Buffers, I encountered a perplexing runtime error:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Importing the first package in &lt;code&gt;PYTHONPATH&lt;/code&gt; works, but subsequent imports from other &lt;code&gt;proto_library&lt;/code&gt; targets fail.&lt;/li&gt;
&lt;li&gt;Reversing the dependency order changes which package is successfully imported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This issue arises because Bazel-generated Python packages for Protocol Buffers are &lt;strong&gt;not namespace packages&lt;/strong&gt; by default. When two packages share the same top-level path (e.g., &lt;code&gt;proto.common&lt;/code&gt;), Python loads only the first one it encounters, masking the others.&lt;/p&gt;




&lt;h3&gt;
  
  
  Environment and Setup
&lt;/h3&gt;

&lt;p&gt;We're using Bazel with &lt;code&gt;bzlmod&lt;/code&gt; in our (&lt;a href="//auxillis.ai"&gt;auxillis.ai&lt;/a&gt;) monorepo, which has the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;proto/
   common/
      some_lib/
         some_lib.proto
         BUILD.bazel
   service/
       some_service/
            some_service.proto
            BUILD.bazel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our&lt;code&gt;MODULE.bazel&lt;/code&gt; file includes dependencies for Python and Protocol Buffers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Protobuf
bazel_dep(name = "protobuf", version = "27.3", repo_name = "com_google_protobuf")
bazel_dep(name = "rules_proto", version = "6.0.2")
bazel_dep(name = "rules_proto_grpc_python", version = "5.0.0")

# Python
PYTHON_VERSION = "3.12.4"
bazel_dep(name = "rules_python", version = "0.35.0")
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.toolchain(python_version = PYTHON_VERSION, is_default = True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reproducing the Issue
&lt;/h3&gt;

&lt;p&gt;The following example shows how the issue manifests. If you run the main.py with bazel run, the imports would fail.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;BUILD.bazel&lt;/code&gt; for &lt;code&gt;common/some_lib&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;proto_library(
    name = "auxillis_ai_common_some_lib_proto",
    srcs = ["some_lib.proto"],
    visibility = ["//visibility:public"],
    deps = ["@com_google_protobuf//:struct_proto"],
)

python_proto_library(
    name = "py",
    protos = [":auxillis_ai_common_some_lib_proto"],
    visibility = ["//visibility:public"],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;BUILD.bazel&lt;/code&gt; for &lt;code&gt;service/some_service&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;proto_library(
    name = "auxillis_ai_service_some_service_proto",
    srcs = ["some_service.proto"],
    visibility = ["//visibility:public"],
    deps = [
        "//proto/common/some_lib:auxillis_ai_common_some_lib_proto",
        "@com_google_protobuf//:any_proto",
    ],
)

python_grpc_library(
    name = "py",
    protos = [":auxillis_ai_service_some_service_proto"],
    visibility = ["//visibility:public"],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Python Script (&lt;code&gt;main.py&lt;/code&gt;)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;python_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;python_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;python_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;common_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commonprefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;python_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Common prefix: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;common_prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;python_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;common_prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-------------------&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;proto.common.some_lib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;some_lib_pb2&lt;/span&gt;
        &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;proto.service.some_service&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;some_service_pb_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;some_service_pb_2_grpc&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_lib_pb2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_service_pb_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_service_pb_2_grpc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ImportError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; 

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;BUILD.bazel&lt;/code&gt; for &lt;code&gt;main.py&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;py_binary(
    name = "main",
    srcs = ["main.py"],
    deps = [
        "//proto/common/some_lib:py",
        "//proto/service/some_service:py",
        "@pip//grpcio",
    ],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;Inspecting the &lt;code&gt;PYTHONPATH&lt;/code&gt; environment variable reveals that Bazel adds generated Python packages to &lt;code&gt;PYTHONPATH&lt;/code&gt; in the order specified in the &lt;code&gt;deps&lt;/code&gt; argument. However:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Each &lt;code&gt;proto_library&lt;/code&gt; generates a directory with an &lt;code&gt;__init__.py&lt;/code&gt; file, making it a regular Python package.&lt;/li&gt;
&lt;li&gt;When Python loads a package (e.g., &lt;code&gt;proto.common.some_lib&lt;/code&gt;), any other packages sharing the same namespace are masked.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;To fix this, you need to configure Bazel to generate &lt;strong&gt;namespace packages&lt;/strong&gt;. Add the following to your &lt;code&gt;.bazelrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build --incompatible_default_to_explicit_init_py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures Bazel creates namespace packages, allowing multiple directories to contribute to the same Python package hierarchy. After adding the flag, all imports work as expected.&lt;/p&gt;




&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Bazel’s default behavior for Python Protocol Buffer packages can lead to runtime import issues when dependencies overlap.&lt;/li&gt;
&lt;li&gt;Adding &lt;code&gt;--incompatible_default_to_explicit_init_py&lt;/code&gt; makes Bazel generate namespace packages, resolving the issue.&lt;/li&gt;
&lt;li&gt;Use flag if your monorepo has shared Protocol Buffer dependencies.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
