| :::{default-domain} bzl | 
 | ::: | 
 |  | 
 | # Circular dependencies | 
 |  | 
 | Sometimes PyPI packages contain dependency cycles. For instance, a particular | 
 | version of `sphinx` (this is no longer the case in the latest version as of | 
 | 2024-06-02) depends on `sphinxcontrib-serializinghtml`. When using them as | 
 | `requirement()`s, ala | 
 |  | 
 | ```starlark | 
 | py_binary( | 
 |     name = "doctool", | 
 |     ... | 
 |     deps = [ | 
 |         requirement("sphinx"), | 
 |     ], | 
 | ) | 
 | ``` | 
 |  | 
 | Bazel will protest because it doesn't support cycles in the build graph -- | 
 |  | 
 | ``` | 
 | ERROR: .../external/pypi_sphinxcontrib_serializinghtml/BUILD.bazel:44:6: in alias rule @pypi_sphinxcontrib_serializinghtml//:pkg: cycle in dependency graph: | 
 |     //:doctool (...) | 
 |     @pypi//sphinxcontrib_serializinghtml:pkg (...) | 
 | .-> @pypi_sphinxcontrib_serializinghtml//:pkg (...) | 
 | |   @pypi_sphinxcontrib_serializinghtml//:_pkg (...) | 
 | |   @pypi_sphinx//:pkg (...) | 
 | |   @pypi_sphinx//:_pkg (...) | 
 | `-- @pypi_sphinxcontrib_serializinghtml//:pkg (...) | 
 | ``` | 
 |  | 
 | The `experimental_requirement_cycles` attribute allows you to work around these | 
 | issues by specifying groups of packages which form cycles. `pip_parse` will | 
 | transparently fix the cycles for you and provide the cyclic dependencies | 
 | simultaneously. | 
 |  | 
 | ```starlark | 
 |     ... | 
 |     experimental_requirement_cycles = { | 
 |         "sphinx": [ | 
 |             "sphinx", | 
 |             "sphinxcontrib-serializinghtml", | 
 |         ] | 
 |     }, | 
 | ) | 
 | ``` | 
 |  | 
 | `pip_parse` supports fixing multiple cycles simultaneously, however, cycles must | 
 | be distinct. `apache-airflow`, for instance, has dependency cycles with a number | 
 | of its optional dependencies, which means those optional dependencies must all | 
 | be a part of the `airflow` cycle. For instance: | 
 |  | 
 | ```starlark | 
 |     ... | 
 |     experimental_requirement_cycles = { | 
 |         "airflow": [ | 
 |             "apache-airflow", | 
 |             "apache-airflow-providers-common-sql", | 
 |             "apache-airflow-providers-postgres", | 
 |             "apache-airflow-providers-sqlite", | 
 |         ] | 
 |     } | 
 | ) | 
 | ``` | 
 |  | 
 | Alternatively, one could resolve the cycle by removing one leg of it. | 
 |  | 
 | For example, while `apache-airflow-providers-sqlite` is "baked into" the Airflow | 
 | package, `apache-airflow-providers-postgres` is not and is an optional feature. | 
 | Rather than listing `apache-airflow[postgres]` in your `requirements.txt`, which | 
 | would expose a cycle via the extra, one could either _manually_ depend on | 
 | `apache-airflow` and `apache-airflow-providers-postgres` separately as | 
 | requirements. Bazel rules which need only `apache-airflow` can take it as a | 
 | dependency, and rules which explicitly want to mix in | 
 | `apache-airflow-providers-postgres` now can. | 
 |  | 
 | Alternatively, one could use `rules_python`'s patching features to remove one | 
 | leg of the dependency manually, for instance, by making | 
 | `apache-airflow-providers-postgres` not explicitly depend on `apache-airflow` or | 
 | perhaps `apache-airflow-providers-common-sql`. |