Fast Python linter for catching LLM-generated anti-patterns
Project description
slopcop
A fast, opinionated Python linter written in Rust that catches anti-patterns commonly produced by language models.
Built on tree-sitter for AST-correct analysis — no false positives on strings or comments.
Install
pip install slopcop
# or
uv tool install slopcop
Or from source:
cargo install --git https://github.com/cm2435/slopcop
Usage
# Lint directories (walks recursively for .py files)
slopcop src/ tests/
# Lint specific files
slopcop path/to/file.py
# Quiet mode (exit code only, for CI)
slopcop --quiet src/
# JSON output
slopcop --format json src/
# Only fail on errors, treat warnings as non-blocking
slopcop --warn-only src/
Exit codes: 0 = clean, 1 = violations found, 2 = fatal error.
Rules
All rules are enabled by default. Disable per-project via pyproject.toml.
| Rule | What it catches |
|---|---|
no-hasattr-getattr |
hasattr() and getattr() calls — use explicit attribute checks or protocols |
guarded-function-import |
Function-scope import without a comment on the line above explaining why |
no-future-annotations |
from __future__ import annotations — unnecessary on 3.13+ and breaks runtime inspection |
no-dataclass |
@dataclass usage and dataclasses imports — use Pydantic or project-standard models |
no-bare-except |
except: without a type — catches everything including KeyboardInterrupt |
no-broad-except |
except Exception: / except BaseException: — too broad, catch specific types |
no-pass-except |
except blocks containing only pass — silently swallows exceptions |
no-nested-try |
Nested try blocks — extract the inner try into a separate function |
no-async-from-sync |
asyncio.run() / get_event_loop() / run_until_complete() / ensure_future() / create_task() inside a sync function — make the caller async def or move the sync/async boundary to an entrypoint |
no-print |
print() calls — use structured logging |
no-todo-comment |
TODO, FIXME, HACK, XXX comments — resolve or track in an issue |
no-assert |
assert in production code — use if not ...: raise ValueError(...) instead |
no-typing-any |
Any in type annotations — use specific types or protocols |
no-str-empty-default |
str = "" defaults on params and model fields — use str | None = None or make required |
no-boolean-positional |
Bare True/False as positional arguments — use keyword arguments for clarity |
no-redundant-none-check |
x is None when x is typed as non-optional |
no-or-empty-coalesce |
obj.attr or {} / or [] / or "" etc. — check is None explicitly or remove dead fallback |
max-function-params |
Functions with more than 8 parameters (configurable) — group into a model |
Configuration
Add [tool.slopcop] to your pyproject.toml:
[tool.slopcop]
exclude = [
"no-dataclass", # this project uses dataclasses
"no-print", # CLI app, print is fine
]
Per-file ignores
Disable rules for specific file patterns:
[tool.slopcop.per-file-ignores]
"tests/**" = ["no-print"]
"**/cli/**" = ["no-print"]
Rule-specific config
[tool.slopcop.rules.max-function-params]
max = 10
slopcop walks upward from the target path to find the nearest pyproject.toml.
Inline suppression
x = getattr(obj, name) # slopcop: ignore
x = getattr(obj, name) # slopcop: ignore[no-hasattr-getattr]
x = getattr(obj, name) # slopcop: ignore[no-hasattr-getattr, no-print]
Adding to CI
# GitHub Actions
- run: pip install slopcop
- run: slopcop src/ tests/
Development
cargo test # run the test suite
cargo run -- src/ # run locally
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file slopcop-0.1.1.tar.gz.
File metadata
- Download URL: slopcop-0.1.1.tar.gz
- Upload date:
- Size: 40.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8698297781af5d46e94557a17c0bb61f70f5186ec99b9478b3f07e3fffd5a9ee
|
|
| MD5 |
eed0f11086b99e708412582e3a60d4f7
|
|
| BLAKE2b-256 |
cbb253cd4ba6b13ff42214d82ff47d4464c1fae63ed496d7d1352e1b8aa74f86
|
File details
Details for the file slopcop-0.1.1-py3-none-win_amd64.whl.
File metadata
- Download URL: slopcop-0.1.1-py3-none-win_amd64.whl
- Upload date:
- Size: 1.4 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b069a522d583ea082a4c6b05341483557dc8d276fce1068e681b81fe97f8f669
|
|
| MD5 |
79da1ab0b136c73d10631e0e757a82b4
|
|
| BLAKE2b-256 |
e417434f028f789a86a7c807c5131ec286b98c001b39159fcbe5979a36568ee4
|
File details
Details for the file slopcop-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: slopcop-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.8 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b91c0ecfde8e87d6247bdd0eabacbae0b92cad6b996725f1023378623cffae53
|
|
| MD5 |
3c19e74d2593a4fc4d0b45c3ad9ceee8
|
|
| BLAKE2b-256 |
18bf6408ceeafdc9759ac353c9ebf177ff68754f28f93ea6d42172b6a5935e83
|
File details
Details for the file slopcop-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: slopcop-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.7 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee9e512ff1b6008741472481a183ed56e7993c55ab73b72beaa7eccb4576e1bd
|
|
| MD5 |
0ed4b9d1cf120eceb59f6454681565c9
|
|
| BLAKE2b-256 |
4af529837ba662834c38954de467bfc54cd3c99b38667ff8424850a536e5f8e9
|
File details
Details for the file slopcop-0.1.1-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: slopcop-0.1.1-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.6 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f047907bc98a87c9c85bda5ba39bdda2b0f4013f82765a1a73357134bbe1086
|
|
| MD5 |
406749e846df0943cd5dc1dc27568e29
|
|
| BLAKE2b-256 |
0b9e4d17525f48a487a60dfb5f028bdff8103a0c98d711c7dc17cf1b980660f7
|
File details
Details for the file slopcop-0.1.1-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: slopcop-0.1.1-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.7 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25d8bdf1ac5f52f32123cf32db298e9f95e68d1dc637cdf2ccb9f0aec2fd3a57
|
|
| MD5 |
fabba037acc102e551f5021891574c44
|
|
| BLAKE2b-256 |
e47b2933a6205f72ccbdf94c93c878122b6a0e91eb0751d2157658a66224d290
|