Skip to main content

Core Configuration Concepts

The configuration system in this project is built around the BaseConfig class in app/config.py. It uses Python dataclasses to provide a structured, type-safe way to manage application settings across different environments (Development, Production, and Testing).

The BaseConfig Foundation

The BaseConfig class serves as the single source of truth for shared settings. It defines the default behavior for the application, which is then refined by environment-specific subclasses.

@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

Core Attributes

  • SECRET_KEY: Used for session signing and security. In the base class, it defaults to "change-me" if the environment variable is missing.
  • DEBUG/TESTING: Boolean flags to enable Flask's debug mode or testing mode.
  • PAGE_SIZE: Controls the default number of items returned in paginated API responses, defaulting to DEFAULT_PAGE_SIZE (25).

Environment-Specific Configurations

The project implements three specialized configurations that inherit from BaseConfig. This allows the application to behave differently depending on where it is running.

DevelopmentConfig

Used for local development. It enables DEBUG mode and reduces the PAGE_SIZE to 10 to make manual testing of pagination easier. It also overrides get_cache_config to provide a shorter TTL (30s) and smaller cache size (128).

ProductionConfig

Designed for deployment. It enforces strict security by requiring the SECRET_KEY to be present in the environment; it will raise a KeyError if the variable is missing. It also uses a larger cache (4096 entries) with a longer TTL (600s).

@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

def get_cache_config(self) -> Dict[str, Any]:
return _build_cache_config(ttl=600, max_size=4096)

TestingConfig

Used during test execution. It sets TESTING to True and uses a very small PAGE_SIZE (5) to ensure pagination logic is frequently triggered during automated tests.

Application Integration

The configuration is loaded into the Flask application within the application factory located in app/__init__.py. The create_app function accepts a config_class argument, which defaults to DevelopmentConfig.

def create_app(config_class=DevelopmentConfig) -> Flask:
app = Flask(__name__)
app.config.from_object(config_class)
# ... blueprint registration ...
return app

By using app.config.from_object(), Flask inspects the dataclass and loads all uppercase attributes into the standard Flask app.config dictionary.

Implementation Gotchas

While the configuration system is robustly defined in app/config.py, there are specific areas in the codebase where these settings are currently bypassed or hardcoded:

  1. Hardcoded Cache Size: The BookmarkService (found in app/services/bookmark_service.py) initializes its internal LRUCache with a hardcoded max_size=256, ignoring the values provided by get_cache_config().
  2. Route Defaults: In app/routes/bookmarks.py, the list_bookmarks endpoint uses a hardcoded default of 25 for the per_page parameter instead of referencing current_app.config['PAGE_SIZE'].
  3. Validation: The _validate() method in BaseConfig is marked as internal and is not automatically invoked by the Flask factory. Developers must manually call this if they wish to verify configuration integrity at startup.