Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion autodev/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"""


def render_prompt(
def render_prompt( # noqa: PLR0913 the template's seven inputs; a PromptInput would be this signature as a class
cfg: Config, issue: dict, comments: list[dict], branch: str, base_sha: str, pr: int | None, feedback: str | None
) -> str:
"""Fill the prompt template with the issue, the human discussion on it, and any reviewer feedback.
Expand Down
2 changes: 1 addition & 1 deletion autodev/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ async def request(
conditional: bool = False,
) -> httpx.Response | None: ...

async def request(
async def request( # noqa: C901, PLR0913 one retry loop over every request option; splitting it hides the order of checks
self,
method: str,
path: str,
Expand Down
2 changes: 1 addition & 1 deletion autodev/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ async def _run_round(self, feedback: Feedback | None) -> PrRef:
self.workspace = None
return result

async def _watch_pr(self) -> str:
async def _watch_pr(self) -> str: # noqa: C901 the review state machine, one branch per action; kept whole so replay changes are visible
"""Watch the PR until it is merged or closed, running revision rounds and escalations as needed.

The wait between polls is observe_pr's retry interval (the activity fails while there is nothing to
Expand Down
7 changes: 6 additions & 1 deletion docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ Run all of these before pushing. CI runs the last three in this order on every p
| `pixi run test` | pytest over `tests/`, including the Temporal replay tests |

Configuration for all four is in `pyproject.toml`. Keep them clean rather than suppressing: there are no
`type: ignore` or `noqa` comments in the source today, and a new one needs a reason next to it.
`type: ignore` comments in the source today, and a `noqa` needs its reason on the same line.

ruff also enforces size limits: complexity 10 (`C901`), 12 branches, 50 statements, 8 returns and 6 parameters
per function (`PLR09xx`). More than six parameters wants a parameter object (`JobArgs`, `Reviewers`). The nine
functions over the line are marked with a `noqa` saying why they are kept whole; do not add to that list
without the same.

## Layout

Expand Down
2 changes: 1 addition & 1 deletion mia_data/activities.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class Activities:
`bot` is the GitHub login mia-data posts as. `probe` returns the csub policy's allowed_hosts patterns;
it is injectable for tests."""

def __init__(
def __init__( # noqa: PLR0913 the clients the activities need, injected here so tests can fake them
self,
cfg: Config,
gh_data: GitHub,
Expand Down
2 changes: 1 addition & 1 deletion mia_data/binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def record_urls(record: dict) -> list[str]:
]


def check_binding(binding: dict, record: dict, catalog_names: set[str], *, pins: Pins) -> list[str]:
def check_binding(binding: dict, record: dict, catalog_names: set[str], *, pins: Pins) -> list[str]: # noqa: C901 a validator: one branch per rule
"""Errors in an agent-written binding (empty = ok). Rewrites s3:// URLs to https in place.

The binding must name the pinned record and commit, use only snippets from the catalog, and only URLs
Expand Down
2 changes: 1 addition & 1 deletion mia_data/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ async def cmd_init_labels(cfg: Config, args: argparse.Namespace) -> int:
return 0


async def run_test_pr(activities: Activities, pr: int, binding_file: Path, record_id: str) -> int:
async def run_test_pr(activities: Activities, pr: int, binding_file: Path, record_id: str) -> int: # noqa: C901, PLR0912, PLR0915 long but linear: the PR path through the same stages the workflow runs
"""Run the test crops on a snippets PR's head with a binding from disk, synchronously, and post the
`mia-data/crops` status and a result comment on the PR. Returns 0 if the crops passed.

Expand Down
2 changes: 1 addition & 1 deletion mia_data/crop_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def judge(verify: VerifyResult, jobs: list[JobDone]) -> tuple[bool, list[str]]:
return not failed and verify.ok_count > 0 and not verify.errors, failed


async def run_crop_test(
async def run_crop_test( # noqa: PLR0913 keyword-only; the workflow passes the round's state through
activities: Activities,
*,
issue: int,
Expand Down
2 changes: 1 addition & 1 deletion mia_data/jobspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def _parent(file: Path | None) -> Path | None:
return Path(file).parent if file else None


def _spec(
def _spec( # noqa: PLR0913 keyword-only; every job builder is a thin wrapper that fills these in
cfg: Config,
kind: str,
workspace: Path,
Expand Down
2 changes: 1 addition & 1 deletion mia_data/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def _assert_same(dest: Path, files: dict, crop_id: str) -> None:
raise Conflict(f"{crop_id} is already published with different checksums")


def publish(
def publish( # noqa: C901, PLR0912 one pass over the crops with a branch per file outcome; the tests cover each
dataset_dir: Path, src_dir: Path, verified: list[dict], withdrawn: dict[str, str], *, tmp_max_age_s: float
) -> dict:
"""Copy the verified files of each crop from `src_dir` (a crop job's crops/) into `dataset_dir`.
Expand Down
10 changes: 9 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,17 @@ line-length = 120
extend-exclude = ["notes"]

[tool.ruff.lint]
select = ["E", "F", "W", "I", "UP", "B"]
select = ["E", "F", "W", "I", "UP", "B", "C901", "PLR0911", "PLR0912", "PLR0913", "PLR0915", "RUF100"]
ignore = ["E501"] # long lines are reviewed by eye; the renames pushed a few past 120

[tool.ruff.lint.per-file-ignores]
# fake activity dispatchers and fake services are one big switch each; that is the test, not a smell
"tests/*" = ["C901", "PLR0913"]

[tool.ruff.lint.pylint]
max-args = 6 # more than this wants a parameter object (JobArgs, Reviewers)
max-returns = 8 # decide() and _round() return once per outcome

[tool.mypy]
python_version = "3.12"
check_untyped_defs = true
Expand Down
2 changes: 1 addition & 1 deletion tests/test_mia_publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def lockstep(a, b): # both attempts have copied the crop; both now rename it
def run(src, verified):
try:
results.append(publish(ds, src, verified, {}, tmp_max_age_s=AGE))
except Exception as e: # noqa: BLE001
except Exception as e:
errors.append(e)

ts = [threading.Thread(target=run, args=s) for s in srcs]
Expand Down
Loading