Quick Reference
Fast lookups for common myfy patterns.
Application Setup
Basic Application
from myfy.core import Application, BaseSettings
from myfy.web import WebModule
class Settings(BaseSettings):
app_name: str = "My App"
app = Application(settings_class=Settings, auto_discover=False)
app.add_module(WebModule())
With Auto-Discovery
# Automatically discovers modules via entry points
app = Application(settings_class=Settings, auto_discover=True)
Dependency Injection
Register Provider
from myfy.core import provider, SINGLETON, REQUEST
@provider(scope=SINGLETON)
def database(settings: Settings) -> Database:
return Database(settings.db_url)
@provider(scope=REQUEST)
def session(db: Database) -> Session:
return db.create_session()
Inject Dependencies
# In routes
@route.get("/users")
async def list_users(db: Database) -> list[User]:
return await db.get_all_users()
# In other providers
@provider(scope=SINGLETON)
def user_service(db: Database, cache: Cache) -> UserService:
return UserService(db, cache)
Scopes
| Scope | Lifetime | Use Case |
|---|---|---|
SINGLETON |
Application | Database connections, caches |
REQUEST |
HTTP Request | Database sessions, request context |
TASK |
Background Task | Task-specific resources |
Configuration
Basic Settings
from myfy.core import BaseSettings
from pydantic import Field
class AppSettings(BaseSettings):
app_name: str = Field(default="My App")
debug: bool = Field(default=False)
database_url: str
api_key: str = Field(alias="API_KEY")
Environment Files
# .env (default)
APP_NAME=My App
DATABASE_URL=postgresql://localhost/mydb
# .env.dev (MYFY_PROFILE=dev)
DEBUG=true
DATABASE_URL=postgresql://localhost/mydb_dev
# .env.prod (MYFY_PROFILE=prod)
DEBUG=false
DATABASE_URL=postgresql://prod-server/mydb
Load Profile
# Use dev profile
MYFY_PROFILE=dev uv run myfy run
# Use prod profile
MYFY_PROFILE=prod uv run myfy run
Web Routes
Basic Routes
from myfy.web import route
@route.get("/")
async def index() -> dict:
return {"message": "Hello"}
@route.get("/users/{user_id}")
async def get_user(user_id: int) -> User:
return await db.get_user(user_id)
@route.post("/users")
async def create_user(body: CreateUserDTO) -> User:
return await db.create_user(body)
HTTP Methods
@route.get("/resource") # GET
@route.post("/resource") # POST
@route.put("/resource/{id}") # PUT
@route.patch("/resource/{id}") # PATCH
@route.delete("/resource/{id}") # DELETE
Status Codes
@route.post("/users", status_code=201)
async def create_user(body: CreateUserDTO) -> User:
return await db.create_user(body)
@route.delete("/users/{id}", status_code=204)
async def delete_user(user_id: int) -> None:
await db.delete_user(user_id)
Path Parameters
@route.get("/posts/{post_id}/comments/{comment_id}")
async def get_comment(post_id: int, comment_id: int) -> Comment:
return await db.get_comment(post_id, comment_id)
Request Body
from pydantic import BaseModel
class CreateUser(BaseModel):
name: str
email: str
@route.post("/users")
async def create_user(body: CreateUser, db: Database) -> User:
return await db.create_user(body)
Query Parameters
# Coming soon - use Starlette's Request for now
@route.get("/search")
async def search(request: Request) -> list[Result]:
query = request.query_params.get("q", "")
return await search_engine.search(query)
Modules
Create Module
from myfy.core import BaseModule, Container
class DataModule(BaseModule):
def __init__(self):
super().__init__("data")
def configure(self, container: Container) -> None:
# Register providers
container.register(Database, factory=create_db, scope=SINGLETON)
async def start(self) -> None:
# Startup logic
self.db = await connect_database()
async def stop(self) -> None:
# Cleanup logic
await self.db.disconnect()
Register Module
CLI Commands
Run Server
# Default (port 8000, auto-reload)
uv run myfy run
# Custom port
uv run myfy run --port 8001
# No reload
uv run myfy run --reload false
# Custom host
uv run myfy run --host 0.0.0.0 --port 8080
List Routes
Show Modules
Validate Config
Error Handling
HTTP Exceptions
from starlette.exceptions import HTTPException
@route.get("/users/{user_id}")
async def get_user(user_id: int, db: Database) -> User:
user = await db.get_user(user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
Custom Exception Handler
from starlette.requests import Request
from starlette.responses import JSONResponse
async def custom_exception_handler(request: Request, exc: Exception):
return JSONResponse(
status_code=500,
content={"error": str(exc)}
)
# Register in WebModule (advanced)
Testing
Basic Test
import pytest
from myfy.core import Application
@pytest.fixture
def app():
return Application(settings_class=TestSettings, auto_discover=False)
def test_repository(app):
repo = app.container.get(TaskRepository)
task = repo.create("Test task")
assert task.id == 1
Override Dependencies
@pytest.fixture
def app():
app = Application(settings_class=TestSettings, auto_discover=False)
# Override provider
@provider(scope=SINGLETON)
def mock_database() -> Database:
return MockDatabase()
return app
HTTP Tests
from starlette.testclient import TestClient
def test_get_users(app):
client = TestClient(app.web_module.get_asgi_app(app.container))
response = client.get("/users")
assert response.status_code == 200
Pydantic Models
Request DTOs
from pydantic import BaseModel, Field, validator
class CreateUserDTO(BaseModel):
username: str = Field(min_length=3, max_length=50)
email: str = Field(pattern=r'^[\w\.-]+@[\w\.-]+\.\w+$')
age: int = Field(ge=18, le=120)
@validator('username')
def username_alphanumeric(cls, v):
if not v.isalnum():
raise ValueError('must be alphanumeric')
return v
Response Models
from datetime import datetime
class UserResponse(BaseModel):
id: int
username: str
email: str
created_at: datetime
class Config:
from_attributes = True # For SQLAlchemy models
Async Patterns
Async Handler
@route.get("/users")
async def list_users(db: Database) -> list[User]:
# Use await for async operations
users = await db.get_all_users()
return users
Sync Handler
@route.get("/config")
def get_config(settings: Settings) -> dict:
# Sync handlers work too (but prefer async)
return {"app_name": settings.app_name}
Background Tasks
# Coming soon - use Starlette's BackgroundTasks for now
from starlette.background import BackgroundTasks
@route.post("/send-email")
async def send_email(
body: EmailDTO,
background_tasks: BackgroundTasks
) -> dict:
background_tasks.add_task(send_email_task, body.to, body.subject)
return {"status": "queued"}
Common Patterns
Repository Pattern
class UserRepository:
def __init__(self, db: Database):
self.db = db
async def get(self, user_id: int) -> User | None:
return await self.db.get_user(user_id)
async def list_all(self) -> list[User]:
return await self.db.get_all_users()
async def create(self, data: CreateUserDTO) -> User:
return await self.db.create_user(data)
@provider(scope=SINGLETON)
def user_repository(db: Database) -> UserRepository:
return UserRepository(db)
Service Layer
class UserService:
def __init__(self, repo: UserRepository, cache: Cache):
self.repo = repo
self.cache = cache
async def get_user(self, user_id: int) -> User:
# Check cache
cached = await self.cache.get(f"user:{user_id}")
if cached:
return User.model_validate(cached)
# Get from database
user = await self.repo.get(user_id)
if user:
await self.cache.set(f"user:{user_id}", user.model_dump())
return user
@provider(scope=SINGLETON)
def user_service(repo: UserRepository, cache: Cache) -> UserService:
return UserService(repo, cache)
Factory Pattern
class DatabaseFactory:
@staticmethod
def create(settings: Settings) -> Database:
if settings.db_type == "postgres":
return PostgresDatabase(settings.db_url)
elif settings.db_type == "mysql":
return MySQLDatabase(settings.db_url)
else:
raise ValueError(f"Unknown db_type: {settings.db_type}")
@provider(scope=SINGLETON)
def database(settings: Settings) -> Database:
return DatabaseFactory.create(settings)
Environment Variables
Common Variables
# Application
APP_NAME=My App
DEBUG=true
# Database
DATABASE_URL=postgresql://localhost/mydb
DB_POOL_SIZE=10
# Redis
REDIS_URL=redis://localhost:6379
# API Keys
API_KEY=your-secret-key
JWT_SECRET=your-jwt-secret
# Profiles
MYFY_PROFILE=dev # Use .env.dev
Type Hints
Common Types
from typing import Optional, List, Dict, Any
# Optional
user: User | None = None
# List
users: list[User] = []
# Dict
config: dict[str, Any] = {}
# Multiple types
result: User | dict[str, Any] = get_result()
Next Steps
- Core Concepts - Deep dive
- Testing Guide - Test your app
- Deployment - Go to production