agentsclimarketplace

Python code

Skill tripcher/skills/skills/engineering/python-code

A personal, growing collection of agent skills for coding agents (Claude Code, Codex, ...).

Install
npx -y skills add tripcher/skills --skill python-code

Assembled 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

Guidance for writing, reviewing, and refactoring Python code with clear style, naming, design principles, and testing discipline. Use when you write Python modules, scripts, packages, tests, refactors Python code, or reviews Python implementation quality.

SKILL.md

13.6 KB, as published. Nobody here has run it

Python Code

Use this skill when producing or changing Python code. Prefer the existing project conventions first; apply these rules where the project is silent.

Style

  • Use PEP 8 style guidelines
  • Use PEP 257 – Docstring Conventions
  • Always use mypy with strict mode
  • Always use mypy stubs for third-party libraries
  • Always use ruff for code linting
  • Always use ruff for code formatting
  • Always use isort for imports sorting

Ruff

extend-select = [
    "F",        # Pyflakes rules
    "W",        # PyCodeStyle warnings
    "E",        # PyCodeStyle errors
    "I",        # Sort imports properly
    "S",        # Enforce bandit rules
    "G",        # Validate (lack of) logging format strings
    "B",        # Finding likely bugs and design problems in your program
    "A",        # Check for python builtins being used as variables or parameters
    "Q",        # Check quotes
    "N",        # PEP8 naming conventions
    "UP",       # Warn if certain things can changed due to newer Python versions
    "C4",       # Catch incorrect use of comprehensions, dict, list, etc
    "FA",       # Enforce from __future__ import annotations
    "ISC",      # Good use of string concatenation
    "ICN",      # Use common import conventions
    "RET",      # Good return practices
    "SIM",      # Common simplification rules
    "TID",      # Some good import practices
    "TC",       # Enforce importing certain types in a TYPE_CHECKING block
    "PTH",      # Use pathlib instead of os.path
    "TD",       # Be diligent with TODO comments
    "NPY",      # Some numpy-specific things
    "FURB",     # Suggest more idiomatic Python patterns
    "ANN",      # Enforce type annotations
    "BLE",      # Avoid blind exception
    "COM",      # Avoid common mistakes
    "DTZ",      # Ban the usage of unsafe naive datetime class
    "EM",       # Helps format nice error messages
    "LOG",      # Checks for issues using the standard library logging module
    "T20",      # Check for Print statements in python files
    "PT",       # Checking common style issues or inconsistencies with pytest-based tests
    "ARG",      # Checks for unused function arguments
    "C90",      # Enable mccabe
    "RUF",      # Enable ruff rules
]

# Required when using `ruff format`; these rules conflict with the formatter.
ignore = [
    "W191",    # Conflicts with formatter indentation
    "E111",    # Conflicts with formatter indentation
    "E114",    # Conflicts with formatter indentation
    "E117",    # Conflicts with formatter indentation
    "Q000",    # Configure quotes via [tool.ruff.format] instead
    "Q001",    # Configure quotes via [tool.ruff.format] instead
    "Q002",    # Configure quotes via [tool.ruff.format] instead
    "Q003",    # Configure quotes via [tool.ruff.format] instead
    "Q004",    # Configure quotes via [tool.ruff.format] instead
    "COM812",  # Conflicts with formatter trailing-comma behavior
    "COM819",  # Conflicts with formatter trailing-comma behavior
]

Philosophy

  • Use PEP 20 – The Zen of Python.
  • The general idea for separation of concerns.
  • The best components are those that provide powerful functionality yet have a simple interface.
  • A module should be responsible to one, and only one, user or stakeholder.
  • A little copying is better than a little dependency.
  • Always try to reduce a cognitive load.
  • Code should be structured and predictable. Recurring tasks should be solved using the same pattern, adding the same layers, directories, files, and functions (creating an API, creating a CLI command, etc.).

