Follow Python code organization conventions including method ordering, datetime handling, circular import avoidance, and type annotations. Use when organizing service classes, handling dates, or structuring modules.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Follow Python code organization conventions including method ordering, datetime handling, circular import avoidance, and type annotations. Use when organizing service classes, handling dates, or structuring modules.
user-invocable
true
argument-hint
[topic]
Python Code Style
Python code organization conventions for clean, maintainable codebases covering method ordering, datetime handling, circular import avoidance, and modern type annotations.
When to Use This Skill
Use this skill when:
Organizing methods in service classes or modules
Working with datetime objects and timestamps
Resolving circular import issues
Adding type annotations to code
Structuring function-based modules
Quick Reference
Method Organization Hierarchy
classMyService:
# 1. Special methods (__init__, __str__, etc.)def__init__(self):
pass# 2. Class methods @classmethoddeffrom_config():
():
():
():
():
from datetime import datetime, timezone
# ✅ Always timezone-aware
now = datetime.now(timezone.utc)
timestamp = datetime(2025, 1, 15, 10, 30, 0, tzinfo=timezone.utc)
# ❌ Never naive
now = datetime.now() # Missing timezone
Principle: Method Organization
Public Before Private
Public methods (part of the API) appear before private/internal methods (prefixed with _). This allows developers to understand the public API of each service at a glance.
Anti-Pattern (❌ Avoid)
classUserService:
def__init__(self):
pass# ❌ Private method before public methodsdef_validate_email(self, email: str):
pass# ❌ Public methods scattered after private onesdefcreate_user(self, email: str, name: str):
returnself._validate_email(email)
def_hash_password(self, password: str):
passdefauthenticate(self, email: str, password: str):
pass
Problems:
Readers must scan through implementation details to find the public API
Harder to understand what the service does at a glance
Inconsistent organization makes navigation difficult
Recommended Pattern (✅ Use This)
classUserService:
def__init__(self, db: Database):
self.db = db
# Public API methods first (high-level to low-level)defcreate_user(self, email: str, name: str) -> User:
"""Create a new user account."""self._validate_email(email)
return User(email=email, name=name)
defauthenticate(self, email: str, password: str) -> bool:
"""Authenticate user credentials."""
user = self.db.find_user(email)
returnself._verify_password(user, password)
# Private helper methods lastdef_validate_email(self, email: str):
"""Validate email format."""if"@"notin email:
raise ValueError("Invalid email")
def_verify_password(self, user: User, password: str) -> bool:
"""Verify password hash."""returnself._hash_password(password) == user.password_hash
def_hash_password(self, password: str) -> str:
"""Hash password for storage."""return hashlib.sha256(password.encode()).hexdigest()
Standard Method Order
Methods follow this ordering:
Special methods (__init__, __str__, __repr__, etc.)
Class methods (@classmethod)
Static methods (@staticmethod)
Instance methods (public, ordered by abstraction level)
Private methods (prefixed with _)
classReportService:
def__init__(self, repo: str):
self.repo = repo
def__str__(self):
returnf"ReportService({self.repo})"# Class methods @classmethoddeffrom_config(cls, config: dict):
return cls(config["repo"])
# Static methods @staticmethoddefvalidate_format(fmt: str):
return fmt in ["json", "csv", "html"]
# Public instance methods (high-level first)defgenerate_report(self, data: list) -> str:
validated = self._validate_data(data)
returnself._format_output(validated)
defexport_report(self, report: str, path: str):
self._write_file(path, report)
# Private helpersdef_validate_data(self, data: list):
return [item for item in data if item]
def_format_output(self, data: list) -> str:
return"\n".join(str(item) for item in data)
def_write_file(self, path: str, content: str):
withopen(path, "w") as f:
f.write(content)
Benefits
✅ Easier onboarding: New developers quickly understand what a service does
✅ Better maintainability: Clear separation between public contracts and implementation
✅ Visual organization: Separators make different sections obvious
✅ Faster navigation: Developers quickly jump to relevant sections
✅ Logical grouping: Related methods are clearly grouped together
Principle: Module-Level Code Organization
Function-Based Modules
For modules with functions rather than classes, use this order:
Dataclasses and models (public before private)
Public API functions (high-level to low-level)
Module utilities (helper functions used by the public API)
Private helper functions (prefixed with _)
Recommended Pattern (✅ Use This)
# artifact_operations.pyfrom dataclasses import dataclass
from typing importList# ============================================================# Public Models# ============================================================@dataclassclassProjectArtifact:
"""Public dataclass for artifact data."""
name: str
size: int
created_at: str@dataclassclassArtifactMetadata:
"""Metadata for artifact collections."""
total_count: int
total_size: int# ============================================================# Public API Functions# ============================================================deffind_artifacts(project: str) -> List[ProjectArtifact]:
"""Highest-level public function - main entry point."""
raw_data = _fetch_from_api(project)
return [_parse_artifact(item) for item in raw_data]
defget_artifact_details(artifact: ProjectArtifact) -> dict:
"""Mid-level public function - supporting operation."""return {
"name": artifact.name,
"size_mb": artifact.size / 1024 / 1024,
"age_days": calculate_age(artifact.created_at)
}
# ============================================================# Module Utilities# ============================================================defparse_artifact_name(name: str) -> tuple[str, str]:
"""Utility function used by multiple operations."""
parts = name.split("-")
return parts[0], "-".join(parts[1:])
defcalculate_age(timestamp: str) -> int:
"""Calculate age in days from timestamp."""# Implementationpass# ============================================================# Private Helper Functions# ============================================================def_fetch_from_api(project: str) -> list:
"""Private implementation detail - API interaction."""# Implementationpassdef_parse_artifact(data: dict) -> ProjectArtifact:
"""Private implementation detail - data parsing."""return ProjectArtifact(
name=data["name"],
size=data["size"],
created_at=data["created_at"]
)
Benefits
✅ Clear structure: Module organization is consistent and predictable
✅ Easy to find: Related code is grouped logically
✅ Public API first: Readers see the module's purpose immediately
Principle: Always Use Timezone-Aware Datetimes
All datetime objects must be timezone-aware. Naive datetimes (without timezone information) are not allowed and will cause validation errors.
Anti-Pattern (❌ Avoid)
from datetime import datetime
# ❌ Naive datetime - no timezone information
now = datetime.now()
timestamp = datetime(2025, 1, 15, 10, 30, 0)
utc_now = datetime.utcnow() # ❌ Deprecated and naive# Problems with naive datetimes:# - Ambiguous: Which timezone does this represent?# - Cannot compare naive and timezone-aware datetimes# - Serialized without timezone, leading to misinterpretation
Recommended Pattern (✅ Use This)
from datetime import datetime, timezone
# ✅ Always use timezone-aware datetimes
now = datetime.now(timezone.utc)
timestamp = datetime(2025, 1, 15, 10, 30, 0, tzinfo=timezone.utc)
# ✅ Use UTC for all internal operations
created_at = datetime.now(timezone.utc)
last_updated = datetime.now(timezone.utc)
# ✅ Serialize to ISO 8601 with timezone
timestamp_str = now.isoformat() # "2025-01-15T10:30:00+00:00"
Parsing ISO 8601 Timestamps
Use a helper function for parsing ISO 8601 timestamps:
✅ Prevents comparison errors: No "can't compare offset-naive and offset-aware datetimes"
✅ Unambiguous data: Timestamps clearly indicate their timezone
✅ ISO 8601 compliant: Standard format works everywhere
✅ Validated: Domain models prevent naive datetimes at construction time
Principle: Avoid Circular Imports
Circular imports indicate architectural problems. Fix the dependency structure rather than working around it.
Anti-Pattern (❌ Avoid)
# ❌ BAD: TYPE_CHECKING guardfrom typing import TYPE_CHECKING, Listif TYPE_CHECKING:
from module_b import SomeClass # Only imported during type checkingdefprocess_items(items: List["SomeClass"]): # String annotation workaroundpass# ❌ BAD: Using Any to avoid circular importfrom typing importAny, Listdefprocess_items(items: List[Any]): # Lost type safetypass
Problems:
TYPE_CHECKING means your code works at runtime only because the import is skipped
Any throws away type safety entirely
Both hide the architectural issue rather than solving it
Recommended Pattern (✅ Use This)
Fix the dependency structure by establishing one-way dependencies:
Identify which module is more foundational (lower-level)
Ensure the lower-level module never imports from higher-level ones
Verify with grep: grep "from higher_module" lower_module.py should return nothing
# lower_level.py - No imports from higher_level.pyfrom dataclasses import dataclass
@dataclassclassGitHubPullRequest:
number: int
title: str
state: str# higher_level.py - Can import from lower_level.pyfrom typing importListfrom lower_level import GitHubPullRequest # ✅ One-way dependency@dataclassclassProjectStats:
project_name: str
open_prs: List[GitHubPullRequest] # ✅ Proper typing, no strings
When You Have a Genuine Cycle
If you have a genuine cycle, either:
Move shared code to a third module that both can depend on
Refactor so the lower-level module doesn't need higher-level types
# Before: Circular dependency# module_a.py imports from module_b.py# module_b.py imports from module_a.py# After: Shared module breaks the cycle# shared.py - Common types both modules need@dataclassclassSharedType:
pass# module_a.py - Imports from sharedfrom shared import SharedType
# module_b.py - Imports from sharedfrom shared import SharedType
Benefits
✅ Clean architecture: One-way dependency graphs are easier to understand
✅ No runtime surprises: All imports work at runtime, not just type checking
✅ Better modularity: Lower-level modules are more reusable
✅ Full type safety: No need for Any or string annotations
Principle: Modern Type Annotations
Use Self for Factory Methods
When a classmethod or factory returns an instance of its own class, use Self instead of quoted string annotations: