> ## Documentation Index
> Fetch the complete documentation index at: https://aspect.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Using monorepo dependencies

> Wire Python monorepo dependencies in Bazel so first-party libraries are live at HEAD, scaffolding a new lib with copier and avoiding wheel publishing.

In a trunk-based (or “live at HEAD”) development model, you want changes to libraries in a monorepo to be immediately live in the application that depends on them.
There shouldn’t be a bumpversion, wheel publishing step, extra package registry, etc.

## Scaffold a library

This exercise uses a code generator to scaffold a new library into our repository.
Here’s an example repository that gives a minimal python library:
[https://github.com/alexeagle/aspect-template-python-lib](https://github.com/alexeagle/aspect-template-python-lib)

As the README of that repo says, it’s a copier template.
Thanks to `direnv`, we already have `copier` on the `PATH`, so you can stamp out a copy of the library into a new folder named `mylib` with this command:

```bash theme={null}
copier copy gh:alexeagle/aspect-template-python-lib mylib
```

And the library is now in the source tree:

<img src="https://mintcdn.com/aspectbuild/gtqBKXWWd-jWHweY/learning/bazel-102/mylib_content.png?fit=max&auto=format&n=gtqBKXWWd-jWHweY&q=85&s=2d655004a506632f90d7369e5794de47" alt="lib is copied" width="546" height="334" data-path="learning/bazel-102/mylib_content.png" />

Now we need to deal with the transitive dependencies.

First, it uses a new Bazel module (`jq.bzl`) so we can run a command to install it:

```shell theme={null}
buildozer 'new bazel_dep jq.bzl' //MODULE.bazel:all
buildozer 'set version 0.4.0' //MODULE.bazel:jq.bzl
```

It also happens that the new `mylib` depends on a library (`cowsay`).
This should be constraint-solved along with the rest of the monorepo, so that you’re certain there’s no
“[diamond dependency](https://en.wikipedia.org/wiki/Diamond_dependency)” version conflict when an application includes two different libraries.

So you need to add that to the monorepo requirements.
Add a line to the `requirements/all.in` file, with a `-r` line that points to the new requirements.txt file:

```bash theme={null}
echo "-r ../mylib/requirements.txt" >> requirements/all.in
```

Now Bazel wants to know the dependency graph, and the new file is a dependency of the `uv pip-compile` step. So you must update the `requirements/BUILD` file.
For this, rather than edit by hand, you can use the `buildozer` tool which is a machine-editor for BUILD files that can apply simple instructions.
It’s already on the `PATH` thanks to `direnv`.

```bash theme={null}
buildozer "add data //mylib:requirements" //requirements:requirements.all
```

Now repin the dependencies again with this change:

```python theme={null}
./tools/repin
```

You can see that it worked as this new dependency is now listed along with the others in the monorepo.

<img src="https://mintcdn.com/aspectbuild/gtqBKXWWd-jWHweY/learning/bazel-102/cowsay_pinned.png?fit=max&auto=format&n=gtqBKXWWd-jWHweY&q=85&s=8988b6427f64448b5961fe400ad7d0d0" alt="new_dep" width="1166" height="190" data-path="learning/bazel-102/cowsay_pinned.png" />

requirements/all.txt

<Info>
  This `all.txt` file is registered with the `pip.parse` extension in `/MODULE.bazel` which is how Bazel knows to install this library when needed.
</Info>

## Use the library from the app

Let’s go back to `__main__.py` and use this.
Start typing “from mylib” at the top of the file - your editor should give you assistance in completing the import statement to get the `say` function.
Then replace the `print` call with `say.marvin`:

```python theme={null}
import requests
from mylib import say

x = requests.get("https://httpbin.org/bytes/1")

say.marvin(x.text.encode().hex())

```

You have to update the dependency graph for Bazel, so run `aspect gazelle` again.

Now run the application again and see the library is working:

<img src="https://mintcdn.com/aspectbuild/gtqBKXWWd-jWHweY/learning/bazel-102/cow_from_dep.png?fit=max&auto=format&n=gtqBKXWWd-jWHweY&q=85&s=6080fa7bc5baa952c90ff4702d0897c9" alt="cow works" width="714" height="516" data-path="learning/bazel-102/cow_from_dep.png" />

## Swap out for a locally-built service

We'll run `copier` again to get a FastAPI service that serves our data.

```shell theme={null}
copier copy gh:alexeagle/aspect-template-python-service myservice
```

This time the template provides no pinned requirements or BUILD files.
That's okay, we do the same thing to add its requirements and generate the BUILD file.
This time you can do the exercise with less help!
