Source code for app.init_db
#!/usr/bin/env python3
"""
Initialize the database schema by creating all ORM tables.
This module provides a thin, dependency-free CLI wrapper around
``app.database.ensure_database_schema`` so that schema creation can be invoked
from containers, CI jobs, or local development shells. It does not perform any
application bootstrapping beyond configuring logging and calling the database
utility.
See Also
--------
app.database.ensure_database_schema : Create DB tables via the shared helper.
app.config.settings : Runtime configuration values.
Notes
-----
- Primary role: minimal CLI to delegate schema creation to
``app.database.ensure_database_schema``.
- Key dependencies: a valid ``app.config.settings.DATABASE_URL`` and a
reachable database service.
- Invariants: the operation is idempotent and safe to re-run; if all tables
already exist, no changes are made.
Examples
--------
>>> # Programmatic usage # doctest: +SKIP
>>> from app.init_db import initialize_database_schema
>>> initialize_database_schema() # doctest: +SKIP
"""
import argparse
import logging
from sqlalchemy.exc import SQLAlchemyError
from app.database import ensure_database_schema
# Constants
SCRIPT_DESCRIPTION: str = "Initialize the database schema for the ML Weather project."
LOG_LEVEL_CHOICES: list[str] = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
DEFAULT_LOG_LEVEL: str = "INFO"
# Module-level logger
logger = logging.getLogger(__name__)
[docs]
def initialize_database_schema() -> None:
"""Create all ORM tables in the configured database.
Delegates to :func:`app.database.ensure_database_schema` and logs the
outcome. This function is idempotent and may be called multiple times
without side effects if the schema already exists.
Raises
------
SQLAlchemyError
If schema initialization fails (e.g., connectivity or permissions).
See Also
--------
app.database.ensure_database_schema : Create DB tables via the shared helper.
"""
ensure_database_schema()
logger.info("Database schema initialized.")
[docs]
def parse_args() -> argparse.Namespace:
"""Parse command-line arguments.
Returns
-------
argparse.Namespace
Parsed arguments, including ``log-level``.
Notes
-----
The ``--log-level`` argument is constrained to
:data:`LOG_LEVEL_CHOICES` to prevent invalid values.
"""
parser = argparse.ArgumentParser(description=SCRIPT_DESCRIPTION)
parser.add_argument(
"--log-level",
type=str,
choices=LOG_LEVEL_CHOICES,
default=DEFAULT_LOG_LEVEL,
help=f"Set the logging level (default: {DEFAULT_LOG_LEVEL}).",
)
return parser.parse_args()
[docs]
def main() -> None:
"""CLI entry point to initialize the database schema.
Parses arguments, configures logging, and calls
:func:`initialize_database_schema`.
Examples
--------
>>> # From a shell (inside the environment) # doctest: +SKIP
>>> python -m app.init_db --log-level DEBUG # doctest: +SKIP
Raises
------
SQLAlchemyError
Propagated from :func:`initialize_database_schema` when schema
initialization fails.
"""
args = parse_args()
logging.basicConfig(level=getattr(logging, args.log_level))
try:
initialize_database_schema()
except SQLAlchemyError as error:
logger.error("Failed to initialize database schema.", exc_info=True)
raise error
if __name__ == "__main__":
main()