-
Notifications
You must be signed in to change notification settings - Fork 0
IN-1298 - Spike to replace pipenv with uv #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Why these changes are being introduced: uv is a modern python project and dependency manager with increasingly attractive features and community support. By contrast, pipenv is feeling a bit stale in terms of features, community support, and even performance. Additionally, without going into great detail here, uv is part of a larger ecocsystem of python tooling that work very well together, including uv, ruff, and ty (type checking). How this addresses that need: * Virtually anywhere pipenv was used, uv is now used * Makefile updated to use uv * Makefile installation recipes updated to utilize uv best * Dockerfile updated to align with uv installation approaches Side effects of this change: * Before this template code can be used by a project, Github actions will need to be updated to intelligently use pipenv or uv depending on the project as we incrementally convert them. Relevant ticket(s): * https://mitlibraries.atlassian.net/browse/IN-1298
RUN cd ${LAMBDA_TASK_ROOT} && \ | ||
uv export --format requirements-txt --no-hashes --no-dev > requirements.txt && \ | ||
uv pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}" --system |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note the pipenv
approach was using a --target
argument to install the libraries in a specific place.
For uv
, the equivalant is using uv pip
which provides a more pip-like API for specific tasks, in this case installing to a specific location instead of the active virtual environment.
I believe there are alternatives to how we could construct the python environment for AWS lambdas, but this approach is readily understandable and conceptually mirrors our previous approach.
Some flags:
--no-hashes
: excludes hashes from library versions where the version may be the same but the hash changes; which can wreak havoc with Docker layers--no-dev
: skips thedev
group of dependencies
install: .venv .git/hooks/pre-commit # Install Python dependencies and create virtual environment if not exists | ||
uv sync --dev | ||
|
||
.venv: # Creates virtual environment if not found | ||
@echo "Creating virtual environment at .venv..." | ||
uv venv .venv | ||
|
||
.git/hooks/pre-commit: # Sets up pre-commit hook if not setup | ||
@echo "Installing pre-commit hooks..." | ||
uv run pre-commit install | ||
|
||
venv: .venv # Create the Python virtual environment | ||
|
||
update: # Update Python dependencies | ||
uv lock --upgrade | ||
uv sync --dev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is 50/50 new functionality from uv
and some Makefile
maneuvers we could use.
When running make install
, while debatable, one approach is that it creates the virtual environment for you. I'm also drawn to a very explicit make venv
(which we actually still have here!) but this kind of combines both. If you run make install
and a .venv
directory doesn't exist, courtesy of line 18, it'll get created. This leans into the Makefile
"build" mentality with built-in checks for assets.
Similar story for pre-commit.
The net effect is that make install
creates a virtual env if it doesn't exist, but remains idempotent to re-run (won't clobber a pre-existing environment).
|
||
ruff: # Run 'ruff' linter and print a preview of errors | ||
pipenv run ruff check . | ||
uv run ruff check . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commenting here arbitraily: nice example of uv
being largely a pipenv
drop-in replacement if you want to have similar ergonomics.
dependencies = [ | ||
"sentry-sdk>=2.29.1", | ||
] | ||
|
||
[dependency-groups] | ||
dev = [ | ||
"black>=25.1.0", | ||
"coveralls>=4.0.1", | ||
"ipython>=9.2.0", | ||
"mypy>=1.15.0", | ||
"pip-audit>=2.9.0", | ||
"pre-commit>=4.2.0", | ||
"pytest>=8.3.5", | ||
"ruff>=0.11.11", | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dependencies are now managed in pyproject.toml
vs a Pipfile
. This is a very active area in the python ecosystem. uv
utilizes a uv.lock
file, and will likely continue to do so (for advanced usage purposes), but there is a new proposed pylock.toml
file via PEP-751 that may get used.
To me, another reason to move to uv
: more than any other project tooling, it's evolving with the community around new standards (in many cases driving it).
Purpose and background context
This PR updates the python AWS lambda template to use
uv
instead ofpipenv
.While this code and PR were intended as a demo and spike to facilitate internal discussions about
uv
, it may very well serve or act as the foundation for a real update to the lambda template.Comments in the code changes are included to point out particularly interesting
uv
things.NOTE: regarding failing Github actions, see this Jira comment
How can a reviewer manually see the effects of these changes?
It is advised to completely remove your old
python-lambda-template
project to avoid anypipenv
cross contamination. Or if you're feeling bold, before pulling down this branchpipenv --rm
can be used to remove thepipenv
virtual environment.Once the branch is checked out, a "normal" installation could be followed:
Some notes from the install:
.venv
virtual environment in the same directory.venv
virtual env and the pre-commit hooks are only installed/created if they don't existThen, can run some tests and linting:
make test make lint
The API for
uv
is quite similar topipenv
,poetry
, etc.To start an IPython shell:
A fun test - create a python file called
hello.py
:Then invoke it with
uv
:To get a sense for how fast
uv
can be -- and not just celebrating speed for speed's sake, but considering that quick installs and builds allow for more time thinking and coding -- you could recreate the virtual environment:And much more! Additional things to try with
uv
can be discussed async of this PR.Includes new or updated dependencies?
YES
Changes expectations for external applications?
YES: Before this template code can be used by a project, Github actions will need to be updated to intelligently use pipenv or uv depending on the project as we incrementally convert them.
What are the relevant tickets?
Developer
Code Reviewer(s)