Naming

  1. Is the function a test? -> test_<entity>_<behavior>.
  2. Does the function has a @property decorator? -> don't use a verb in the function name.
  3. Does the function use a disk or a network: 3.1. … to store data? -> save_to, send, write_to 3.2. … to receive data? -> fetch, load, read
  4. Does the function output any data? -> print, output
  5. Returns boolean value? -> is_, has_/have_, can_, check_if_<entity>_<characteristic>
  6. Aggregates data? -> calculate, extract, analyze
  7. Put data from one form to another: 7.1. Creates a single meaningful object? -> create 7.2. Fills an existing object with data? -> initialize, configure 7.3. Clean raw data? -> clean 7.4. Receive a string as input? -> parse 7.5. Return a string as output? -> render 7.6. Return an iterator as output? ->iter 7.7. Mutates its arguments or some global state? -> update, mutate, add, remove, insert, set 7.8. Return a list of errors? -> validate 7.9. Checks data items recursively? -> walk 7.10. Finds appropriate item in data? -> find, search, match 7.11. Transform data type? -> <something>to<something_else> 7.12. None of the above, but still works with data? -> Check one of those: morph, compose, prepare, extract, generate, initialize, filter, map, aggregate, export, import, normalize, calculate .

Principles

Prefer LBYL for routine branching when the precondition is cheap and precise.

LBYL means validating a known condition before doing the work. EAFP means executing the operation and handling the failure. Use LBYL for normal in-memory branching when the check is cheap and accurate. Use EAFP when the operation itself is the only reliable check, or when translating low-level failures at an application boundary.

# CORRECT: branch on explicit state
if user_id in users_by_id:
    user = users_by_id[user_id]
    send_welcome_email(user)
else:
    mark_unknown_user(user_id)

# CORRECT: use .get() when a default is real domain behavior
timeout = settings.get("timeout_seconds", 30)
run_job(timeout=timeout)

# WRONG: KeyError is not a business branch
try:
    user = users_by_id[user_id]
except KeyError:
    mark_unknown_user(user_id)

# CORRECT: translate boundary failures once, near the CLI/API edge
try:
    publish_report(report_id)
except StorageError as exc:
    raise click.ClickException(f"Could not publish report {report_id}: {exc}") from exc

Use .exists() when filesystem presence is part of your requirement

from pathlib import Path

# CORRECT: skip optional files that are not present
for config_path in candidate_configs:
    config_path = config_path.expanduser()
    if not config_path.exists():
        continue
    load_config(config_path)

# CORRECT: require the file to exist when missing input is an error
template_path = Path("templates/invoice.html").resolve(strict=True)

# WRONG: broad exception handling hides unrelated filesystem problems
for config_path in candidate_configs:
    try:
        load_config(config_path)
    except OSError:
        continue

Always Use Pathlib (Never os.path)

from pathlib import Path

# CORRECT: build and use a path as a Path
cache_dir = Path.home() / ".cache" / "invoice-tool"
cache_file = cache_dir / "latest.json"
payload = cache_file.read_text(encoding="utf-8")

# WRONG: string path composition is harder to read and refactor
import os.path

cache_file = os.path.join(os.path.expanduser("~"), ".cache", "invoice-tool", "latest.json")
with open(cache_file, encoding="utf-8") as file:
    payload = file.read()

ALWAYS place imports at module level and use absolute imports only

from pathlib import Path

from billing.config import load_settings
from billing.rendering import render_invoice


def build_invoice(invoice_path: Path) -> str:
    settings = load_settings()
    return render_invoice(invoice_path, settings=settings)


# WRONG: dependency is hidden inside the function
def build_invoice_with_hidden_import(invoice_path: Path) -> str:
    from .config import load_settings

    settings = load_settings()
    return render_invoice(invoice_path, settings=settings)

Properties Must Be O(1)

class Report:
    def __init__(self, rows: list[Row]) -> None:
        self._rows = rows

    @property
    def row_count(self) -> int:
        return len(self._rows)


class RemoteReport:
    # CORRECT: method name makes latency visible to the caller
    def fetch_row_count(self) -> int:
        return self._client.count_rows(self.report_id)

    # WRONG: property hides a network request
    @property
    def row_count(self) -> int:
        return self._client.count_rows(self.report_id)

ALWAYS use keyword-only arguments

Exceptions:

  • self - always positional.
  • ctx / context objects - may remain positional as the first parameter.
  • ABC/Protocol methods - may keep framework-compatible signatures.
def export_orders(
    *,
    output_path: Path,
    include_archived: bool,
    batch_size: int,
) -> None:
    write_orders(output_path, include_archived=include_archived, batch_size=batch_size)


# CORRECT: the call documents intent
export_orders(output_path=Path("orders.csv"), include_archived=False, batch_size=500)

# WRONG: boolean and number meaning is invisible at the call site
export_orders(Path("orders.csv"), False, 500)

