From 75fd49a4e4f1ab2fbff20cd0e9234e3d7d057a8b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 17 May 2026 12:29:11 -0700 Subject: [PATCH] Enforce top-level imports via ruff PLC0415 Adds ``PLC0415`` to ``[tool.ruff.lint]`` select. Function-scoped imports must now opt in with ``# noqa: PLC0415`` plus an inline comment justifying the reason. Catches a pattern that LLM contributors frequently introduce. No opt-outs needed in the tree today; the rule is clean against ``ruff check`` as-is. Mirrors the approach taken in yarl PR aio-libs/yarl#1697. --- CHANGES/1349.contrib.rst | 8 ++++++++ pyproject.toml | 6 ++++++ 2 files changed, 14 insertions(+) create mode 100644 CHANGES/1349.contrib.rst diff --git a/CHANGES/1349.contrib.rst b/CHANGES/1349.contrib.rst new file mode 100644 index 000000000..888cb42a4 --- /dev/null +++ b/CHANGES/1349.contrib.rst @@ -0,0 +1,8 @@ +Enabled the ``PLC0415`` (import-outside-top-level) rule in +``[tool.ruff.lint]``. Function-scoped imports must now opt in +with ``# noqa: PLC0415`` plus a comment explaining the reason +(typically avoiding a heavy optional dependency at import time). +This catches a pattern that LLM contributors frequently introduce. +There are currently no opt-outs in the tree, so the rule is +enforced everywhere ``ruff check`` runs +-- by :user:`bdraco`. diff --git a/pyproject.toml b/pyproject.toml index 6d54f4549..6c4826ea6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,12 @@ select = [ # (ruff format) and the import sorter (ruff check --select I) come # from the same tool and rev. "I", + # Imports must live at the top of the module. Late/inside-function + # imports must be opted into explicitly with `# noqa: PLC0415` and a + # comment explaining why (e.g. avoiding a heavy optional dependency + # in the import path). Enforced because AI-assisted contributions + # frequently introduce function-scoped imports that are unnecessary. + "PLC0415", # pyupgrade: enforce modern Python syntax for the current # ``target-version`` (currently py310). "UP",