|
| 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_beta", |
| 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 | +```bzl |
| 37 | +# File: MODULE.bazel |
| 38 | + |
| 39 | +rules_python_config.add_transition_setting( |
| 40 | + setting = "//:pypi_hub", |
| 41 | +) |
| 42 | + |
| 43 | +# File: BUILD.bazel |
| 44 | + |
| 45 | +```bzl |
| 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