Prefer modules and functions instead of classes and objects

Create classes only when the code needs identity, lifecycle, shared state, polymorphism, or an interface boundary. For stateless transformations, use functions in a clear module.

Exceptions:

  • Use ABCs or Protocols for repository, strategy, adapter, singleton, or similar boundaries.
# CORRECT: stateless behavior as functions
def calculate_invoice_total(lines: list[InvoiceLine]) -> Decimal:
    return sum((line.quantity * line.unit_price for line in lines), Decimal("0"))


# CORRECT: class owns a dependency and represents a boundary
class InvoiceRepository(Protocol):
    def save(self, invoice: Invoice) -> None: ...


# WRONG: empty class used as a namespace
class InvoiceCalculator:
    def calculate_total(self, lines: list[InvoiceLine]) -> Decimal:
        return sum((line.quantity * line.unit_price for line in lines), Decimal("0"))

ALWAYS use typing annotations, avoid Any if possible

# CORRECT: type annotations clarify intent and prevent bugs
def parse_invoice(raw_invoice: Mapping[str, object]) -> Invoice:
    invoice_id = require_str(raw_invoice, "id")
    total = require_decimal(raw_invoice, "total")
    return Invoice(id=invoice_id, total=total)


# WRONG: Any spreads uncertainty through the codebase
def parse_invoice_untyped(raw_invoice: Any) -> Any:
    return {"id": raw_invoice["id"], "total": raw_invoice["total"]}

ALWAYS use pydantic for data classes

# CORRECT: use pydantic for data classes and validation
from pydantic import BaseModel, Field


class CreateInvoiceRequest(BaseModel):
    customer_id: str
    amount_cents: int = Field(gt=0)
    currency: str = Field(min_length=3, max_length=3)


request = CreateInvoiceRequest.model_validate(payload)


# WRONG: unvalidated external data copied into a dataclass
@dataclass
class RawCreateInvoiceRequest:
    customer_id: str
    amount_cents: int
    currency: str

ALWAYS write Pure Functions

# CORRECT: pure functions are easy to test and reason about
def apply_discount(total: Decimal, percent: Decimal) -> Decimal:
    discount = total * percent / Decimal("100")
    return total - discount
    
# WRONG: side effects are hard to test and reason about
def charge_invoice(invoice_id: str, gateway: PaymentGateway) -> None:
    invoice = load_invoice(invoice_id)
    amount = apply_discount(invoice.total, invoice.discount_percent)
    gateway.charge(invoice.customer_id, amount)


# WRONG: calculation reads global state and performs I/O
def apply_discount_from_storage(invoice_id: str) -> Decimal:
    invoice = load_invoice(invoice_id)
    return invoice.total - invoice.total * settings.discount_percent / Decimal("100")

# CORRECT: pure code
all_invoices = []
invoice = load_invoice(invoice_id)
all_invoices.append(invoice)

# WRONG: side effects are hard to reason about
all_invoices = []
def add_available_invoices(invoices: list[Invoice], invoice_id: str) -> None:
    invoice = load_invoice(invoice_id)
    invoices.append(invoice)

Use f-strings for string formatting or .format in challenging cases

message = f"Invoice {invoice.id} was sent to {invoice.email}"

template = "Invoice {invoice_id} was sent to {email}"
message = template.format(invoice_id=invoice.id, email=invoice.email)

# WRONG: percent formatting is harder to read and easy to mismatch
message = "Invoice %s was sent to %s" % (invoice.id, invoice.email)

Testing

  • Always use pytest, pytest-cov, pytest-mock, pytest-factoryboy, pytest-freezegun, pytest-dotenv, pytest-randomly pytest-socket
  • Use factories, fixtures, faker to remove duplication, but keep each test readable on its own.
  • Use pytest_plugins to include factories and fixtures in the conftest.py file.
  • Avoid real network calls, clocks, randomness, and filesystem dependence unless the test is explicitly integration-level.

Structure

Split tests depending on the type of code they represent.

The file structure usually looks like this:

project_name ├── app_name │ ├── init.py │ └── tests │ ├── init.py │ ├── factories.py │ ├── fixturies.py │ ├── conftest.py │ ├── models │ │ └── init.py │ │ └── test_some_model_file_name.py │ ├── selectors │ │ └── init.py │ │ └── test_some_selector_file_name.py │ └── services │ ├── init.py │ └── test_some_service_file_name.py └── init.py

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.