Core Configuration Architecture
The configuration architecture of this project is built around a hierarchical structure of Python dataclasses defined in app/config.py. This approach provides type safety, default values, and environment-specific overrides that are easily consumed by the Flask application factory.
The Base Configuration Foundation
The core of the system is the BaseConfig class. It defines the shared settings and default behaviors used across all environments. By using the @dataclass decorator, the project ensures that configuration objects are structured and predictable.
@dataclass
class BaseConfig:
"""Base configuration shared across all environments."""
SECRET_KEY: str = field(default_factory=lambda: os.environ.get("SECRET_KEY", "change-me"))
DEBUG: bool = False
TESTING: bool = False
PAGE_SIZE: int = DEFAULT_PAGE_SIZE
def get_cache_config(self) -> Dict[str, Any]:
"""Return cache settings for this environment."""
return _build_cache_config()
def _validate(self) -> bool:
"""Check internal invariants. Not part of the public API."""
return bool(self.SECRET_KEY) and self.PAGE_SIZE <= MAX_PAGE_SIZE
Key Attributes
- SECRET_KEY: Used for cryptographic signing. In
BaseConfig, it defaults to"change-me"if the environment variable is missing. - PAGE_SIZE: Controls pagination limits, defaulting to
DEFAULT_PAGE_SIZE(25). - DEBUG/TESTING: Boolean flags that toggle Flask's internal modes.
Environment-Specific Specialization
The project uses inheritance to specialize configurations for development, production, and testing. This allows for different behaviors, such as stricter security in production or smaller page sizes for easier testing.
Development Configuration
DevelopmentConfig enables DEBUG mode and reduces the PAGE_SIZE to 10 to make manual testing of pagination easier.
@dataclass
class DevelopmentConfig(BaseConfig):
"""Configuration for local development."""
DEBUG: bool = True
PAGE_SIZE: int = 10
Production Configuration
ProductionConfig enforces stricter security requirements. Most notably, it overrides the SECRET_KEY field to force a lookup in os.environ. If the SECRET_KEY environment variable is not set, the application will raise a KeyError on startup, preventing insecure deployments.
@dataclass
class ProductionConfig(BaseConfig):
"""Configuration for production deployments."""
SECRET_KEY: str = field(default_factory=lambda: os.environ["SECRET_KEY"])
PAGE_SIZE: int = DEFAULT_PAGE_SIZE
Testing Configuration
TestingConfig sets the TESTING flag to True and further reduces PAGE_SIZE to 5, which is useful for verifying pagination logic in automated test suites.
Dynamic Cache Configuration
Instead of static dictionary definitions, the configuration classes use a method called get_cache_config() to generate environment-specific cache settings. This method wraps an internal helper _build_cache_config.
| Environment | TTL (seconds) | Max Size |
|---|---|---|
| Base / Default | 300 | 1024 |
| Development | 30 | 128 |
| Production | 600 | 4096 |
For example, ProductionConfig overrides this to provide a larger, longer-lived cache:
def get_cache_config(self) -> Dict[str, Any]:
return _build_cache_config(ttl=600, max_size=4096)
Application Integration
The configuration classes are integrated into the Flask application within the factory function create_app located in app/__init__.py. Flask's app.config.from_object() method is used to load the attributes of the chosen class directly into the Flask configuration dictionary.
def create_app(config_class=DevelopmentConfig) -> Flask:
"""Application factory."""
app = Flask(__name__)
app.config.from_object(config_class)
# ... registration of blueprints ...
return app
Validation and Constraints
The BaseConfig class includes a _validate() method that checks internal invariants. It ensures that:
- A
SECRET_KEYis present. - The
PAGE_SIZEdoes not exceed theMAX_PAGE_SIZE(100), as defined in the module constants.
While this method is defined within the configuration classes, it serves as a safeguard for internal logic to ensure the application remains within its operational limits.