Quick Start
Get started with SmartRoute in 5 minutes.
Installation
pip install smartroute
Your First Router
Create a service with instance-scoped routing:
from smartroute import RoutedClass, Router, route
class Service(RoutedClass):
def __init__(self, label: str):
self.label = label
self.api = Router(self, name="api")
@route("api")
def describe(self):
return f"service:{self.label}"
# Each instance is isolated
first = Service("alpha")
second = Service("beta")
assert first.api.get("describe")() == "service:alpha"
assert second.api.get("describe")() == "service:beta"
Key concept: Routers are instantiated in __init__ with Router(self, ...) - each instance gets its own isolated router.
Custom Entry Names
Use prefixes and explicit names for cleaner method registration:
class SubService(RoutedClass):
def __init__(self, prefix: str):
self.prefix = prefix
self.routes = Router(self, name="routes", prefix="handle_")
@route("routes")
def handle_list(self):
return f"{self.prefix}:list"
@route("routes", name="detail")
def handle_detail(self, ident: int):
return f"{self.prefix}:detail:{ident}"
sub = SubService("users")
# Prefix stripped: "handle_list" → "list"
assert sub.routes.get("list")() == "users:list"
# Custom name used: "handle_detail" → "detail"
assert sub.routes.get("detail")(10) == "users:detail:10"
Building Hierarchies
Create nested router structures:
class RootAPI(RoutedClass):
def __init__(self):
self.api = Router(self, name="api")
self.users = SubService("users")
self.products = SubService("products")
self.api.attach_instance(self.users, name="users")
self.api.attach_instance(self.products, name="products")
root = RootAPI()
# Access with dotted paths
assert root.api.get("users.list")() == "users:list"
assert root.api.get("products.detail")(5) == "products:detail:5"
Adding Plugins
Extend behavior with plugins. Built-in plugins (logging, pydantic) are pre-registered; scope/channel policies live in the SmartPublisher ecosystem plugin.
class PluginService(RoutedClass):
def __init__(self):
self.api = Router(self, name="api").plug("logging")
@route("api")
def do_work(self):
return "ok"
svc = PluginService()
result = svc.api.get("do_work")() # Automatically logged
Validating Arguments
Use Pydantic for automatic validation:
pip install smartroute[pydantic]
class ValidateService(RoutedClass):
def __init__(self):
self.api = Router(self, name="api").plug("pydantic")
@route("api")
def concat(self, text: str, number: int = 1) -> str:
return f"{text}:{number}"
svc = ValidateService()
# Valid inputs
assert svc.api.get("concat")("hello", 3) == "hello:3"
assert svc.api.get("concat")("hi") == "hi:1"
# Invalid inputs raise ValidationError
# svc.api.get("concat")(123, "oops") # ValidationError!
Next Steps
Now that you’ve learned the basics:
Basic Usage Guide - Detailed explanation of core concepts
Plugin Guide - Learn to create custom plugins
Hierarchies Guide - Master nested routers
Best Practices - Production-ready patterns
API Reference - Complete API documentation
Need Help?
LLM Reference: See llm-docs for AI-optimized documentation
Examples: Check the examples directory
Issues: Report bugs on GitHub Issues