This guide covers advanced features and patterns for the Sweet Tea Factory System.
Enable automatic class discovery and registration:
# In your package's __init__.py
from sweet_tea.registry import Registry
# Automatically register all classes in this package
Registry.fill_registry()
# Classes are now available by their lowercase names
instance = Factory.create("my_class") # Creates MyClass instance
All registry operations are thread-safe:
import threading
from sweet_tea import Registry, SingletonFactory
def worker(thread_id):
# Safe concurrent registration and singleton creation
Registry.register(f"service_{thread_id}", MyService)
instance = SingletonFactory.create(f"service_{thread_id}")
threads = [threading.Thread(target=worker, args=(i,)) for i in range(10)]
for t in threads: t.start()
for t in threads: t.join()
The InverterFactory provides class definitions instead of instances, giving you complete control over instantiation:
from sweet_tea import Registry, InverterFactory
# Register a class
Registry.register("expensive_service", ExpensiveService)
# Get the class definition (no instantiation yet)
service_class = InverterFactory.create("expensive_service")
# Instantiate when ready, with custom parameters
service1 = service_class(config="production", timeout=30)
service2 = service_class(config="testing", timeout=5)
# Perfect for:
# - Expensive object creation
# - Dependency injection frameworks
# - Metaprogramming scenarios
# - When instantiation parameters aren't known at factory call time
The SingletonFactory provides comprehensive singleton lifecycle management:
from sweet_tea import Registry, SingletonFactory
# Register classes
Registry.register("cache", RedisCache)
Registry.register("database", PostgreSQLConnection)
# Create singletons on-demand
cache = SingletonFactory.create("cache", configuration={"ttl": 3600})
db = SingletonFactory.create("database", configuration={"host": "localhost"})
# Inspect current singletons
singletons = SingletonFactory.list_singletons() # ['cache', 'database']
available = SingletonFactory.list_keys() # All registry keys
# Remove specific singleton
old_cache = SingletonFactory.pop("cache") # Returns and removes instance
# Clear all singletons
SingletonFactory.clear() # Remove all cached instances
The system gracefully handles missing optional dependencies:
# If a module has optional imports, it will warn but continue
# sweet_tea/registry.py will issue SweetTeaWarning for missing dependencies
# but registration continues for available classes
Handle factory errors appropriately:
from sweet_tea import Factory, SweetTeaError
try:
instance = Factory.create("nonexistent_key")
except SweetTeaError as e:
print(f"Factory error: {e}")
Use Protocol-based abstract factories for maximum type safety:
from typing import Protocol
from sweet_tea import AbstractFactory
class LoggerProtocol(Protocol):
def log(self, message: str) -> None: ...
def set_level(self, level: str) -> None: ...
# Only classes implementing LoggerProtocol can be created
logger_factory = AbstractFactory[LoggerProtocol]
# Type checker will ensure compliance
logger = logger_factory.create("console_logger")
logger.log("Hello, World!") # Type-safe!
class Application:
def __init__(self, db_factory, cache_factory):
self.db = db_factory.create("postgres")
self.cache = cache_factory.create("redis")
# Create specialized factories
db_factory = AbstractFactory[DatabaseInterface]
cache_factory = AbstractFactory[CacheInterface]
app = Application(db_factory, cache_factory)