agentleFS
MuvonMuvon/octomind-tap/skills/programming-python/SKILL.md

programming-python

Skill6 starsChanged 8 months agoApache-2.0View on GitHub

Python practices: architecture, type-driven design, boundary validation, library choices beyond scripts. Use when writing or reviewing Python projects.

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 2 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use dataclasses for records.

    line 43
  2. Very specific:

    Use an explicit is None check when zero, False, or an empty collection is valid.

    line 45
  3. Distinctive:

    Don't replace missing required configuration, failed I/O, or invalid input with defaults.

    line 50
  4. Very specific:

    Use with/async with for resources and ExitStack for dynamic groups.

    line 51
  5. Very specific:

    Keep imports free of heavyweight work and mutable global configuration.

    line 52
  6. Distinctive:

    Use async I/O for concurrent awaitable operations and threads for blocking I/O.

    line 57
  7. Very specific:

    Keep blocking work off the event loop with appropriate executors or to_thread.

    line 60

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Overview

Write Python with clear data contracts, deliberate effects, and predictable failure behavior. As of 2026-10: Python 3.15 is the newest stable release (2026-10-09), 3.14 is in bugfix, and 3.10 reached end of life on 2026-10-01. Read requires-python, environment pins, dependency lockfiles, type-checker settings, and CI first. Use features supported by every required interpreter; don't raise the minimum version or replace the project's tooling during unrelated work. Recheck official releases when updating this guidance.

Mental model

Annotations describe a contract; validation enforces it. Keep boundary parsing explicit, represent trusted data with small types, and make ownership of mutable state and resources visible. A function or module is enough until a class or abstraction solves a concrete lifecycle or substitution problem.

Recent features and migration traps

VersionUseful change and boundary
3.11TaskGroup, exception groups/except*, and asyncio.timeout support structured concurrent failure handling.
3.12type Alias = ... and type-parameter syntax (def first[T](...)) simplify typed APIs; older interpreters cannot parse them.
3.13TypeIs supports narrowing both branches; use it only when its condition exactly identifies the claimed type.
3.14Annotations are deferred by default; annotationlib supports introspection. T-strings produce Template objects, and free-threaded builds are officially supported.
3.15lazy import / lazy from ... import at module scope (PEP 810), built-in frozendict (PEP 814) and sentinel (PEP 661), unpacking in comprehensions ([*xs for xs in groups]), TaskGroup.cancel(), TypedDict extra_items (PEP 728), and the profiling.sampling profiler that attaches to a running PID. I/O defaults to UTF-8 regardless of locale (PEP 686).

Don't assume annotation values are eagerly evaluated or all strings. Use typing.get_type_hints when evaluated types are needed, or appropriate annotationlib formats for introspection; evaluating annotations can execute code. T-strings preserve literal and interpolated parts for a processor: they do not automatically escape HTML or parameterize SQL, and they are not interchangeable with str.

Lazy imports defer import errors and import-time side effects to first use; don't make a module lazy when its import registers plugins or must fail fast at startup. frozendict is not a dict subclass, so isinstance(x, dict) checks miss it; check collections.abc.Mapping where both are valid. The UTF-8 default changes behavior on Windows and non-UTF-8 locales; keep passing encoding= explicitly in code that supports older interpreters.

Types and data

  • Annotate public boundaries and non-obvious internal contracts; use list[T], dict[K, V], and T | None on supported versions. Use object for unknown data that must be narrowed; isolate necessary Any at untyped integration points.
  • TypedDict describes dictionary shape without runtime validation. Protocol describes structural behavior; a runtime-checkable protocol does not verify method signatures or semantic correctness.
  • Use dataclasses for records; choose frozen=True when reassignment is unwanted and slots=True when its restrictions fit. Frozen fields do not freeze nested lists or dictionaries. Use default_factory for mutable defaults.
  • Validate untrusted values once at entry and pass trusted values inward. Choose strict validation or explicit coercion deliberately; don't let a serializer or modeling library quietly change the input contract.
  • Use an explicit is None check when zero, False, or an empty collection is valid. Truthiness-based defaults can erase meaningful input.

Errors, resources, and module design

  • Catch specific failures close to the operation that can recover. A top-level handler may catch broadly to report failure, but should not pretend success. Add a domain exception when callers need that distinction; preserve causes with raise ... from ....
  • Don't replace missing required configuration, failed I/O, or invalid input with defaults. Suppress only a named, expected failure whose absence is part of the contract. Keep sensitive input out of exception messages and logs.
  • Use with/async with for resources and ExitStack for dynamic groups. Make cleanup observable where failure matters; finalizers and garbage collection do not guarantee timely cleanup.
  • Keep imports free of heavyweight work and mutable global configuration. Public submodules are valid APIs; re-exporting everything from __init__.py is unnecessary and can introduce cycles.
  • Use pyproject.toml for modern package metadata and [dependency-groups] (PEP 735) for dev/test dependencies. A src/ layout helps test installed-package behavior; flat layouts and requirements files still have valid uses. Preserve the established package/environment tools unless changing them is part of the task. For a new project with no established tooling, uv (uv.lock, uv run) plus Ruff for lint and format is the common default; commit the lockfile for applications.

Concurrency

  • Use async I/O for concurrent awaitable operations and threads for blocking I/O. In a GIL-enabled interpreter, pure-Python CPU work generally needs processes, isolated interpreters, or native code that releases the GIL for parallelism.
  • Free-threaded builds can execute Python threads in parallel, but extensions may re-enable the GIL. Verify runtime and dependency support; protect compound shared mutations with locks rather than relying on container internals.
  • TaskGroup cancels siblings after an ordinary task failure and waits for cleanup. Propagate CancelledError after necessary cleanup; swallowing it can break task groups and timeouts. gather has different failure semantics and remains useful when those semantics are intended.
  • Keep blocking work off the event loop with appropriate executors or to_thread. Bound queued work; cancelling an awaiting coroutine does not necessarily stop a running thread.
  • Python 3.14 no longer defaults to fork on any platform. Make process-pool entry points importable, guard startup with if __name__ == "__main__":, and explicitly choose a multiprocessing context only when required. InterpreterPoolExecutor provides isolated interpreters, not shared mutable globals.

Example

A missing optional value may use a default; an invalid supplied value must fail:

def parse_workers(raw: str | None) -> int:
    if raw is None:
        return 4
    try:
        workers = int(raw)
    except ValueError as exc:
        raise ValueError("worker count must be an integer") from exc
    if workers < 1:
        raise ValueError("worker count must be positive")
    return workers

Checklist

  • Syntax and libraries match the supported Python versions and interpreter build.
  • Types are validated at boundaries; mutable defaults and truthiness don't change meaning.
  • Errors, cleanup, cancellation, and worker shutdown preserve the contract.
  • When authorized, use the project's formatter, linter, type checker, and focused tests. Cover invalid input and concurrent cleanup; report skipped checks without installing missing tools implicitly.

References

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.