From python-plugin
Provides core Python 3.10+ expertise on type hints, pattern matching, async/await, context managers, list comprehensions, and Pythonic idioms/best practices. Use for idiomatic code writing.
npx claudepluginhub laurigates/claude-plugins --plugin python-pluginThis skill is limited to using the following tools:
Core Python language concepts, idioms, and best practices.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Core Python language concepts, idioms, and best practices.
# Modern syntax (Python 3.10+)
def process_items(
items: list[str], # Not List[str]
mapping: dict[str, int], # Not Dict[str, int]
optional: str | None = None, # Not Optional[str]
) -> tuple[bool, str]: # Not Tuple[bool, str]
"""Process items with modern type hints."""
return True, "success"
# Type aliases
type UserId = int
type UserDict = dict[str, str | int]
def get_user(user_id: UserId) -> UserDict:
return {"id": user_id, "name": "Alice"}
def handle_command(command: dict) -> str:
match command:
case {"action": "create", "item": item}:
return f"Creating {item}"
case {"action": "delete", "item": item}:
return f"Deleting {item}"
case {"action": "list"}:
return "Listing items"
case _:
return "Unknown command"
def process_response(response):
match response:
case {"status": 200, "data": data}:
return process_success(data)
case {"status": 404}:
raise NotFoundError()
case {"status": code} if code >= 500:
raise ServerError(code)
# File handling
with open("file.txt") as f:
content = f.read()
# Custom context manager
from contextlib import contextmanager
@contextmanager
def database_connection():
conn = create_connection()
try:
yield conn
finally:
conn.close()
with database_connection() as conn:
conn.execute("SELECT * FROM users")
# List comprehension
squares = [x**2 for x in range(10)]
# Dict comprehension
word_lengths = {word: len(word) for word in ["hello", "world"]}
# Set comprehension
unique_lengths = {len(word) for word in ["hello", "world", "hi"]}
# Generator expression
sum_of_squares = sum(x**2 for x in range(1000000)) # Memory efficient
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# Use generator
fib = fibonacci()
first_ten = [next(fib) for _ in range(10)]
# Generator expression
even_squares = (x**2 for x in range(10) if x % 2 == 0)
import pdb
def problematic_function():
value = calculate()
pdb.set_trace() # Debugger breakpoint
return process(value)
# Debug on error
python -m pdb script.py
# pytest with debugger
uv run pytest --pdb # Drop into pdb on failure
uv run pytest --pdb --pdbcls=IPython.terminal.debugger:TerminalPdb
# CPU profiling
uv run python -m cProfile -s cumtime script.py | head -20
# Line-by-line profiling (temporary dependency)
uv run --with line-profiler kernprof -l -v script.py
# Memory profiling (temporary dependency)
uv run --with memory-profiler python -m memory_profiler script.py
# Real-time profiling (ephemeral tool)
uvx py-spy top -- python script.py
# Quick profiling with scalene
uv run --with scalene python -m scalene script.py
# Trace execution
import sys
def trace_calls(frame, event, arg):
if event == 'call':
print(f"Calling {frame.f_code.co_name}")
return trace_calls
sys.settrace(trace_calls)
# Memory tracking
import tracemalloc
tracemalloc.start()
# ... code to profile
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
for stat in top_stats[:10]:
print(stat)
import asyncio
async def fetch_data(url: str) -> dict:
async with httpx.AsyncClient() as client:
response = await client.get(url)
return response.json()
async def main():
result = await fetch_data("https://api.example.com")
print(result)
asyncio.run(main())
async def process_multiple():
# Run concurrently
results = await asyncio.gather(
fetch_data("url1"),
fetch_data("url2"),
fetch_data("url3"),
)
return results
# With timeout
async def with_timeout():
try:
result = await asyncio.wait_for(fetch_data("url"), timeout=5.0)
except asyncio.TimeoutError:
print("Request timed out")
from typing import Protocol
class Database(Protocol):
def query(self, sql: str) -> list: ...
def get_users(db: Database) -> list:
return db.query("SELECT * FROM users")
def create_handler(handler_type: str):
match handler_type:
case "json":
return JSONHandler()
case "xml":
return XMLHandler()
case _:
raise ValueError(f"Unknown handler: {handler_type}")
from functools import wraps
import time
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.2f}s")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
Single Responsibility:
# Bad: Class does too much
class User:
def save(self): pass
def send_email(self): pass
def generate_report(self): pass
# Good: Separate concerns
class User:
def save(self): pass
class EmailService:
def send_email(self, user): pass
class ReportGenerator:
def generate(self, user): pass
def process_data(data: dict) -> str:
# Validate early
if not data:
raise ValueError("Data cannot be empty")
if "required_field" not in data:
raise KeyError("Missing required field")
# Process with confidence
return data["required_field"].upper()
# Prefer immutable transformations
def process_items(items: list[int]) -> list[int]:
return [item * 2 for item in items] # New list
# Over mutations
def process_items_bad(items: list[int]) -> None:
for i in range(len(items)):
items[i] *= 2 # Mutates input
my-project/
├── pyproject.toml
├── README.md
├── src/
│ └── my_project/
│ ├── __init__.py
│ ├── core.py
│ ├── utils.py
│ └── models.py
└── tests/
├── conftest.py
├── test_core.py
└── test_utils.py