myfy Framework Patterns
You are assisting a developer building an application with the myfy Python framework.
Core Principles
- •Opinionated, not rigid - Strong defaults, full configurability
- •Modular by design - Features are modules (web, data, tasks, frontend)
- •Type-safe DI - Constructor injection with compile-time validation
- •Async-native - Built on ASGI and AnyIO with contextvars
- •Zero-config defaults - Convention over configuration
Imports
Always import from the public API:
python
# Core from myfy.core import Application, provider, SINGLETON, REQUEST, TASK from myfy.core import BaseSettings, BaseModule # Web from myfy.web import WebModule, route, Query, abort, errors from myfy.web import Authenticated, Anonymous, AuthModule from myfy.web.ratelimit import RateLimitModule, rate_limit # Data from myfy.data import DataModule, AsyncSession # Tasks from myfy.tasks import TasksModule, task, TaskContext # Frontend from myfy.frontend import FrontendModule, render_template # User from myfy.user import UserModule # CLI Commands from myfy.commands import CliModule, cli
Application Structure
python
from myfy.core import Application
from myfy.web import WebModule, route
from myfy.data import DataModule
app = Application(
settings_class=AppSettings, # Optional custom settings
auto_discover=False, # Disable auto-discovery for explicit control
)
# Add modules in dependency order
app.add_module(DataModule())
app.add_module(WebModule())
Module Categories
| Module | Package | Purpose |
|---|---|---|
| WebModule | myfy-web | HTTP routing, ASGI, FastAPI-like decorators |
| DataModule | myfy-data | SQLAlchemy async, migrations, sessions |
| FrontendModule | myfy-frontend | Jinja2, Tailwind 4, DaisyUI 5, Vite |
| TasksModule | myfy-tasks | Background jobs, SQL-based task queue |
| UserModule | myfy-user | Auth, OAuth, user management |
| CliModule | myfy-commands | Custom CLI commands |
| AuthModule | myfy-web.auth | Type-based authentication, protected routes |
| RateLimitModule | myfy-web.ratelimit | Rate limiting per IP or user |
Key Conventions
- •File naming:
app.py,main.py, orapplication.pyfor entry point - •Settings: Extend
BaseSettingsfrommyfy.core - •Routes: Use global
routedecorator frommyfy.web - •Providers: Use
@provider(scope=...)decorator frommyfy.core - •Tasks: Use
@taskdecorator for background jobs
Common Patterns
Creating a Route with DI
python
from myfy.web import route
from myfy.data import AsyncSession
@route.get("/users/{user_id}")
async def get_user(user_id: int, session: AsyncSession) -> dict:
# session is auto-injected (REQUEST scope)
result = await session.execute(select(User).where(User.id == user_id))
return {"user": result.scalar_one_or_none()}
Creating a Provider
python
from myfy.core import provider, SINGLETON
@provider(scope=SINGLETON)
def email_service(settings: AppSettings) -> EmailService:
return EmailService(api_key=settings.email_api_key)
Settings Class
python
from pydantic import Field
from pydantic_settings import SettingsConfigDict
from myfy.core import BaseSettings
class AppSettings(BaseSettings):
app_name: str = Field(default="my-app")
debug: bool = Field(default=False)
database_url: str = Field(default="sqlite+aiosqlite:///./app.db")
model_config = SettingsConfigDict(
env_prefix="MYFY_",
env_file=".env",
)
Error Handling
python
from myfy.web import abort, errors
# Quick abort
abort(404, "User not found")
# Typed errors
raise errors.NotFound("User not found")
raise errors.BadRequest("Invalid email", field="email")
When Generating Code
Always:
- •Use type hints for all function parameters and return types
- •Use async/await for all handlers
- •Import from
myfy.*not internal modules - •Follow existing project structure
- •Use Pydantic models for request/response bodies