.. module:: Compatibility Compatibility ========================= Cross-version compatibility utilities for Python 3.9+ support. This module provides backports and compatibility shims for features introduced in newer Python versions. Overview -------------------------- The compatibility module ensures your code works across different Python versions by: - Providing ``Self`` type hint for Python < 3.11 - Implementing ``StrEnum`` for Python < 3.11 - Automatically using native implementations when available Quick Examples -------------------------- Self Type Hint ~~~~~~~~~~~~~~ Use ``Self`` for better type hints in methods that return the instance itself: .. code-block:: python from core_mixins import Self class Builder: def __init__(self) -> None: self.value = 0 def add(self, amount: int) -> Self: """Returns self for method chaining.""" self.value += amount return self def multiply(self, factor: int) -> Self: """Returns self for method chaining.""" self.value *= factor return self # Type checker knows the return type result = Builder().add(5).multiply(2) # type: Builder **Why use Self?** Before Python 3.11, you had to use string literals or type variables: .. code-block:: python # Old way (Python < 3.11) from typing import TypeVar T = TypeVar('T', bound='Builder') class Builder: def add(self: T, amount: int) -> T: # Complex! return self # New way (Python 3.11+, works in 3.9+ with core-mixins) from core_mixins import Self class Builder: def add(self, amount: int) -> Self: # Simple! return self StrEnum Usage ~~~~~~~~~~~~~ Create string-based enumerations that work consistently across Python versions: .. code-block:: python from core_mixins import StrEnum class Status(StrEnum): """Order status enumeration.""" PENDING = "pending" PROCESSING = "processing" COMPLETED = "completed" CANCELLED = "cancelled" # Use as strings status = Status.PENDING print(status) # "pending" print(f"Status: {status}") # "Status: pending" # String comparison works if status == "pending": print("Order is pending") # Enum features print(Status.PENDING.name) # "PENDING" print(Status.PENDING.value) # "pending" print(list(Status)) # [Status.PENDING, Status.PROCESSING, ...] HTTP Status Example ~~~~~~~~~~~~~~~~~~~ .. code-block:: python from core_mixins import StrEnum class HTTPStatus(StrEnum): """HTTP status codes.""" OK = "200" CREATED = "201" BAD_REQUEST = "400" UNAUTHORIZED = "401" NOT_FOUND = "404" SERVER_ERROR = "500" def handle_response(status: HTTPStatus) -> str: """Handle HTTP response based on status.""" if status == HTTPStatus.OK: return "Success" elif status in (HTTPStatus.BAD_REQUEST, HTTPStatus.UNAUTHORIZED): return "Client error" elif status == HTTPStatus.SERVER_ERROR: return "Server error" return "Unknown status" # Usage response_status = HTTPStatus.OK print(handle_response(response_status)) # "Success" Python Version Support -------------------------- +------------------+-------------------+------------------------+ | Feature | Native In | Backported By | +==================+===================+========================+ | ``Self`` | Python 3.11+ | typing_extensions | +------------------+-------------------+------------------------+ | ``StrEnum`` | Python 3.11+ | Custom implementation | +------------------+-------------------+------------------------+ The module automatically uses native implementations when running on Python 3.11+, ensuring optimal performance and compatibility. API Reference -------------------------- .. automodule:: core_mixins.compatibility :members: :undoc-members: :show-inheritance: Best Practices -------------------------- Import from core_mixins ~~~~~~~~~~~~~~~~~~~~~~~~ Always import compatibility features from ``core_mixins``: .. code-block:: python # ✓ Correct from core_mixins import Self, StrEnum # ✗ Avoid direct imports (may not exist in older Python) from typing import Self # Fails in Python < 3.11 Use Self for Fluent Interfaces ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``Self`` is perfect for builder patterns and fluent APIs: .. code-block:: python from core_mixins import Self class QueryBuilder: def where(self, condition: str) -> Self: return self def order_by(self, field: str) -> Self: return self def limit(self, count: int) -> Self: return self # Type-safe method chaining query = QueryBuilder().where("active = true").order_by("name").limit(10) Use StrEnum for Constants ~~~~~~~~~~~~~~~~~~~~~~~~~~ ``StrEnum`` is ideal for configuration values and constants: .. code-block:: python from core_mixins import StrEnum class Environment(StrEnum): DEVELOPMENT = "dev" STAGING = "staging" PRODUCTION = "prod" class LogLevel(StrEnum): DEBUG = "DEBUG" INFO = "INFO" WARNING = "WARNING" ERROR = "ERROR"