agentsclimarketplace

Py anti patterns

Skill CodeSigils/py-review-skill/skills/py-anti-patterns

Portable Python code-review skills for agentskills.io-compatible agents — router plus focused skills for type safety, error handling, anti-patterns, async, and code style

Install
npx -y skills add CodeSigils/py-review-skill --skill py-anti-patterns

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

3 things to look at

  • 29 days oldThe repository was created 29 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 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

Review Python code for common correctness and maintainability anti-patterns including hard-coded configuration, mixed I/O and business logic, leaked internal models, scattered retries, mutable defaults, and resource misuse. Use as a focused checklist during Python review.

SKILL.md

5.1 KB, as published. Nobody here has run it

Python Anti-Pattern Review

Use these rules as a correctness-first checklist. Do not flag broad architecture preferences unless the changed code creates a concrete maintenance or behavior risk.

Freshness: stable (no external references) — review rules based on core Python conventions, not volatile APIs.

Review Rules

Rule: anti-hard-coded-config

Impact: HIGH Applies when: Code adds endpoints, credentials, filesystem paths, timeouts, feature flags, or environment-specific values. Skip when: The value is a harmless local constant or test fixture. Python: any Tools: none Review signal: Production configuration or secrets are hard-coded in module globals or functions.

Incorrect:

API_KEY = "sk-live-example"
DB_HOST = "prod-db.example.com"

Correct:

class Settings(BaseSettings):
    api_key: str = Field(alias="API_KEY")
    db_host: str = Field(alias="DB_HOST")

Reason: Hard-coded environment values make deployments brittle and can leak secrets.

Rule: anti-mixed-io-business-logic

Impact: MEDIUM-HIGH Applies when: Business decisions are added near SQL, HTTP calls, filesystem reads, or ORM queries. Skip when: The function is a thin adapter whose only job is I/O orchestration. Python: any Tools: none Review signal: A function both fetches raw data and implements domain decisions that should be testable independently.

Incorrect:

def calculate_discount(user_id: str) -> float:
    orders = db.query("SELECT * FROM orders WHERE user_id = ?", user_id)
    return 0.15 if len(orders) > 10 else 0.0

Correct:

def calculate_discount(orders: Sequence[Order]) -> float:
    return 0.15 if len(orders) > 10 else 0.0

Reason: Separating I/O from business logic makes behavior easier to test and reduces hidden coupling.

Rule: anti-expose-internal-model

Impact: MEDIUM-HIGH Applies when: API, serialization, or package boundaries return ORM models, protobuf internals, or persistence objects. Skip when: The boundary is internal and consumers are explicitly coupled to that model. Python: any Tools: none Review signal: Handler or public method returns a database model directly.

Incorrect:

@app.get("/users/{user_id}")
def get_user(user_id: str) -> UserModel:
    return session.get(UserModel, user_id)

Correct:

@app.get("/users/{user_id}")
def get_user(user_id: str) -> UserResponse:
    user = session.get(UserModel, user_id)
    return UserResponse.model_validate(user)

Reason: Exposing internal models couples clients to storage details and can leak fields unintentionally.

Rule: anti-scattered-retry-timeout

Impact: MEDIUM-HIGH Applies when: Network/database calls add custom retries, timeouts, or backoff behavior. Skip when: The code is the single shared client wrapper for that service. Python: any Tools: none Review signal: Similar timeout/retry logic appears in multiple call sites, or retries exist at multiple layers.

Incorrect:

def fetch_user(user_id: str) -> Response:
    for _ in range(3):
        try:
            return requests.get(url, timeout=30)
        except Timeout:
            continue

Correct:

@retry(stop=stop_after_attempt(3), wait=wait_exponential())
def http_get(url: str) -> Response:
    return requests.get(url, timeout=30)

Reason: Scattered retry behavior creates inconsistent failure semantics and can accidentally multiply retries.

Rule: anti-mutable-default

Impact: HIGH Applies when: A function or method default value is a mutable object. Skip when: The object is intentionally immutable despite its type, which should be rare and documented. Python: any Tools: ruff | project-configured Review signal: Defaults such as [], {}, set(), or model instances appear in function signatures.

Incorrect:

def add_tag(tag: str, tags: list[str] = []) -> list[str]:
    tags.append(tag)
    return tags

Correct:

def add_tag(tag: str, tags: list[str] | None = None) -> list[str]:
    result = [] if tags is None else list(tags)
    result.append(tag)
    return result

Reason: Mutable defaults are shared across calls and can leak state between independent invocations.

Sensitive Evidence Safety

If changed code or tool output reveals a suspected credential, token, private key, secret-bearing URL, or other sensitive value, do not quote or reproduce the value. Report only its existence and location. Treat filename and pattern checks as heuristic evidence, not proof that a repository is secret-free.

If the exposure appears credible, make it the first finding, stop lower-priority review, and recommend revocation or rotation. Never place sensitive values in reports, generated examples, or commit subjects or bodies.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.