Python anti patterns
Skill JoseVelazcoH/python-skills/skills/python-anti-patterns
Claude Code Python skills that improve how you write Python: clean code, design, and testing, enforced by a pre-commit review.
npx -y skills add JoseVelazcoH/python-skills --skill python-anti-patternsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Trigger: anti-patterns, import order, file too long, split module, unrelated functions, hardcoded values, magic values, module constants, extract constants, future annotations import. Enforce battle-tested Python module-organization rules.
The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
4.7 KB, as published. Nobody here has run it
Python Anti-Patterns
Prescriptive module-organization rules learned in practice. These are enforced engineering standards, not style preferences: apply them on every Python file touched.
Activation Contract
Apply when writing or reviewing any Python module: checking import order, file size, module cohesion, hardcoded values, or where constants live. Flag every violation below; do not wait to be asked.
Hard Rules
- Import order (custom convention): first all
import xstatements (alphabetical), thenfrom x import ...for stdlib/third-party, then a blank line, then first-partyfrom core...imports. No blank line between theimportblock and the non-localfromblock. Seereferences/import-order.md. NOTE: ruff's isort (I) rule reverts this: disableIin the linter config or it overwrites the skill. - No reflexive
from __future__ import annotations: do not add it by default; in most modules it is noise. Keep it ONLY when load-bearing: annotations that referenceTYPE_CHECKING-guarded imports (to break import cycles) or forward references you would otherwise have to quote. Remove it everywhere else. - File length: ~300 lines is a hard smell. Split by responsibility before that. A long file almost always hides multiple concerns.
- Module cohesion: functions with no relationship to the module's purpose must be extracted to their own module. One module = one cohesive concern.
- No hardcoded values: never inline literals (URLs, paths, thresholds, column names, magic numbers/strings) in logic. Name them.
- Separate constants from logic (discriminant): domain/config constants (geometry, thresholds, URLs, column names, labels) must NOT sit atop a logic module, even if few or single-use. Move them to a dedicated
constants.py, or to aconstants/subpackage with one module per category (constants/layout.py,constants/routing.py) when they are many or span categories. EXCEPTION: a value meaningful only inside one algorithm (a private sentinel, an internal state marker) stays local: model it as a localEnumor a_privateconstant in that module, never hoisted to the shared constants surface. The deciding test: would this constant mean anything to another module? Yes, centralize it. No (algorithm-internal), keep it local and prefer anEnum.
Decision Gates
| Symptom | Fix |
|---|---|
| Imports mixed/misordered | Reorder per the custom convention above |
from __future__ import annotations with no TYPE_CHECKING/forward-ref need | Remove it |
| File approaching ~300 lines | Split by responsibility into separate modules |
| Function unrelated to module purpose | Extract to its own module |
| Literal inside logic | Replace with a named constant |
| Domain/config constant atop a logic module | Move to constants.py (or constants/<category>.py), import it |
| Many constants spanning categories | constants/ subpackage, one module per category |
| Private algorithm-internal value (sentinel/state) | Keep local; prefer an Enum over a bare string |
Execution Steps
- Scan the module against each gate; list every hit with
file:line. - Fix imports first (cheap, mechanical), then move domain/config constants to
constants.py(or aconstants/<category>.pysubpackage), keeping algorithm-internal values local, then split oversized/incohesive files. - Replace each hardcoded literal with an imported named constant.
- Confirm each remaining module has a single cohesive concern.
# Bad: hardcoded + local constant + mixed imports
from core.utils.logger import get_logger
import requests
TIMEOUT = 30
def fetch(): requests.get("https://api.inegi.org.mx/data", timeout=TIMEOUT)
# Good: named, centralized, ordered
# constants.py
INEGI_DATA_URL = "https://api.inegi.org.mx/data"
REQUEST_TIMEOUT_SECONDS = 30
# module.py
import requests
from core.constants import INEGI_DATA_URL, REQUEST_TIMEOUT_SECONDS
from core.utils.logger import get_logger
def fetch():
return requests.get(INEGI_DATA_URL, timeout=REQUEST_TIMEOUT_SECONDS)
Output Contract
Return the corrected module(s) with imports reordered, domain/config constants moved to constants.py (or a constants/<category>.py subpackage) while algorithm-internal values stay local as Enums, hardcoded values named, and oversized/incohesive files split. Cite each violation by file:line.
References
references/import-order.md: the custom import-ordering convention with full examples.