Skip to content

Commit 49f21d2

Browse files
blarghmateyCopilotampcode-com
authored
chore: migrate from poetry/pip to uv for dependency management (#3327)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Amp <amp@ampcode.com>
1 parent baa9309 commit 49f21d2

12 files changed

Lines changed: 3911 additions & 6571 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,16 @@ jobs:
3434
- name: Apt install
3535
run: cat Aptfile | sudo xargs apt-get install
3636

37-
- name: Set up Python
38-
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
37+
- name: Install uv
38+
uses: astral-sh/setup-uv@v7
3939
with:
40-
python-version: "3.11"
40+
enable-cache: true
4141

42-
- name: Install poetry
43-
uses: snok/install-poetry@v1
44-
with:
45-
version: 2.1.3
46-
virtualenvs-create: true
47-
virtualenvs-in-project: true
42+
- name: Install Python
43+
run: uv python install 3.11
4844

4945
- name: Install dependencies
50-
run: poetry install --no-interaction
46+
run: uv sync --locked --no-group prod
5147

5248
- name: Create test local state
5349
run: ./scripts/test/stub-data.sh
@@ -69,7 +65,7 @@ jobs:
6965
OPENEDX_API_CLIENT_SECRET: fake_client_secret # pragma: allowlist secret
7066

7167
- name: Django system checks
72-
run: poetry run ./manage.py check --fail-level WARNING
68+
run: uv run ./manage.py check --fail-level WARNING
7369
env:
7470
CELERY_TASK_ALWAYS_EAGER: 'True'
7571
CELERY_BROKER_URL: redis://localhost:6379/4

AGENTS.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,25 @@ MITx Online is a Django-based web platform for managing MIT online courses and p
2121
**Run tests:**
2222
```bash
2323
# Full test suite with parallel execution
24-
poetry run pytest -n logical
24+
uv run pytest -n logical
2525

2626
# Single test file
27-
poetry run pytest courses/api_test.py
27+
uv run pytest courses/api_test.py
2828

2929
# Single test function
30-
poetry run pytest courses/api_test.py::test_function_name
30+
uv run pytest courses/api_test.py::test_function_name
3131

3232
# With coverage
33-
poetry run pytest --cov . --cov-report html
33+
uv run pytest --cov . --cov-report html
3434
```
3535

3636
**Linting and formatting:**
3737
```bash
3838
# Format code (ruff)
39-
poetry run ruff format .
39+
uv run ruff format .
4040

4141
# Lint with auto-fix
42-
poetry run ruff check --fix .
42+
uv run ruff check --fix .
4343

4444
# Pre-commit hooks (runs all checks)
4545
pre-commit run --all-files
@@ -199,7 +199,7 @@ course = CourseFactory.create()
199199

200200
**Always check for missing migrations before committing:**
201201
```bash
202-
poetry run python manage.py makemigrations --check --dry-run
202+
uv run python manage.py makemigrations --check --dry-run
203203
```
204204

205205
Test suite includes checks for:
@@ -250,9 +250,9 @@ These provide standard patterns used across MIT ODL projects.
250250

251251
### Dependency Management
252252

253-
**Python:** Use Poetry for dependency management:
253+
**Python:** Use uv for dependency management:
254254
```bash
255-
docker compose run --rm web poetry add <package>
255+
docker compose run --rm web uv add <package>
256256
docker compose build web celery # Rebuild images after changes
257257
```
258258

@@ -298,16 +298,16 @@ Optional OIDC authentication via Keycloak:
298298
The test suite uses `pytest-django` with parallel execution via `pytest-xdist`:
299299
```bash
300300
# Single test module
301-
poetry run pytest courses/models_test.py
301+
uv run pytest courses/models_test.py
302302

303303
# Single test class
304-
poetry run pytest courses/models_test.py::TestCourse
304+
uv run pytest courses/models_test.py::TestCourse
305305

306306
# Single test method
307-
poetry run pytest courses/models_test.py::TestCourse::test_course_creation
307+
uv run pytest courses/models_test.py::TestCourse::test_course_creation
308308

309309
# With debugging (disables parallel execution)
310-
poetry run pytest -n0 -s courses/models_test.py::test_function
310+
uv run pytest -n0 -s courses/models_test.py::test_function
311311
```
312312

313313
### Common Management Commands
@@ -331,7 +331,7 @@ manage.py collectstatic # Collect static files
331331
Generate and view API schema:
332332
```bash
333333
# Generate schema
334-
poetry run python manage.py spectacular --file schema.yml
334+
uv run python manage.py spectacular --file schema.yml
335335

336336
# View in browser
337337
# Navigate to http://mitxonline.odl.local:8013/api/schema/swagger-ui/

Dockerfile

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,46 +20,36 @@ RUN mkdir /src && \
2020
adduser --disabled-password --gecos "" mitodl && \
2121
mkdir /var/media && chown -R mitodl:mitodl /var/media
2222

23-
FROM system AS poetry
23+
FROM system AS uv
2424

2525
# copy in trusted certs
2626
COPY --chmod=644 certs/*.crt /usr/local/share/ca-certificates/
2727
RUN update-ca-certificates
2828

29-
# Poetry env configuration
29+
# uv env configuration
3030
ENV \
31-
# poetry:
3231
PYTHONUNBUFFERED=1 \
3332
PYTHONDONTWRITEBYTECODE=1 \
34-
PIP_DISABLE_PIP_VERSION_CHECK=on \
35-
POETRY_VERSION=2.1.3 \
36-
POETRY_VIRTUALENVS_CREATE=false \
37-
POETRY_CACHE_DIR='/tmp/cache/poetry' \
38-
POETRY_HOME='/home/mitodl/.local' \
39-
VIRTUAL_ENV="/opt/venv"
40-
ENV PATH="$VIRTUAL_ENV/bin:$POETRY_HOME/bin:$PATH"
33+
UV_PROJECT_ENVIRONMENT="/opt/venv"
34+
ENV PATH="/opt/venv/bin:$PATH"
4135

42-
RUN pip install --no-cache-dir "poetry==$POETRY_VERSION"
36+
# Install uv
37+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
4338

4439
COPY pyproject.toml /src
45-
COPY poetry.lock /src
40+
COPY uv.lock /src
4641
COPY mitol_*.gz /src
4742

4843
RUN chown -R mitodl:mitodl /src && \
49-
mkdir ${VIRTUAL_ENV} && chown -R mitodl:mitodl ${VIRTUAL_ENV}
44+
mkdir -p /opt/venv && \
45+
chown -R mitodl:mitodl /opt/venv
5046

5147
USER mitodl
52-
RUN curl -sSL https://install.python-poetry.org \
53-
| \
54-
POETRY_VERSION=${POETRY_VERSION} \
55-
POETRY_HOME=${POETRY_HOME} \
56-
python3 -q
5748
WORKDIR /src
58-
RUN python3 -m venv $VIRTUAL_ENV
59-
RUN poetry install
49+
RUN uv sync --frozen --no-install-project --group prod
6050

6151

62-
FROM poetry AS code
52+
FROM uv AS code
6353

6454
COPY . /src
6555
WORKDIR /src
@@ -90,6 +80,6 @@ COPY --from=node /src /src
9080

9181
FROM code AS jupyter-notebook
9282

93-
RUN pip install --force-reinstall jupyter
83+
RUN uv pip install --force-reinstall jupyter
9484

9585
USER mitodl

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ In order to manage the certificates, follow these steps:
4444

4545
# Updating python dependencies
4646

47-
Python dependencies are managed with poetry. If you need to add a new dependency, run this command:
47+
Python dependencies are managed with uv. If you need to add a new dependency, run this command:
4848

4949
```
50-
docker compose run --rm web poetry add <dependency>
50+
docker compose run --rm web uv add <dependency>
5151
```
52-
This will update the `pyproject.toml` and `poetry.lock` files. Then run `docker-compose build web celery` to make the change permanent in your docker images.
53-
Refer to the [poetry documentation](https://python-poetry.org/docs/cli/) for particulars about specifying versions, removing dependencies, etc.
52+
This will update the `pyproject.toml` and `uv.lock` files. Then run `docker-compose build web celery` to make the change permanent in your docker images.
53+
Refer to the [uv documentation](https://docs.astral.sh/uv/reference/cli/) for particulars about specifying versions, removing dependencies, etc.
5454

5555

5656
# Generating documentation

b2b/api_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ def test_ensure_enrollment_codes( # noqa: PLR0913
281281
mocker.patch("openedx.tasks.clone_courserun.delay")
282282
mocked_ensure_call = mocker.patch("b2b.tasks.queue_enrollment_code_check.delay")
283283
max_learners = FAKE.random_int(min=1, max=15) if has_learner_cap else None
284-
price = FAKE.random_int(min=0, max=100) if has_price else None
284+
price = FAKE.random_int(min=1, max=100) if has_price else None
285285
assert_price = price if price else Decimal(0)
286286

287287
contract = factories.ContractPageFactory(
@@ -326,7 +326,7 @@ def test_ensure_enrollment_codes( # noqa: PLR0913
326326
# no longer have discounts.
327327
if update_no_price or update_sso or update_change_price:
328328
if update_change_price:
329-
price = FAKE.random_int(min=0, max=100)
329+
price = FAKE.random_int(min=1, max=100)
330330
assert_price = price if price else Decimal(0)
331331
contract.enrollment_fixed_price = price
332332
if update_no_price:

docs/source/configuration/uwsgi_tuning.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ To set up locally:
1616

1717
Set up uwsgitop
1818
---------------
19-
1. Install uwsgitop: ``docker compose run --rm web poetry add uwsgitop``
19+
1. Install uwsgitop: ``docker compose run --rm web uv add uwsgitop``
2020
2. Set UWSGI_RELOAD_ON_RSS in your .env to a high value (e.g. 500)
2121
3. Set UWSGI_MAX_REQUESTS in your .env to a high value (e.g. 10000)
2222
4. ``docker compose build``
@@ -27,7 +27,7 @@ Set up uwsgitop
2727

2828
Set up Locust
2929
-------------
30-
1. Install Locust: ``docker compose run --rm web poetry add locust``
30+
1. Install Locust: ``docker compose run --rm web uv add locust``
3131
2. Add locust to your docker-compose.yml locally, under services:
3232

3333
.. code-block:: shell

0 commit comments

Comments
 (0)