You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Avoid excessive use of getattr, hasattr, and runtime type checks.
If an object is a pydantic BaseModel, prefer using its validated attributes and type annotations instead of probing attributes at runtime.
Rely on pydantic validation, model validators, and type hints; prefer TypedDict or Protocol for structural typing when appropriate.
When runtime checks are necessary, make them explicit, minimal, and well-documented so the reason for the guard is clear.
Async-First Design
Prefer asynchronous APIs for I/O-bound work.
Use asyncio or anyio; for HTTP, prefer httpx (async client).
Ensure clear async boundaries: public APIs and I/O paths should be async.
Provide minimal sync adapters only when needed, and document them.
importasynciofromloguruimportloggerimporthttpxasyncdeffetch_agent_state(url: str, timeout_s: float) ->dict:
"""Fetch agent state from a remote endpoint."""asyncwithhttpx.AsyncClient(timeout=timeout_s) asclient:
resp=awaitclient.get(url)
resp.raise_for_status()
data=resp.json()
logger.info("Fetched state from {url}", url=url)
returndatadeffetch_agent_state_sync(url: str, timeout_s: float) ->dict:
"""Synchronous adapter. Prefer the async variant."""returnasyncio.run(fetch_agent_state(url, timeout_s))
Logging
Use loguru; placeholders must be {} rather than %.
Log key events at info; avoid excessive logging.
Do not log sensitive data.
Use logger.exception sparingly: only for truly unexpected errors that require stack traces for debugging. For expected or recoverable errors, prefer logger.warning or logger.error with explicit context.
Prefer logger.warning for recoverable issues, degraded states, or when an operation can continue despite an error.
fromloguruimportloggerdefprocess_items(items: list[str]) ->int:
"""Process items and return count."""count=len(items)
logger.info("Processing {count} items", count=count)
# ...logger.info("Processed {count} items", count=count)
returncount# Good: expected error, use warning with contextasyncdefsend_notification(msg: str) ->None:
"""Send notification; log warning if it fails (non-critical)."""try:
awaitnotify_service(msg)
exceptNetworkErrorasexc:
logger.warning("Notification failed, continuing: {err}", err=str(exc))
# Good: unexpected error requiring investigation, use exceptionasyncdefcritical_operation() ->None:
"""Perform critical operation that should never fail."""try:
awaitprocess_critical_data()
exceptException:
logger.exception("Critical operation failed unexpectedly")
raise
Type Hints and Comments
Add type hints across public and internal APIs.
Comments and docstrings should be in English and explain why, not only what.
Use Protocols and TypedDict or pydantic models where appropriate.
Avoid excessive literal dict access (for example, using obj['key'] everywhere); prefer typed structures such as dataclass, pydantic models, or TypedDict for clearer contracts and better type safety.
Error Handling
Keep try-except depth to at most two levels.
Catch specific exceptions. Re-raise with context if needed.
Prefer explicit None checks and guard clauses over broad exception use.
importjsonfromloguruimportloggerdefparse_payload(raw: str) ->dict:
"""Parse payload; return empty dict on known format errors."""try:
data=json.loads(raw)
exceptjson.JSONDecodeErrorasexc:
logger.info("Invalid JSON: {err}", err=str(exc))
return {}
returndata
Structure and Size
Avoid nested functions; extract helpers at module level.
Keep functions under 200 lines. Split into well-named helpers.
Avoid functions with more than 10 parameters; prefer wrapping parameters in a struct or object.
Separate concerns: I/O, parsing, business logic, and orchestration.
Strings and Literals
Avoid long string literals; wrap lines under 100 characters.
Avoid magic numbers and ad-hoc string literals. Centralize constants.