| name | find-unused-cython-imports |
| description | Find and remove unused imports/cimports in xpra's Cython .pyx/.pxd files, which ruff and flake8 do not check. Use when asked to find or remove unused imports (especially in .pyx/.pxd/Cython files), clean up imports codebase-wide, or "do more like <commit that removed unused imports>". For pure-Python .py files, use `ruff check --select F401` instead. |
find-unused-cython-imports
ruff/flake8 only lint .py files, so unused import/cimport statements in xpra's ~117 .pyx and ~32 .pxd Cython files go undetected. This skill finds them with a bundled scanner and — crucially — verifies every removal by transpiling with cython, which does full name resolution without needing any native libraries.
Bundled scripts (in this skill's directory):
find_unused_cimports.py — detector (heuristic).
rewrite.py — removes named imports from statements (single-line + multi-line paren blocks), then you re-verify.
First: the two traps that cause false positives
A naive "does the name appear elsewhere?" check is wrong in two ways here. The bundled scanner already handles both — do not reimplement the check without them:
# inside a string literal is not a comment. Log lines like
log("resource %#x freed", <uintptr_t> ptr) contain # inside "%#x".
Splitting the line on # hides the real <uintptr_t> usage after it, so the
type looks unused when it is not. Truncate a line at # only when the # is
outside quotes.
- A
.pxd shares its namespace with the companion .pyx. A name cimported
in foo.pxd may be used only in foo.pyx (which relies on it instead of
self-importing). Removing it from the .pxd breaks the build. Count
non-import usage in the companion .pyx too, and also check that no other
module does from xpra.<this_module> cimport <name> (re-export).
The verification oracle
cython transpilation (.pyx → .c) resolves every C-level name and errors
on a wrongly-removed cimport ('<name>' is not a type identifier,
undeclared name, …). It does not need the native libs, so it works even for
nvenc / amf / vpx / avif / wayland files:
cython -X language_level=3 -I . <file>.pyx -o /tmp/out.c
Transpilation does not validate runtime Python imports — an undefined
Python name only raises NameError at runtime, not at transpile time. So Python
imports are covered by the scanner's static token scan, not by transpilation.
Workflow
Run from the repo root.
1. Baseline — confirm each candidate file transpiles cleanly before editing
SKILL=.claude/skills/find-unused-cython-imports
TSV=1 python3 $SKILL/find_unused_cimports.py xpra > /tmp/candidates.tsv
cut -f1 /tmp/candidates.tsv | sort -u | while read f; do
[ "${f##*.}" = pyx ] || continue
cython -X language_level=3 -I . "$f" -o /tmp/_b.c >/dev/null 2>&1 || echo "PRE-FAIL $f"
done
Any file that already fails to transpile can't be used as an oracle — set it aside and inspect by hand.
2. Review the candidate list
Skim /tmp/candidates.tsv. Delete any rows you want to keep (e.g. an import
kept deliberately for a side effect, or one you're unsure about). The scanner is
a heuristic; you are the gate.
3. Remove
python3 $SKILL/rewrite.py /tmp/candidates.tsv
4. Verify — transpile every edited .pyx, and every consumer of an edited .pxd
for f in $(git diff --name-only -- '*.pyx'); do
cython -X language_level=3 -I . "$f" -o /tmp/_v.c >/tmp/err.txt 2>&1 \
|| { echo "FAIL $f"; tail -5 /tmp/err.txt; }
done
A .pxd can't be transpiled alone: transpile the .pyx files in its module
(its companion .pyx and any file that cimports from it). If a file fails,
the removed name was actually used — git checkout -- <file> it and drop that
row.
Independently confirm the Python-level imports (not covered by transpile): every
removed name should have zero non-import, comment-stripped occurrences in its
edited file. Re-running find_unused_cimports.py on the edited tree should
report 0 candidate unused imports (idempotent).
5. Tidy & commit
Whole-line removals can leave a doubled blank line; collapse any blank run your
edit newly created (vs HEAD) down to one. Then confirm scope and commit
straight to master (this repo's convention — no throw-away branch):
ruff check ./xpra --ignore E902 --ignore E501
git diff --name-only | grep -v '\.pyx$\|\.pxd$'
git add -- '*.pyx' '*.pxd' && git commit
Notes
- The scanner keys "used" on the bound local name (respects
import x as y).
- Multi-line parenthesised
cimport (...) blocks and \-continued lines are
parsed as one statement.
- Names appearing only inside a
#-comment or a string literal count as not
used for a comment but as used for a string (conservative — avoids removing
something a string references). A name used only in a commented-out line is
therefore reported as unused; that's usually correct (the code is dead), but
eyeball it.