Configuration Management
This tutorial guides you through managing environment-specific settings in the Pagemark API. You will learn how to use the project's dataclass-based configuration system to switch between development, testing, and production environments.
Prerequisites
To follow this tutorial, you need:
- Python 3.7 or higher (for
dataclassessupport) - Flask installed in your environment
Step 1: Understand the Configuration Hierarchy
The Pagemark API uses a hierarchy of dataclasses in app/config.py to manage settings. All configurations inherit from BaseConfig, which defines shared defaults like the API version and default page sizes.
Open app/config.py to see the core definitions:
from dataclasses import dataclass, field
import os
@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 = 25
@dataclass
class DevelopmentConfig(BaseConfig):
"""Configuration for local development."""
DEBUG: bool = True
PAGE_SIZE: int = 10
In this step, you can see that DevelopmentConfig overrides DEBUG to True and reduces the PAGE_SIZE to 10 for easier local debugging.
Step 2: Apply Configuration via the Application Factory
The application uses the "Factory Pattern" to initialize the Flask instance. The create_app function in app/__init__.py accepts a configuration class and applies it using Flask's app.config.from_object() method.
from flask import Flask
from app.config import DevelopmentConfig
def create_app(config_class=DevelopmentConfig) -> Flask:
app = Flask(__name__)
app.config.from_object(config_class)
# ... blueprint registration ...
return app
By default, calling create_app() without arguments uses DevelopmentConfig. This is how the entry point run.py starts the server:
from app import create_app
app = create_app()
if __name__ == "__main__":
app.run(debug=True, port=5000)
Step 3: Configure for Production
When moving to production, you must use ProductionConfig. Unlike other environments, ProductionConfig enforces security by requiring a SECRET_KEY to be set in your environment variables.
In app/config.py, the ProductionConfig is defined as:
@dataclass
class ProductionConfig(BaseConfig):
"""Configuration for production deployments."""
SECRET_KEY: str = field(default_factory=lambda: os.environ["SECRET_KEY"])
PAGE_SIZE: int = 25
Warning: If you attempt to initialize the app with ProductionConfig without setting the SECRET_KEY environment variable, the application will raise a KeyError and fail to start.
To run the app in production mode, you would initialize it like this:
from app import create_app
from app.config import ProductionConfig
# Ensure SECRET_KEY is in os.environ before calling this
app = create_app(config_class=ProductionConfig)
Step 4: Access Environment-Specific Cache Settings
The configuration classes also provide helper methods for complex settings, such as cache configurations. Each environment can define its own cache TTL (Time To Live) and size limits via the get_cache_config() method.
You can access these settings within your application logic:
from flask import current_app
from app.config import DevelopmentConfig
# In a route or service:
config_inst = DevelopmentConfig()
cache_settings = config_inst.get_cache_config()
# Result for DevelopmentConfig:
# {'ttl_seconds': 30, 'max_entries': 128, 'eviction': 'lru'}
The ProductionConfig increases these limits significantly (ttl=600, max_size=4096) to handle higher traffic, as seen in app/config.py:
def get_cache_config(self) -> Dict[str, Any]:
return _build_cache_config(ttl=600, max_size=4096)
Summary of Constants
The system also relies on several top-level constants defined in app/config.py that govern global API behavior:
DEFAULT_PAGE_SIZE(25): The fallback size for paginated responses.MAX_PAGE_SIZE(100): The hard limit enforced by the internal_validate()method.API_VERSION("v1"): The current version string used for API paths.
By using this dataclass-based approach, you ensure that your application settings are type-safe and easily swappable across different deployment stages.