From d297bb4802aa4ccf66c5e65dfbdbaf0804381822 Mon Sep 17 00:00:00 2001 From: salmannawaz Date: Tue, 19 May 2026 13:57:28 +0500 Subject: [PATCH 1/8] chore: add tox.ini for local development Co-Authored-By: Claude Sonnet 4.6 --- tox.ini | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tox.ini diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..81275db --- /dev/null +++ b/tox.ini @@ -0,0 +1,22 @@ +[tox] +envlist = lint, test, docs +requires = + tox-uv>=1 + +[testenv:lint] +runner = uv-venv-lock-runner +extras = dev +commands = + ruff check . + ruff format --check . + +[testenv:test] +runner = uv-venv-lock-runner +extras = test +commands = pytest --cov=src --cov-report=xml {posargs} + +[testenv:docs] +runner = uv-venv-lock-runner +extras = docs +commands = + make -C docs html From 5841a45bf604488eb58ae6e93e3dbea553c96be5 Mon Sep 17 00:00:00 2001 From: salmannawaz Date: Mon, 22 Jun 2026 22:10:38 +0500 Subject: [PATCH 2/8] chore: make tox the source of truth for test commands - Makefile and CI now delegate to `tox -e ` instead of running commands directly - Add `allowlist_externals = make` to [testenv:docs] for tox v4 compatibility - Add `uv tool install tox --with tox-uv` to `make requirements` Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 17 +++++++++-------- Makefile | 15 ++++++--------- tox.ini | 1 + 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0da78d9..c546a69 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,11 +21,11 @@ jobs: enable-cache: true python-version: "3.12" - - name: Install dependencies - run: uv sync --extra dev + - name: Install tox + run: uv tool install tox --with tox-uv - name: Run linting - run: make lint + run: tox -e lint test: name: Test (Python ${{ matrix.python-version }}, Django ${{ matrix.django-version }}) @@ -46,13 +46,14 @@ jobs: enable-cache: true python-version: "${{ matrix.python-version }}" - - name: Install dependencies - run: | - uv lock --upgrade-package "django==${{ matrix.django-version }}.*" - uv sync --extra test + - name: Pin Django version + run: uv lock --upgrade-package "django==${{ matrix.django-version }}.*" + + - name: Install tox + run: uv tool install tox --with tox-uv - name: Run tests with coverage - run: make test-with-coverage + run: tox -e test - name: Upload coverage to Codecov if: matrix.django-version == '4.2' diff --git a/Makefile b/Makefile index ac18b18..779fa7a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help requirements upgrade lint format test test-with-coverage docs clean +.PHONY: help requirements upgrade lint format test docs clean .PHONY: extract_translations @@ -15,26 +15,23 @@ help: ## Show this help message requirements: ## Sync dev dependencies uv sync + uv tool install tox --with tox-uv upgrade: ## Upgrade python dependencies uv lock --upgrade lint: ## Run linting checks - uv run ruff check . - uv run ruff format --check . + tox -e lint format: ## Auto-fix formatting issues uv run ruff check --fix . uv run ruff format . -test: ## Run tests with pytest - uv run pytest - -test-with-coverage: ## Run tests with coverage reporting - uv run pytest --cov=$(SRC_DIRECTORY) --cov-report=xml +test: ## Run tests with coverage reporting + tox -e test docs: ## Build documentation - $(MAKE) -C docs html + tox -e docs clean: ## Clean build artifacts rm -rf build/ diff --git a/tox.ini b/tox.ini index 81275db..d905e52 100644 --- a/tox.ini +++ b/tox.ini @@ -18,5 +18,6 @@ commands = pytest --cov=src --cov-report=xml {posargs} [testenv:docs] runner = uv-venv-lock-runner extras = docs +allowlist_externals = make commands = make -C docs html From 264bc604ed02b756856290d31d88e9fe631e1a58 Mon Sep 17 00:00:00 2001 From: salmannawaz Date: Tue, 23 Jun 2026 16:13:00 +0500 Subject: [PATCH 3/8] chore: replicate CI test matrix locally via tox dependency groups Adds PEP 735 dependency groups to test against Django 4.2 and 5.2 (matching the CI matrix), following the same pattern as openedx/XBlock. Co-Authored-By: Claude Sonnet 4.6 --- Makefile | 4 +- pyproject.toml | 27 +++++++- tox.ini | 14 ++-- uv.lock | 182 ++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 190 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index 779fa7a..cef3349 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,8 @@ format: ## Auto-fix formatting issues uv run ruff check --fix . uv run ruff format . -test: ## Run tests with coverage reporting - tox -e test +test: ## Run tests against all supported Python/Django combinations + tox -e "py312-django{42,52}" docs: ## Build documentation tox -e docs diff --git a/pyproject.toml b/pyproject.toml index 5cdc0ad..bdde0ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,18 +49,32 @@ dev = [ "ruff", "edx-i18n-tools", ] -test = [ + +[dependency-groups] +# Base test packages, no Django version pinned +test-base = [ "coverage", "edx-lint", "edx-opaque-keys", - "edx-opaque-keys", "mock", "pytest-cov", "pytest-django", "pytest>=7.0", "xblock-sdk", ] -docs = [ +# Default test group: current supported Django version +# Update Django pin here when bumping the default; add a legacy group for older versions +test = [ + {include-group = "test-base"}, + "Django>=5.2,<6.0", +] +# Legacy Django 4.2 support +django42 = [ + {include-group = "test-base"}, + "Django>=4.2,<5.0", +] +doc = [ + {include-group = "test"}, "sphinx", "sphinx-book-theme", ] @@ -172,6 +186,13 @@ directory = "htmlcov" # https://docs.astral.sh/uv/reference/settings/ [tool.uv] package = true +conflicts = [ + [ + {group = "test"}, + {group = "django42"}, + {group = "doc"}, + ], +] # Setuptools SCM configuration # https://setuptools-scm.readthedocs.io/ diff --git a/tox.ini b/tox.ini index d905e52..596f3d8 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,6 @@ [tox] -envlist = lint, test, docs -requires = - tox-uv>=1 +envlist = py312-django{42,52}, lint, docs +requires = tox-uv>=1 [testenv:lint] runner = uv-venv-lock-runner @@ -10,14 +9,17 @@ commands = ruff check . ruff format --check . -[testenv:test] +[testenv:py312-django{42,52}] runner = uv-venv-lock-runner -extras = test + +dependency_groups = + django42: django42 + django52: test commands = pytest --cov=src --cov-report=xml {posargs} [testenv:docs] runner = uv-venv-lock-runner -extras = docs +dependency_groups = doc allowlist_externals = make commands = make -C docs html diff --git a/uv.lock b/uv.lock index 4ac4c23..feb4f7c 100644 --- a/uv.lock +++ b/uv.lock @@ -5,6 +5,14 @@ resolution-markers = [ "python_full_version >= '3.13'", "python_full_version < '3.13'", ] +conflicts = [[ + { package = "xblocks-extra", group = "django42" }, + { package = "xblocks-extra", group = "doc" }, + { package = "xblocks-extra", group = "test" }, +], [ + { package = "xblocks-extra", group = "django42" }, + { package = "xblocks-extra", group = "doc" }, +]] [[package]] name = "accessible-pygments" @@ -131,7 +139,7 @@ name = "build" version = "1.4.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "os_name == 'nt'" }, + { name = "colorama", marker = "os_name == 'nt' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, { name = "packaging" }, { name = "pyproject-hooks" }, ] @@ -227,7 +235,7 @@ name = "click" version = "8.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/57/75/31212c6bf2503fdf920d87fee5d7a86a2e3bcf444984126f13d8e4016804/click-8.3.2.tar.gz", hash = "sha256:14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5", size = 302856, upload-time = "2026-04-03T19:14:45.118Z" } wheels = [ @@ -383,14 +391,54 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, ] +[[package]] +name = "django" +version = "4.2.30" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version < '3.13'", +] +dependencies = [ + { name = "asgiref", marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "sqlparse", marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "tzdata", marker = "(sys_platform == 'win32' and extra == 'group-13-xblocks-extra-django42') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/11/b5/f1a53dc68da6429d6e0345bb848161e2381a2e9f02700148911e8582c2b3/django-4.2.30.tar.gz", hash = "sha256:4ebc7a434e3819db6cf4b399fb5b3f536310a30e8486f08b66886840be84b37c", size = 10468707, upload-time = "2026-04-07T14:05:45.57Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/b7/a7c96f239cf91313a6589233fed55111c7063b26683b226802732c455dbc/django-4.2.30-py3-none-any.whl", hash = "sha256:4d07aaf1c62f9984842b67c2874ebbf7056a17be253860299b93ae1881faad65", size = 7997231, upload-time = "2026-04-07T14:05:38.241Z" }, +] + +[[package]] +name = "django" +version = "5.2.15" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version < '3.13'", +] +dependencies = [ + { name = "asgiref", marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test'" }, + { name = "sqlparse", marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test'" }, + { name = "tzdata", marker = "(sys_platform == 'win32' and extra == 'group-13-xblocks-extra-doc') or (sys_platform == 'win32' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2b/e3/31722f7284c9f43333daff9aee9184678e4487adcb5506af0db8cea09ce1/django-5.2.15.tar.gz", hash = "sha256:5154a9bf84ac01dde011e367f355c07dbb329532e06810dcf3ef2af269e236e7", size = 10873669, upload-time = "2026-06-03T13:03:35.892Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/b5/38140b1643c00d5c46ce69c78e6980fd285aee223100319631bedee4f5e7/django-5.2.15-py3-none-any.whl", hash = "sha256:0eb4a9bb1853a35b0286dbc6d916bd352c8c2687195a7f2d6f80cefd840e4970", size = 8311957, upload-time = "2026-06-03T13:03:31.329Z" }, +] + [[package]] name = "django" version = "6.0.4" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version < '3.13'", +] dependencies = [ - { name = "asgiref" }, - { name = "sqlparse" }, - { name = "tzdata", marker = "sys_platform == 'win32'" }, + { name = "asgiref", marker = "(extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test') or (extra != 'group-13-xblocks-extra-django42' and extra != 'group-13-xblocks-extra-doc' and extra != 'group-13-xblocks-extra-test')" }, + { name = "sqlparse", marker = "(extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test') or (extra != 'group-13-xblocks-extra-django42' and extra != 'group-13-xblocks-extra-doc' and extra != 'group-13-xblocks-extra-test')" }, + { name = "tzdata", marker = "(sys_platform == 'win32' and extra != 'group-13-xblocks-extra-django42' and extra != 'group-13-xblocks-extra-doc' and extra != 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/60/b9/4155091ad1788b38563bd77a7258c0834e8c12a7f56f6975deaf54f8b61d/django-6.0.4.tar.gz", hash = "sha256:8cfa2572b3f2768b2e84983cf3c4811877a01edb64e817986ec5d60751c113ac", size = 10907407, upload-time = "2026-04-07T13:55:44.961Z" } wheels = [ @@ -402,7 +450,9 @@ name = "django-crum" version = "0.7.9" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "django" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test'" }, + { name = "django", version = "6.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test') or (extra != 'group-13-xblocks-extra-django42' and extra != 'group-13-xblocks-extra-doc' and extra != 'group-13-xblocks-extra-test')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/34/1d/c56588f67130aeef8828e47535e8551337d2ae02f91f1414da61bc5e49fb/django-crum-0.7.9.tar.gz", hash = "sha256:65e9bc0f070a663fafc4d9e357f45fd4e6f01838b20a9e2fb7670f5706754288", size = 5168, upload-time = "2020-11-10T17:15:35.124Z" } wheels = [ @@ -444,7 +494,9 @@ name = "edx-i18n-tools" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "django" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test'" }, + { name = "django", version = "6.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test') or (extra != 'group-13-xblocks-extra-django42' and extra != 'group-13-xblocks-extra-doc' and extra != 'group-13-xblocks-extra-test')" }, { name = "lxml", extra = ["html-clean"] }, { name = "path" }, { name = "polib" }, @@ -806,7 +858,9 @@ name = "openedx-django-pyfs" version = "4.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "django" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test'" }, + { name = "django", version = "6.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test') or (extra != 'group-13-xblocks-extra-django42' and extra != 'group-13-xblocks-extra-doc' and extra != 'group-13-xblocks-extra-test')" }, { name = "fs" }, { name = "fs-s3fs" }, ] @@ -820,7 +874,9 @@ name = "openedx-filters" version = "3.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "django" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test'" }, + { name = "django", version = "6.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test') or (extra != 'group-13-xblocks-extra-django42' and extra != 'group-13-xblocks-extra-doc' and extra != 'group-13-xblocks-extra-test')" }, { name = "edx-opaque-keys" }, { name = "setuptools" }, ] @@ -907,7 +963,7 @@ version = "4.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astroid" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, { name = "dill" }, { name = "isort" }, { name = "mccabe" }, @@ -1028,7 +1084,7 @@ name = "pytest" version = "9.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, @@ -1461,7 +1517,7 @@ name = "webob" version = "1.8.9" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "legacy-cgi", marker = "python_full_version >= '3.13'" }, + { name = "legacy-cgi", marker = "python_full_version >= '3.13' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/85/0b/1732085540b01f65e4e7999e15864fe14cd18b12a95731a43fd6fd11b26a/webob-1.8.9.tar.gz", hash = "sha256:ad6078e2edb6766d1334ec3dee072ac6a7f95b1e32ce10def8ff7f0f02d56589", size = 279775, upload-time = "2024-10-24T03:19:20.651Z" } wheels = [ @@ -1501,7 +1557,9 @@ version = "0.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cookiecutter" }, - { name = "django" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test'" }, + { name = "django", version = "6.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test') or (extra != 'group-13-xblocks-extra-django42' and extra != 'group-13-xblocks-extra-doc' and extra != 'group-13-xblocks-extra-test')" }, { name = "fs-s3fs" }, { name = "lxml" }, { name = "pypng" }, @@ -1520,7 +1578,9 @@ wheels = [ name = "xblocks-extra" source = { editable = "." } dependencies = [ - { name = "django" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test'" }, + { name = "django", version = "6.0.4", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test') or (extra != 'group-13-xblocks-extra-django42' and extra != 'group-13-xblocks-extra-doc' and extra != 'group-13-xblocks-extra-test')" }, { name = "django-crum" }, { name = "edx-codejail" }, { name = "openedx-filters" }, @@ -1535,11 +1595,44 @@ dev = [ { name = "edx-i18n-tools" }, { name = "ruff" }, ] -docs = [ + +[package.dev-dependencies] +django42 = [ + { name = "coverage" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" } }, + { name = "edx-lint" }, + { name = "edx-opaque-keys" }, + { name = "mock" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "xblock-sdk" }, +] +doc = [ + { name = "coverage" }, + { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" } }, + { name = "edx-lint" }, + { name = "edx-opaque-keys" }, + { name = "mock" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, { name = "sphinx" }, { name = "sphinx-book-theme" }, + { name = "xblock-sdk" }, ] test = [ + { name = "coverage" }, + { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" } }, + { name = "edx-lint" }, + { name = "edx-opaque-keys" }, + { name = "mock" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "xblock-sdk" }, +] +test-base = [ { name = "coverage" }, { name = "edx-lint" }, { name = "edx-opaque-keys" }, @@ -1553,24 +1646,61 @@ test = [ [package.metadata] requires-dist = [ { name = "build", marker = "extra == 'dev'" }, - { name = "coverage", marker = "extra == 'test'" }, { name = "django", specifier = ">=4.2" }, { name = "django-crum" }, { name = "edx-codejail" }, { name = "edx-i18n-tools", marker = "extra == 'dev'" }, - { name = "edx-lint", marker = "extra == 'test'" }, - { name = "edx-opaque-keys", marker = "extra == 'test'" }, - { name = "mock", marker = "extra == 'test'" }, { name = "openedx-filters" }, - { name = "pytest", marker = "extra == 'test'", specifier = ">=7.0" }, - { name = "pytest-cov", marker = "extra == 'test'" }, - { name = "pytest-django", marker = "extra == 'test'" }, { name = "requests" }, { name = "ruff", marker = "extra == 'dev'" }, { name = "six" }, - { name = "sphinx", marker = "extra == 'docs'" }, - { name = "sphinx-book-theme", marker = "extra == 'docs'" }, { name = "xblock", extras = ["django"] }, - { name = "xblock-sdk", marker = "extra == 'test'" }, ] -provides-extras = ["dev", "test", "docs"] +provides-extras = ["dev"] + +[package.metadata.requires-dev] +django42 = [ + { name = "coverage" }, + { name = "django", specifier = ">=4.2,<5.0" }, + { name = "edx-lint" }, + { name = "edx-opaque-keys" }, + { name = "mock" }, + { name = "pytest", specifier = ">=7.0" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "xblock-sdk" }, +] +doc = [ + { name = "coverage" }, + { name = "django", specifier = ">=5.2,<6.0" }, + { name = "edx-lint" }, + { name = "edx-opaque-keys" }, + { name = "mock" }, + { name = "pytest", specifier = ">=7.0" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "sphinx" }, + { name = "sphinx-book-theme" }, + { name = "xblock-sdk" }, +] +test = [ + { name = "coverage" }, + { name = "django", specifier = ">=5.2,<6.0" }, + { name = "edx-lint" }, + { name = "edx-opaque-keys" }, + { name = "mock" }, + { name = "pytest", specifier = ">=7.0" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "xblock-sdk" }, +] +test-base = [ + { name = "coverage" }, + { name = "edx-lint" }, + { name = "edx-opaque-keys" }, + { name = "mock" }, + { name = "pytest", specifier = ">=7.0" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "xblock-sdk" }, +] From eef9f16a6f62d29d82de1b2f9a0880c986960c38 Mon Sep 17 00:00:00 2001 From: salmannawaz Date: Tue, 23 Jun 2026 16:46:58 +0500 Subject: [PATCH 4/8] chore: align CI and tox config with XBlock's approach - Replace separate lint/test/docs CI jobs with a single matrix job over [lint, docs, django42, django52] running in parallel - Use uv sync --group ci instead of uv tool install tox - Simplify tox envs from py312-django{42,52} to django{42,52} using [testenv] default with dependency group factors - Add ci dependency group to lock tox/tox-uv versions Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 38 ++-------- Makefile | 2 +- pyproject.toml | 4 + tox.ini | 5 +- uv.lock | 156 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 171 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23cd168..6693dae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,33 +8,14 @@ on: workflow_call: jobs: - lint: - name: Lint - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 - with: - enable-cache: true - python-version: "3.12" - - - name: Install tox - run: uv tool install tox --with tox-uv - - - name: Run linting - run: tox -e lint - - test: - name: Test (Python ${{ matrix.python-version }}, Django ${{ matrix.django-version }}) + run_tests: + name: ${{ matrix.toxenv }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: ["3.12"] - django-version: ["4.2", "5.2"] + toxenv: [lint, docs, django42, django52] steps: - name: Checkout repository @@ -46,17 +27,14 @@ jobs: enable-cache: true python-version: "${{ matrix.python-version }}" - - name: Pin Django version - run: uv lock --upgrade-package "django==${{ matrix.django-version }}.*" - - - name: Install tox - run: uv tool install tox --with tox-uv + - name: Install CI dependencies + run: uv sync --group ci - - name: Run tests with coverage - run: tox -e test + - name: Run tox + run: uv run tox -e ${{ matrix.toxenv }} - name: Upload coverage to Codecov - if: matrix.django-version == '4.2' + if: matrix.toxenv == 'django42' uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/Makefile b/Makefile index cef3349..d5db6b8 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ format: ## Auto-fix formatting issues uv run ruff format . test: ## Run tests against all supported Python/Django combinations - tox -e "py312-django{42,52}" + tox -e "django{42,52}" docs: ## Build documentation tox -e docs diff --git a/pyproject.toml b/pyproject.toml index 35addb6..8540eea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,6 +78,10 @@ doc = [ "sphinx", "sphinx-book-theme", ] +ci = [ + "tox", + "tox-uv", +] [project.entry-points."xblock.v1"] audio = "audio:AudioXBlock" diff --git a/tox.ini b/tox.ini index 596f3d8..7c95379 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py312-django{42,52}, lint, docs +envlist = django{42,52}, lint, docs requires = tox-uv>=1 [testenv:lint] @@ -9,9 +9,8 @@ commands = ruff check . ruff format --check . -[testenv:py312-django{42,52}] +[testenv] runner = uv-venv-lock-runner - dependency_groups = django42: django42 django52: test diff --git a/uv.lock b/uv.lock index 4c13251..1074ce3 100644 --- a/uv.lock +++ b/uv.lock @@ -148,6 +148,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl", hash = "sha256:13f3eecb844759ab66efec90ca17639bbf14dc06cb2fdf37a9010322d9c50a6f", size = 26018, upload-time = "2026-04-30T03:18:23.644Z" }, ] +[[package]] +name = "cachetools" +version = "7.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/8b/0d3945a13955303b81272f759a0331e54c5c793da455e6f5706b89d2639c/cachetools-7.1.4.tar.gz", hash = "sha256:437f55a4e0c1b01a4f3077cc470e6991d47430970e36fbcb77e2be0df4fc1cd6", size = 40085, upload-time = "2026-05-21T22:40:43.376Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/7b/1fc1c09cc0756cf25861a3be10565915953876da48bb228fb9a672b20a42/cachetools-7.1.4-py3-none-any.whl", hash = "sha256:323dc4127934744db5b54eb4924482d7edafbf9554e820d1531c2e08c0e4ef54", size = 16761, upload-time = "2026-05-21T22:40:41.845Z" }, +] + [[package]] name = "certifi" version = "2026.6.17" @@ -385,6 +394,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, ] +[[package]] +name = "distlib" +version = "0.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/02/bd72be9134d25ed783ecbbc38a539ffaefbf90c78418c7fb7229600dbac7/distlib-0.4.3.tar.gz", hash = "sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed", size = 615141, upload-time = "2026-06-12T08:04:52.847Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/08/9c41fb51ab5b43eb21674aff13df270e8ba6c4b29c8624e328dc7a9482af/distlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b", size = 470628, upload-time = "2026-06-12T08:04:50.506Z" }, +] + [[package]] name = "django" version = "4.2.30" @@ -514,6 +532,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/39/1b/e9edebd12fd461b605691759a01c12e73a78cb50a4cd0b04ab58bb8303d9/edx_opaque_keys-4.0.0-py3-none-any.whl", hash = "sha256:dab0fd985b13d6d6515049606f93684d1eb284207b6d5e8da0721e29efdd0088", size = 77651, upload-time = "2026-04-02T19:00:55.259Z" }, ] +[[package]] +name = "filelock" +version = "3.29.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e6/dc/be6cbe99670cd6e4ad387123647cb08e0c32975e223f82551e914c5568a6/filelock-3.29.4.tar.gz", hash = "sha256:10cdb3656fc44541cdf30652a93fb10ec6b05325620eb316bd26893e4201538a", size = 63028, upload-time = "2026-06-13T16:12:00.744Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/37/a065dc3bd6e49423a6532c642ca7378d3f467b1ef44c2800c937af7f9739/filelock-3.29.4-py3-none-any.whl", hash = "sha256:dac1648087d5115554850d113e7dd8c83ab2d38e3435dde2d4f163847e57b767", size = 42757, upload-time = "2026-06-13T16:11:59.582Z" }, +] + [[package]] name = "fs" version = "2.4.16" @@ -1043,6 +1070,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3e/b9/3766cc361d93edb2ce81e2e1f87dd98f314d7d513877a342d31b30741680/pypng-0.20220715.0-py3-none-any.whl", hash = "sha256:4a43e969b8f5aaafb2a415536c1a8ec7e341cd6a3f957fd5b5f32a4cfeed902c", size = 58057, upload-time = "2022-07-15T14:11:03.713Z" }, ] +[[package]] +name = "pyproject-api" +version = "1.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/62/0fe346fe380b1aafaf819c8cb195d3241bb4f355f908e6339814131a830b/pyproject_api-1.10.1.tar.gz", hash = "sha256:c2b2726bd7aa9217b6c50b621fef5b2ae5def4d55b779c9e0694c15e0a8517ba", size = 23477, upload-time = "2026-05-28T14:22:14.049Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/d7/29e1e5e882f79133631f7bcace42d23db493f616463c157a1ab614bf69dd/pyproject_api-1.10.1-py3-none-any.whl", hash = "sha256:fa9e6f66c35b5017e909825d8f2b5d5482ea699d7be809d21c03bd1f7317f36a", size = 12992, upload-time = "2026-05-28T14:22:12.711Z" }, +] + [[package]] name = "pyproject-hooks" version = "1.2.0" @@ -1106,6 +1145,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] +[[package]] +name = "python-discovery" +version = "1.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/1a/cbbaf13b730abb0a16b964d984e19f2fe520c21a4dc664051359a3f5a9e7/python_discovery-1.4.2.tar.gz", hash = "sha256:8f3746c4b4968d22afbb97d36e1a0e5b66e6c0f297290f2e95f05b9b8bf18690", size = 70277, upload-time = "2026-06-11T16:10:42.383Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/82/a70006589557f267f15bd384c0642ad49f0d97b690c3a05b166b9dcbad3b/python_discovery-1.4.2-py3-none-any.whl", hash = "sha256:475803f53b7b2ed6e490e27373f9d8340f7d2eebf9acdaf645d7d714c97bb500", size = 33886, upload-time = "2026-06-11T16:10:41.192Z" }, +] + [[package]] name = "python-slugify" version = "8.0.4" @@ -1458,6 +1510,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154, upload-time = "2019-08-30T21:37:03.543Z" }, ] +[[package]] +name = "tomli-w" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, +] + [[package]] name = "tomlkit" version = "0.15.0" @@ -1467,6 +1528,52 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6a/43/8bd850ee71a191bf072e31302c73a66be413fecdd98fdcd111ecbcce13ca/tomlkit-0.15.0-py3-none-any.whl", hash = "sha256:4dbc8f0fc024412b57ced8757ac7461305126a648ff8c2c807fcb8e133a78738", size = 41328, upload-time = "2026-05-10T07:38:23.517Z" }, ] +[[package]] +name = "tox" +version = "4.55.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachetools" }, + { name = "colorama" }, + { name = "filelock" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "pluggy" }, + { name = "pyproject-api" }, + { name = "python-discovery" }, + { name = "tomli-w" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/5b/4f09156a3f7bf3c4fa23212717f097c59126d81e2c557e6fd872a62db38a/tox-4.55.1.tar.gz", hash = "sha256:0678fbf26dd5b559b1ef128fa4388325920219322ebc8cc5f3497627c00f4472", size = 280676, upload-time = "2026-06-03T20:01:03.487Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/fd/394f00f3d3e23d87eb7b20276d88fe835e48780d3eb30e6f362428bb80c8/tox-4.55.1-py3-none-any.whl", hash = "sha256:e2084be6dfdef96ba1bed4948e6a1f73613d6952e1477be5dca45653d4c053c8", size = 215360, upload-time = "2026-06-03T20:01:01.967Z" }, +] + +[[package]] +name = "tox-uv" +version = "1.35.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tox-uv-bare" }, + { name = "uv" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/dc/6e9994c799bdbb309f829dd6b8d98764dd0757302f3433c380438a3a127b/tox_uv-1.35.2-py3-none-any.whl", hash = "sha256:2d99b0e3c782ba49e7cbe521c8d344758595961b17a3633738d67096641c1bde", size = 6565, upload-time = "2026-05-05T01:34:16.07Z" }, +] + +[[package]] +name = "tox-uv-bare" +version = "1.35.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "tox" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0a/cb/168dc1ccf24e4065a9a0a33df55709ed2b5eb73bd2b13ddd53187e5dffb8/tox_uv_bare-1.35.2.tar.gz", hash = "sha256:49e28a804c97f23ea17e25859960c0fa78f35bccb7e14344cfd840e89a9aade9", size = 32333, upload-time = "2026-05-05T01:34:18.916Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/53/4a33dc81da39db7b31e5622333df361e8fe055b7ec636bd5fea762c9182d/tox_uv_bare-1.35.2-py3-none-any.whl", hash = "sha256:c0d590a41d1054a1ad0874e9e5943ff52402786e3d4599d8f8d37a65b566ef53", size = 22307, upload-time = "2026-05-05T01:34:17.681Z" }, +] + [[package]] name = "typing-extensions" version = "4.15.0" @@ -1494,6 +1601,47 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, ] +[[package]] +name = "uv" +version = "0.11.23" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/47/99914cda63a82ce0421274df3f05caa042972c6d10c0bb4c2a1f48e779da/uv-0.11.23.tar.gz", hash = "sha256:f2476dda35866ea3ded3a5905759da2d32dfac36dfd5b3428191a99a8ce15b02", size = 4280676, upload-time = "2026-06-19T18:41:58.868Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dd/4c/4bdad9fc27c095babd686a65a8343d53d2fac9ee57e03429e4aabcb71a0a/uv-0.11.23-py3-none-linux_armv6l.whl", hash = "sha256:576d776a1ca62e3d8aba99f0d8ec607db91a5ebaf52feaff820f28ed820e1665", size = 24105940, upload-time = "2026-06-19T18:41:11.21Z" }, + { url = "https://files.pythonhosted.org/packages/e7/6d/798a730b481c02974fddda491c6b33c121e8871ee978dd16ef37dea99b11/uv-0.11.23-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac337dacd640aab1ef97cf00f8c01e2889f0fd0ef8460a0f4e816bf12bb5988b", size = 23237658, upload-time = "2026-06-19T18:41:14.252Z" }, + { url = "https://files.pythonhosted.org/packages/bf/88/042998975200a03d00321d3f922fa099ed7766883d129f4c2ae89f2fe476/uv-0.11.23-py3-none-macosx_11_0_arm64.whl", hash = "sha256:03fbb0a1c7b6d15e96778bdd79e8d1826c6259fea17fc13337fb0744136953f2", size = 22057768, upload-time = "2026-06-19T18:41:16.678Z" }, + { url = "https://files.pythonhosted.org/packages/24/e7/181e3cc171383001bdb6f69dea8bcba84988a12ab88d7344aa3d498fc6e0/uv-0.11.23-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:d256f90513d01ff6cbc2f17d88c0ccde65d138500df547ece214e6a50731c4b7", size = 23883298, upload-time = "2026-06-19T18:41:19.141Z" }, + { url = "https://files.pythonhosted.org/packages/02/57/4f11d8f5295d3e297b8a1c87b4b4cadc3426445fa4f074d4698a4151ffaa/uv-0.11.23-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:985aa93c9d6223e32fc747e09662537c4073c9ebef59c0a4fd7c6949d1d24fb3", size = 23657839, upload-time = "2026-06-19T18:41:21.459Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ef/82f12927ea76ba547b86121d553dfa2830f3daac08ec43201bc3937f8458/uv-0.11.23-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ca1d37e851fb9323250385403d8512a71c0d1b6162c729ff4909f37cfd067920", size = 23663720, upload-time = "2026-06-19T18:41:23.968Z" }, + { url = "https://files.pythonhosted.org/packages/a2/9f/3dd5e553d0ac834e1a9e2b748639adaaa72a03e242e1a14da5d9316dab82/uv-0.11.23-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91d19c4249d7437b69b91c385134360d7ed9d0ee2e2e83e81d369867151e78c2", size = 25093644, upload-time = "2026-06-19T18:41:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/8f/86/0e65260780c0609ca5863d5f3da1eb431a4cea0c316907fce5d276d147c9/uv-0.11.23-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8abe7d6f5e0d92bd41a9c000bbd9c8387af7886df4790c0451a34e781b8a075", size = 26036961, upload-time = "2026-06-19T18:41:29.207Z" }, + { url = "https://files.pythonhosted.org/packages/4a/6b/3bc2a1dc98baf39a893e2e0d50f9fa89cc3653ff38dc47379f66b4cbf160/uv-0.11.23-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a900c8fd757f8c3da9dc5532d9a22d30540e91fdefd63c93909fedbfd756655", size = 25240174, upload-time = "2026-06-19T18:41:31.955Z" }, + { url = "https://files.pythonhosted.org/packages/19/ff/764e1c21ba988589d2b505d2b06876b5f06ffe7cc6858dff6cc3faf7cb14/uv-0.11.23-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a85330de0a7eb0d5c6cf03c80edfb86facad19df367a0b52fc906db1ab15ce9", size = 25364351, upload-time = "2026-06-19T18:41:34.253Z" }, + { url = "https://files.pythonhosted.org/packages/ff/a0/499c4a8ce9bb54df65b4070513f4a6150d18a184767d4679a14c3b8a13b6/uv-0.11.23-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:6d7cea7d9ade3c1c3e3db1dfcc23d335bceaabf38f51e442b6f57f8f7885a9a6", size = 23994955, upload-time = "2026-06-19T18:41:37.056Z" }, + { url = "https://files.pythonhosted.org/packages/8f/3c/5a895aca4c03b38d7405d12f85de01e5dd7f00a85504ded4700ab31a3843/uv-0.11.23-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:e7e215d69ea21fd5824a63edf8fef933bee2c028a0c2930651cfa6b88ca4ff8e", size = 24714261, upload-time = "2026-06-19T18:41:39.557Z" }, + { url = "https://files.pythonhosted.org/packages/22/56/8cc65207403b7b1ca39d9b623c1d4dfcc477a567f91997dd8e1a15ee2454/uv-0.11.23-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9dd412127cbe0e115bd3fc5c6cbe9cf59f593273fafab9f7dc6b2ac95efcc7c1", size = 24824341, upload-time = "2026-06-19T18:41:42.449Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ea/3792d17ddbd6773bafc1261fede473befcf16eb4e9fc341ee11ce8de9d2b/uv-0.11.23-py3-none-musllinux_1_1_i686.whl", hash = "sha256:bbc41182d655f92cd380ecdf378da7fc1598c6b19057208f450f0ee9c259f46a", size = 24335130, upload-time = "2026-06-19T18:41:44.991Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ac/0546359a30b1a2f110a43e4271c94f4ebdc3ae6c8bcadc8d1fcdbc11ad57/uv-0.11.23-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:d62410e5f60a961cfda00ead8a1cc5fd37d052afda021099e488e90c15419beb", size = 25600430, upload-time = "2026-06-19T18:41:48.252Z" }, + { url = "https://files.pythonhosted.org/packages/3d/30/d907c9d6e191819bed5466f634bb9ace6b1d971f0e31f8cede881b08e01d/uv-0.11.23-py3-none-win32.whl", hash = "sha256:c2089b992919858dabae89d410cbb5cecf9034d26bbb04f14e6da52dffced290", size = 22926072, upload-time = "2026-06-19T18:41:50.784Z" }, + { url = "https://files.pythonhosted.org/packages/41/c7/3ad22f0d3f52497bef079ac1a6805c994ca68148bd273d11a61cb5c4bf56/uv-0.11.23-py3-none-win_amd64.whl", hash = "sha256:b3f515fd6b43068f241467496bced62cb2ed36d52d4c0877cfe61a1240713d32", size = 25624656, upload-time = "2026-06-19T18:41:53.987Z" }, + { url = "https://files.pythonhosted.org/packages/3d/71/5954f12428c5d7502e97d15d7600c818424fd3b946761c5a0c85fec58315/uv-0.11.23-py3-none-win_arm64.whl", hash = "sha256:61e6bd7e7f0fe24f103540ba19516443bea6e689022c787217310a1e64558e3f", size = 24027764, upload-time = "2026-06-19T18:41:56.589Z" }, +] + +[[package]] +name = "virtualenv" +version = "21.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "python-discovery" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/a5/81f987504738e6defeed61ec1c47e2aefab3c35d8eeb87e1b3f38cf28254/virtualenv-21.5.1.tar.gz", hash = "sha256:dca3bf98275a59c652b69d68e73433e597d977c2da9198882479d1a7188009c8", size = 4578798, upload-time = "2026-06-16T16:23:58.603Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/02/3623e6169bed617ed1e2d372f7c69f92ec28d54c4dfc997055c8578ec148/virtualenv-21.5.1-py3-none-any.whl", hash = "sha256:55aa670b67bbfb991b03fda39bd3276d92c419d702376e98c5df1c9989a26783", size = 4558820, upload-time = "2026-06-16T16:23:56.963Z" }, +] + [[package]] name = "web-fragments" version = "4.0.0" @@ -1586,6 +1734,10 @@ dev = [ ] [package.dev-dependencies] +ci = [ + { name = "tox" }, + { name = "tox-uv" }, +] django42 = [ { name = "coverage" }, { name = "ddt" }, @@ -1656,6 +1808,10 @@ requires-dist = [ provides-extras = ["dev"] [package.metadata.requires-dev] +ci = [ + { name = "tox" }, + { name = "tox-uv" }, +] django42 = [ { name = "coverage" }, { name = "ddt" }, From 0151abc4cf68747393def8708a04df750cb28016 Mon Sep 17 00:00:00 2001 From: salmannawaz Date: Tue, 23 Jun 2026 16:58:31 +0500 Subject: [PATCH 5/8] chore: use changedir for docs tox env Matches XBlock's approach of using changedir = {toxinidir}/docs with make html instead of make -C docs html. Co-Authored-By: Claude Sonnet 4.6 --- tox.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 7c95379..6619d6e 100644 --- a/tox.ini +++ b/tox.ini @@ -18,7 +18,9 @@ commands = pytest --cov=src --cov-report=xml {posargs} [testenv:docs] runner = uv-venv-lock-runner +basepython = python3.12 +changedir = {toxinidir}/docs dependency_groups = doc allowlist_externals = make commands = - make -C docs html + make html From 42f67bb41ede2bff0c35c22832ccaaee17901cdb Mon Sep 17 00:00:00 2001 From: salmannawaz Date: Wed, 24 Jun 2026 15:05:39 +0500 Subject: [PATCH 6/8] chore: fail CI on codecov errors and drop redundant doc conflict - Set fail_ci_if_error: true so coverage upload failures surface in CI - Remove explicit {group = "doc"} from uv conflicts; uv derives it automatically since doc includes test via include-group Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 2 +- pyproject.toml | 1 - uv.lock | 31 +++++++++++++++---------------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6693dae..ee69447 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,4 +39,4 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} flags: unittests - fail_ci_if_error: false + fail_ci_if_error: true diff --git a/pyproject.toml b/pyproject.toml index 8540eea..ba910e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -196,7 +196,6 @@ conflicts = [ [ {group = "test"}, {group = "django42"}, - {group = "doc"}, ], ] diff --git a/uv.lock b/uv.lock index 1074ce3..d38f350 100644 --- a/uv.lock +++ b/uv.lock @@ -7,7 +7,6 @@ resolution-markers = [ ] conflicts = [[ { package = "xblocks-extra", group = "django42" }, - { package = "xblocks-extra", group = "doc" }, { package = "xblocks-extra", group = "test" }, ], [ { package = "xblocks-extra", group = "django42" }, @@ -139,7 +138,7 @@ name = "build" version = "1.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "os_name == 'nt' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "colorama", marker = "os_name == 'nt' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test')" }, { name = "packaging" }, { name = "pyproject-hooks" }, ] @@ -244,7 +243,7 @@ name = "click" version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9b/98/518d8e5081007684232226f475082b30087d0f585e8457db087298259f49/click-8.4.1.tar.gz", hash = "sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96", size = 353007, upload-time = "2026-05-22T04:08:37.769Z" } wheels = [ @@ -412,9 +411,9 @@ resolution-markers = [ "python_full_version < '3.13'", ] dependencies = [ - { name = "asgiref", marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, - { name = "sqlparse", marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, - { name = "tzdata", marker = "(sys_platform == 'win32' and extra == 'group-13-xblocks-extra-django42') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "asgiref", marker = "extra == 'group-13-xblocks-extra-django42'" }, + { name = "sqlparse", marker = "extra == 'group-13-xblocks-extra-django42'" }, + { name = "tzdata", marker = "(sys_platform == 'win32' and extra == 'group-13-xblocks-extra-django42') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/11/b5/f1a53dc68da6429d6e0345bb848161e2381a2e9f02700148911e8582c2b3/django-4.2.30.tar.gz", hash = "sha256:4ebc7a434e3819db6cf4b399fb5b3f536310a30e8486f08b66886840be84b37c", size = 10468707, upload-time = "2026-04-07T14:05:45.57Z" } wheels = [ @@ -432,7 +431,7 @@ resolution-markers = [ dependencies = [ { name = "asgiref", marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test' or extra != 'group-13-xblocks-extra-django42'" }, { name = "sqlparse", marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test' or extra != 'group-13-xblocks-extra-django42'" }, - { name = "tzdata", marker = "(sys_platform == 'win32' and extra != 'group-13-xblocks-extra-django42') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test')" }, + { name = "tzdata", marker = "(sys_platform == 'win32' and extra != 'group-13-xblocks-extra-django42') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2b/e3/31722f7284c9f43333daff9aee9184678e4487adcb5506af0db8cea09ce1/django-5.2.15.tar.gz", hash = "sha256:5154a9bf84ac01dde011e367f355c07dbb329532e06810dcf3ef2af269e236e7", size = 10873669, upload-time = "2026-06-03T13:03:35.892Z" } wheels = [ @@ -444,7 +443,7 @@ name = "django-crum" version = "0.7.9" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42'" }, { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test' or extra != 'group-13-xblocks-extra-django42'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/34/1d/c56588f67130aeef8828e47535e8551337d2ae02f91f1414da61bc5e49fb/django-crum-0.7.9.tar.gz", hash = "sha256:65e9bc0f070a663fafc4d9e357f45fd4e6f01838b20a9e2fb7670f5706754288", size = 5168, upload-time = "2020-11-10T17:15:35.124Z" } @@ -487,7 +486,7 @@ name = "edx-i18n-tools" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42'" }, { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test' or extra != 'group-13-xblocks-extra-django42'" }, { name = "lxml", extra = ["html-clean"] }, { name = "path" }, @@ -860,7 +859,7 @@ name = "openedx-django-pyfs" version = "4.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42'" }, { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test' or extra != 'group-13-xblocks-extra-django42'" }, { name = "fs" }, { name = "fs-s3fs" }, @@ -875,7 +874,7 @@ name = "openedx-filters" version = "3.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42'" }, { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test' or extra != 'group-13-xblocks-extra-django42'" }, { name = "edx-opaque-keys" }, { name = "setuptools" }, @@ -963,7 +962,7 @@ version = "4.0.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astroid" }, - { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test')" }, { name = "dill" }, { name = "isort" }, { name = "mccabe" }, @@ -1096,7 +1095,7 @@ name = "pytest" version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test')" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, @@ -1656,7 +1655,7 @@ name = "webob" version = "1.8.10" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "legacy-cgi", marker = "python_full_version >= '3.13' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test') or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "legacy-cgi", marker = "python_full_version >= '3.13' or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-doc') or (extra == 'group-13-xblocks-extra-django42' and extra == 'group-13-xblocks-extra-test')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/58/f9/974eafebfd0bd442b8848899fe7d30675c93f750c313e1a6fe61acbde1e3/webob-1.8.10.tar.gz", hash = "sha256:1c963a11f307bc3f624fbab9dde737701eae255f32981b7a5486a88db1767c2b", size = 280796, upload-time = "2026-06-02T19:56:47.268Z" } wheels = [ @@ -1696,7 +1695,7 @@ version = "0.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cookiecutter" }, - { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42'" }, { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test' or extra != 'group-13-xblocks-extra-django42'" }, { name = "fs-s3fs" }, { name = "lxml" }, @@ -1716,7 +1715,7 @@ wheels = [ name = "xblocks-extra" source = { editable = "." } dependencies = [ - { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42' or (extra == 'group-13-xblocks-extra-doc' and extra == 'group-13-xblocks-extra-test')" }, + { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-django42'" }, { name = "django", version = "5.2.15", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-13-xblocks-extra-doc' or extra == 'group-13-xblocks-extra-test' or extra != 'group-13-xblocks-extra-django42'" }, { name = "django-crum" }, { name = "edx-codejail" }, From 7a68dac765bf898d4fb33d27a972f27dfe9e540b Mon Sep 17 00:00:00 2001 From: salmannawaz Date: Wed, 24 Jun 2026 15:19:20 +0500 Subject: [PATCH 7/8] chore: update codecov-action pin to v6.0.2 v6.0.1 had a stale GPG signing key causing CI failures. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee69447..2e602f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: - name: Upload coverage to Codecov if: matrix.toxenv == 'django42' - uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6.0.2 with: token: ${{ secrets.CODECOV_TOKEN }} flags: unittests From e411010d078063416290171411f67544917577d9 Mon Sep 17 00:00:00 2001 From: salmannawaz Date: Wed, 24 Jun 2026 16:01:24 +0500 Subject: [PATCH 8/8] chore: explicitly pin py312 in tox envlist and Makefile test target Co-Authored-By: Claude Sonnet 4.6 --- Makefile | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d5db6b8..cef3349 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ format: ## Auto-fix formatting issues uv run ruff format . test: ## Run tests against all supported Python/Django combinations - tox -e "django{42,52}" + tox -e "py312-django{42,52}" docs: ## Build documentation tox -e docs diff --git a/tox.ini b/tox.ini index 6619d6e..7fd1b04 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = django{42,52}, lint, docs +envlist = py312-django{42,52}, lint, docs requires = tox-uv>=1 [testenv:lint]