What's a nice approach for dealing with a monorepo...
# general
b
What's a nice approach for dealing with a monorepo with a few apps that depend on a shared library which is also part of the monorepo? Python for now.
e
What's your final distribution strategy? My particular case involves building a number of docker containers running python applications (copying pex files into docker images), so "shared library" just means "code organization strategy" (eg. separate directory), but at the end of the day, dependency inference will just pull whatever source files you need across your whole hierarchy of source files.
If "shared library" refers explictly to a versioned/published package that needs to be used in a number of applications, the answers will differ (and I won't be a great one to comment on that situation, unfortunately)
b
Um, for now the former really, not container images as the resulting artifact, but something similar..
f
What language is the shared library written in? That might point at what the desired treatment should be.
> Python for now. Is it just pure Python and no C extension?
Is it just internal source code and is not published as a wheel anywhere?
b
Just internal. Just python for now, it’s a theoretical library for the time being as we know there’s room to remove duplicate code, shouldn’t be any C extensions but not sure about any dependencies. Later some Go components which may benefit from reducing duplication but not prioritized now.
f
Okay really just first-party source code in the repository then. And as @elegant-florist-94385 answered above, "dependency inference will just pull whatever source files you need across your whole hierarchy of source files."
You shouldn't have to treat the shared code specially at this point.
(At least not from Pants' view, obviously any normal software engineering concerns of how to structure shared code remain.)
b
Right so I guess the question then becomes python/go specific how to handle imports of the shared library if the apps and the library have their own pyproject.toml’s/go.mod’s. Assuming they allow for that
e
a
pyproject.toml
file doesn't (directly) play into pants' dependency inference system. A few concepts to understand: •
python_requirement
target represents a single third party dependency. Usually you create these using
python_requirements
(for
requirements.txt
) or
poetry_requirements
(for
pyproject.toml
) target generators, which are just a macro that creates individual
python requirement
targets for each dependency in your file(s). • A
resolve
is essentially a "universe" of dependencies. In the default case, any time pants finds a
python_requirement
target, it understands that that dependency should belong in the universe, (ie. its part of your
resolve
) ◦ It doesn't matter where these requirements are found, they all get pulled into the same resolve. (so if there are multiple pyproject.toml files, they aren't actually separate things, as far as pants is concerned) ◦ A
resolve
must be consistent, in terms of compatible versions of dependencies. • When you try to use a python file (whether by
run
,
check
,
test
, building a
pex
, etc.) pants will assume it belongs in your resolve, and interpret imports accordingly. Typically, I organize my project like: • 3rdparty/python/pyproject.toml (contains all my dependencies used anywhere) • 3rdparty/python/my-lockfile.lock (the generated lockfile that contains the exact versions that were resolved, including transitive dependencies) • src/python/library, src/python/projectA, src/python/projectB, etc. (source code that is free to import anything from the 3rdparty dependencies) https://www.pantsbuild.org/prerelease/docs/python/overview/lockfiles has more good information on this. As a note: There are ways to have separate resolves for different projects. Generally, I would only recommend to do this if you need to have conflicting dependencies (eg. if Project A and Project B must use different versions of Django, or something like that.) (remember that its okay to have dependencies that are unused by some projects. the dependency inference will avoid pulling them in where they are not needed). If you do need a separate resolve for each project, you need to explicitly tell each
python_requirement
which resolve it must belong to, and then your source files will also specify which resolve they are compatible with. In the case of a shared library, you would use
parametrize
to indicate that it is supposed to be used with both Project A resolve and Project B resolve. (and then it will
lint
,
check
,
test
etc. against each resolve)