Skip to content

Commit 7d870be

Browse files
farhanclaude
andauthored
build: modernize mockprock to uv + pyproject.toml (pylint retained, no ruff) (#66)
- Replace setup.py with pyproject.toml (PEP 621 static metadata) - Switch from pip-compile to uv with PEP 735 dependency groups; commit uv.lock - Retain pylint/isort as on master (ruff deferred to separate epic per public-engineering#506) - Update tox.ini to use tox-uv with uv-venv-lock-runner - Add ci.yml using astral-sh/setup-uv; SHA-pin all actions; add workflow_call trigger - Drop Python 3.11 support; set requires-python = ">=3.12" - Add placeholder test so pytest collects at least one item Split from #65; ruff retained there for adoption in a future epic (per public-engineering#506). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 695a0a3 commit 7d870be

28 files changed

Lines changed: 2172 additions & 388 deletions

.github/workflows/ci.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
# Allow this workflow to be called from other workflows
8+
workflow_call:
9+
10+
jobs:
11+
run_tests:
12+
name: ${{ matrix.toxenv }}
13+
runs-on: ubuntu-latest
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
python-version: ["3.12"]
18+
toxenv: [quality, py]
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
23+
24+
- name: Install uv
25+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v6.3.1
26+
with:
27+
enable-cache: true
28+
python-version: "${{ matrix.python-version }}"
29+
30+
- name: Install CI dependencies
31+
run: uv sync --group ci
32+
33+
- name: Run tox
34+
run: uv run tox -e ${{ matrix.toxenv }}
35+
36+
- name: Upload coverage to Codecov
37+
if: matrix.toxenv == 'py' && matrix.python-version == '3.12'
38+
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
39+
with:
40+
token: ${{ secrets.CODECOV_TOKEN }}
41+
flags: unittests
42+
fail_ci_if_error: false

.github/workflows/release.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@ on:
44
tags:
55
- '*'
66

7-
permissions:
8-
id-token: write # Required for OIDC
9-
contents: write # For Semantic Release tagging
10-
117
jobs:
8+
run_tests:
9+
uses: ./.github/workflows/ci.yml
10+
secrets: inherit
11+
permissions:
12+
contents: read
13+
1214
release:
1315
name: Release
16+
needs: run_tests
1417
runs-on: ubuntu-latest
18+
permissions:
19+
id-token: write # Required for OIDC
20+
contents: write # For Semantic Release tagging
1521
steps:
1622
- name: Checkout
1723
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1

MANIFEST.in

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,4 @@ include LICENSE.txt
22
include README.rst
33
# graft edx_proctoring
44
# prune edx_proctoring/static/proctoring/spec
5-
recursive-include requirements *.in *.txt
65
global-exclude *.pyc
7-
include requirements/constraints.txt

Makefile

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
help: ## display this help message
66
@echo "Please use \`make <target>' where <target> is one of:"
7-
@awk -F ':.*?## ' '/^[a-zA-Z]/ && NF==2 {printf "\033[36m %-25s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort
7+
@awk -F ':.*?## ' '/^[a-zA-Z]/ && NF==2 {printf "\033[36m %-25s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort
88

99
clean: ## remove generated byte code, coverage reports, and build artifacts
1010
find . -name '__pycache__' -exec rm -rf {} +
@@ -15,34 +15,20 @@ clean: ## remove generated byte code, coverage reports, and build artifacts
1515
rm -fr dist/
1616
rm -fr *.egg-info
1717

18-
COMMON_CONSTRAINTS_TXT=requirements/common_constraints.txt
19-
.PHONY: $(COMMON_CONSTRAINTS_TXT)
20-
$(COMMON_CONSTRAINTS_TXT):
21-
wget -O "$(@)" https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt || touch "$(@)"
22-
23-
upgrade: export CUSTOM_COMPILE_COMMAND=make upgrade
24-
upgrade: $(COMMON_CONSTRAINTS_TXT)
25-
## update the requirements/*.txt files with the latest packages satisfying requirements/*.in
26-
pip install -qr requirements/pip-tools.txt
27-
pip-compile --upgrade --rebuild --allow-unsafe -o requirements/pip.txt requirements/pip.in
28-
pip-compile --upgrade -o requirements/pip-tools.txt requirements/pip-tools.in
29-
pip install -qr requirements/pip.txt
30-
pip install -qr requirements/pip-tools.txt
31-
pip-compile --upgrade -o requirements/base.txt requirements/base.in
32-
pip-compile --upgrade -o requirements/server.txt requirements/server.in
33-
pip-compile --upgrade -o requirements/testing.txt requirements/testing.in
18+
upgrade: ## Upgrade and regenerate pinned dependencies
19+
uv run --with edx-lint edx_lint write_uv_constraints pyproject.toml
20+
uv lock --upgrade
3421

3522
requirements: ## install development environment requirements
36-
pip install -qr requirements/base.txt
37-
pip install -qr requirements/testing.txt
38-
23+
uv sync --group dev
24+
uv tool install tox --with tox-uv
3925

4026
quality-python: ## Run python linters
41-
pylint --rcfile=pylintrc mockprock setup.py
27+
uv run tox -e quality
4228

4329
quality: quality-python ## Run linters
4430

4531
test-python: clean ## run tests using pytest and generate coverage report
46-
pytest
32+
uv run tox -e py312
4733

4834
test: test-python ## run tests

mockprock/commands.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Command line utilities"""
22
import argparse
3+
34
from mockprock.backend import MockProckBackend
45

56

mockprock/db.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from collections import namedtuple
2-
from contextlib import closing
31
import json
42
import sqlite3
53
import uuid
4+
from collections import namedtuple
5+
from contextlib import closing
66

77

88
def namedtuple_factory(cursor, row):

mockprock/desktop_views.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
These endpoints emulate a desktop proctoring application
33
They support starting a session, stopping a session, and pinging for availability
44
"""
5-
from flask import Blueprint, jsonify
65
import time
76

7+
from flask import Blueprint, jsonify
8+
89
fake_application = Blueprint(__name__, 'mockprock')
910

1011
# this assumes there's only one application "running". haha

mockprock/rest_api_client/client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from mockprock.rest_api_client.auth import SuppliedJwtAuth
1010

11+
1112
def user_agent():
1213
"""
1314
Return a User-Agent that identifies this client.

mockprock/server.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,16 @@
55
import sys
66
import threading
77
import time
8-
from collections import Iterable
8+
from collections.abc import Iterable
99
from functools import wraps
1010
from pprint import pprint
1111

1212
import jwt
1313
from flask import Flask, abort, jsonify, render_template, request
1414

15-
from mockprock.rest_api_client.client import OAuthAPIClient
1615
from mockprock.db import init_app
1716
from mockprock.desktop_views import fake_application
18-
17+
from mockprock.rest_api_client.client import OAuthAPIClient
1918

2019
app = Flask(__name__)
2120
app.debug = True

pyproject.toml

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
[build-system]
2+
requires = ["setuptools>=61.0"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "mockprock"
7+
version = "2.0.0"
8+
description = "Mock proctoring backend for Open edX"
9+
readme = "README.rst"
10+
requires-python = ">=3.12"
11+
license = "Apache-2.0"
12+
authors = [
13+
{name = "Open edX Project", email = "oscm@openedx.org"},
14+
]
15+
classifiers = [
16+
"Development Status :: 3 - Alpha",
17+
"Intended Audience :: Developers",
18+
"Natural Language :: English",
19+
"Programming Language :: Python :: 3",
20+
"Programming Language :: Python :: 3.12",
21+
"Framework :: Django",
22+
"Framework :: Django :: 4.2",
23+
"Framework :: Django :: 5.2",
24+
]
25+
keywords = [
26+
"Python",
27+
"edx",
28+
"openedx",
29+
"proctoring",
30+
]
31+
dependencies = []
32+
33+
[project.optional-dependencies]
34+
server = [
35+
"Flask<2.0",
36+
"PyJWT",
37+
"requests",
38+
]
39+
40+
[project.entry-points."openedx.proctoring"]
41+
mockprock = "mockprock.backend:MockProckBackend"
42+
43+
[project.scripts]
44+
get-dashboard = "mockprock.commands:get_url"
45+
46+
[project.urls]
47+
Repository = "https://github.com/openedx/mockprock"
48+
49+
[tool.setuptools.packages.find]
50+
exclude = ["tests*", "*.tests", "*.tests.*"]
51+
52+
[tool.setuptools.package-data]
53+
"mockprock" = ["templates/*"]
54+
55+
[dependency-groups]
56+
test-base = [
57+
"pytest",
58+
"pytest-cov",
59+
]
60+
test = [
61+
{include-group = "test-base"},
62+
]
63+
quality = [
64+
"pylint>=3.3,<4.0",
65+
"pylint-celery",
66+
"pylint-django",
67+
"isort",
68+
"edx-lint",
69+
]
70+
doc = []
71+
ci = [
72+
"tox",
73+
"tox-uv",
74+
]
75+
dev = [
76+
{include-group = "test"},
77+
{include-group = "quality"},
78+
{include-group = "doc"},
79+
"edx-lint",
80+
]
81+
82+
# uv configuration
83+
# https://docs.astral.sh/uv/reference/settings/
84+
[tool.uv]
85+
package = true
86+
87+
# edx-lint uv constraint support
88+
# https://github.com/openedx/edx-lint
89+
# DO NOT EDIT constraint-dependencies DIRECTLY.
90+
# This list is managed by `edx_lint write_uv_constraints`
91+
# and will be overwritten the next time `make upgrade` is run.
92+
# - GLOBAL constraints: edit edx_lint/files/common_constraints.txt
93+
# - REPO-SPECIFIC constraints: edit [tool.edx_lint].uv_constraints in this file
94+
constraint-dependencies = [
95+
"Django<6.0",
96+
"elasticsearch<7.14.0",
97+
]
98+
[tool.edx_lint]
99+
# This section is read by edx-lint; do not edit the constraint-dependencies directly.
100+
uv_constraints = []
101+
102+
# Pytest configuration
103+
# https://docs.pytest.org/en/stable/reference/customize.html
104+
[tool.pytest.ini_options]
105+
addopts = "--cov mockprock --cov-report term-missing --cov-report xml"
106+
107+
# Coverage configuration
108+
# https://coverage.readthedocs.io/en/latest/config.html
109+
[tool.coverage.run]
110+
branch = true
111+
source = ["mockprock"]
112+
omit = [
113+
"*/tests/*",
114+
"*/__pycache__/*",
115+
]
116+
117+
[tool.coverage.report]
118+
exclude_lines = [
119+
"pragma: no cover",
120+
"def __repr__",
121+
"raise AssertionError",
122+
"raise NotImplementedError",
123+
"if __name__ == .__main__.:",
124+
"if TYPE_CHECKING:",
125+
]
126+
show_missing = true
127+
128+
[tool.coverage.html]
129+
directory = "htmlcov"
130+

0 commit comments

Comments
 (0)