| 
 | 1 | +# How to use a common set of dependencies with multiple PyPI versions  | 
 | 2 | + | 
 | 3 | +In this guide, we show how to handle a situation common to monorepos  | 
 | 4 | +that extensively share code: How does a common library refer to the correct  | 
 | 5 | +`@pypi_<name>` hub when binaries may have their own requirements (and thus  | 
 | 6 | +PyPI hub name)? Stated as code, this situation:  | 
 | 7 | + | 
 | 8 | +```bzl  | 
 | 9 | + | 
 | 10 | +py_binary(  | 
 | 11 | +  name = "bin_alpha"  | 
 | 12 | +  deps = ["@pypi_alpha//requests", ":common"],  | 
 | 13 | +)  | 
 | 14 | +py_binary(  | 
 | 15 | +  name = "bin_alpha"  | 
 | 16 | +  deps = ["@pypi_beta//requests", ":common"],  | 
 | 17 | +)  | 
 | 18 | + | 
 | 19 | +py_library(  | 
 | 20 | +  name = "common",  | 
 | 21 | +  deps = ["@pypi_???//more_itertools"] # <-- Which @pypi repo?  | 
 | 22 | +)  | 
 | 23 | +```  | 
 | 24 | + | 
 | 25 | +## Using flags to pick a hub  | 
 | 26 | + | 
 | 27 | +The basic trick to make `:common` pick the appropriate `@pypi_<name>` is to use  | 
 | 28 | +`select()` to choose one based on build flags. To help this process, `py_binary`  | 
 | 29 | +et al allow forcing particular build flags to be used, and custom flags can be  | 
 | 30 | +registered to allow `py_binary` et al to set them.  | 
 | 31 | + | 
 | 32 | +In this example, we create a custom string flag named `//:pypi_hub`,  | 
 | 33 | +register it to allow using it with `py_binary` directly, then use `select()`  | 
 | 34 | +to pick different dependencies.  | 
 | 35 | + | 
 | 36 | +```  | 
 | 37 | +# File: MODULE.bazel  | 
 | 38 | +
  | 
 | 39 | +rules_python_config.add_transition_setting(  | 
 | 40 | +    setting = "@//pick:pypi_hub",  | 
 | 41 | +)  | 
 | 42 | +
  | 
 | 43 | +# File: BUILD.bazel  | 
 | 44 | +
  | 
 | 45 | +```bazel  | 
 | 46 | +
  | 
 | 47 | +load("@bazel_skylib//rules:common_settings.bzl", "string_flag")  | 
 | 48 | +
  | 
 | 49 | +string_flag(  | 
 | 50 | +    name = "pypi_hub",  | 
 | 51 | +)  | 
 | 52 | +
  | 
 | 53 | +config_setting(  | 
 | 54 | +    name = "is_pypi_alpha",  | 
 | 55 | +    flag_values = {"//:pypi_hub": "alpha"},  | 
 | 56 | +)  | 
 | 57 | +
  | 
 | 58 | +config_setting(  | 
 | 59 | +    name = "is_pypi_beta",  | 
 | 60 | +    flag_values = {"//:pypi_hub": "beta"}  | 
 | 61 | +)  | 
 | 62 | +
  | 
 | 63 | +py_binary(  | 
 | 64 | +    name = "bin_alpha",  | 
 | 65 | +    srcs = ["bin_alpha.py"],  | 
 | 66 | +    config_settings = {  | 
 | 67 | +        "//:pypi_hub": "alpha",  | 
 | 68 | +    },  | 
 | 69 | +    deps ["@pypi_alpha//requests", ":common"],  | 
 | 70 | +)  | 
 | 71 | +py_binary(  | 
 | 72 | +    name = "bin_beta",  | 
 | 73 | +    srcs = ["bin_beta.py"],  | 
 | 74 | +    config_settings = {  | 
 | 75 | +        "//:pypi_hub": "beta",  | 
 | 76 | +    },  | 
 | 77 | +    deps ["@pypi_beta//requests", ":common"],  | 
 | 78 | +)  | 
 | 79 | +py_library(  | 
 | 80 | +    name = "common",  | 
 | 81 | +    deps = select({  | 
 | 82 | +        ":is_pypi_alpha": ["@pypi_alpha//more_itertools"],  | 
 | 83 | +        ":is_pypi_beta": ["@pypi_beta//more_itertools"],  | 
 | 84 | +    }),  | 
 | 85 | +)  | 
 | 86 | +```  | 
 | 87 | + | 
 | 88 | +When `bin_alpha` and `bin_beta` are built, they will have the `pypi_hub`  | 
 | 89 | +flag force to their respective value. When `:common` is evaluated, it sees  | 
 | 90 | +the flag value of the binary that is consuming it, and the `select()` resolves  | 
 | 91 | +appropriately.  | 
0 commit comments