================= Command Line Tool ================= Advanced Alchemy provides a command-line interface (CLI) for common database operations and project management tasks. Installation ------------ The CLI is installed with Advanced Alchemy with the extra ``cli``: .. tab-set:: .. tab-item:: pip :sync: key1 .. code-block:: bash :caption: Using pip python3 -m pip install advanced-alchemy[cli] .. tab-item:: uv .. code-block:: bash :caption: Using `UV `_ uv add advanced-alchemy[cli] .. tab-item:: pipx :sync: key2 .. code-block:: bash :caption: Using `pipx `_ pipx install advanced-alchemy[cli] .. tab-item:: pdm .. code-block:: bash :caption: Using `PDM `_ pdm add advanced-alchemy[cli] .. tab-item:: Poetry .. code-block:: bash :caption: Using `Poetry `_ poetry add advanced-alchemy[cli] Basic Usage ----------- The CLI can be invoked using the ``alchemy`` command: .. code-block:: bash alchemy --help Global Options -------------- The following options are available for all commands: .. list-table:: Global options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--config`` TEXT - **Required**. Dotted path to SQLAlchemy config(s), it's an instance of ``SQLAlchemyConfig`` (sync or async). Example: ``--config path.to.alchemy-config.config`` * - ``--bind-key`` TEXT - Optional. Specify which SQLAlchemy config to use * - ``--no-prompt`` - Optional. Skip confirmation prompts * - ``--verbose`` - Optional. Enable verbose output Config ------ Here is an example of what **config** looks like. If the file is named ``alchemy-config.py``, you would need to use it like this ``--config path.to.alchemy-config.config`` .. code-block:: python :caption: alchemy-config.py from sqlalchemy import create_engine from advanced_alchemy.config import SQLAlchemyConfig # Create a test config using SQLite config = SQLAlchemyConfig( connection_url="sqlite:///test.db" ) Available Commands ------------------ Migration Commands ~~~~~~~~~~~~~~~~~~ These commands manage database migrations and revisions. show-current-revision ^^^^^^^^^^^^^^^^^^^^^ Show the current revision of the database: .. code-block:: bash alchemy show-current-revision --config path.to.alchemy-config.config .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--verbose`` - Display detailed revision information downgrade ^^^^^^^^^ Downgrade database to a specific revision: .. code-block:: bash alchemy downgrade --config path.to.alchemy-config.config [REVISION] .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--sql`` - Generate SQL output for offline migrations * - ``--tag`` TEXT - Arbitrary tag for custom env.py scripts * - ``REVISION`` - Target revision (default: "-1") upgrade ^^^^^^^ Upgrade database to a specific revision: .. code-block:: bash alchemy upgrade --config path.to.alchemy-config.config [REVISION] .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--sql`` - Generate SQL output for offline migrations * - ``--tag`` TEXT - Arbitrary tag for custom env.py scripts * - ``REVISION`` - Target revision (default: "head") stamp ^^^^^ Stamp the revision table with a specific revision without running migrations: .. code-block:: bash alchemy stamp --config path.to.alchemy-config.config REVISION .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--sql`` - Generate SQL output for offline migrations * - ``--tag`` TEXT - Arbitrary tag for custom env.py scripts * - ``--purge`` - Delete all entries in version table before stamping * - ``REVISION`` - Target revision to stamp (required) **Use cases:** - Initialize version table for existing database - Mark migrations as applied without running them - Reset migration history (with ``--purge``) - Generate SQL for manual database stamping (with ``--sql``) init ^^^^ Initialize migrations for the project: .. code-block:: bash alchemy init --config path.to.alchemy-config.config [DIRECTORY] .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--multidb`` - Support multiple databases * - ``--package`` - Create __init__.py for created folder (default: True) * - ``DIRECTORY`` - Directory for migration files (optional) make-migrations ^^^^^^^^^^^^^^^ Create a new migration revision: .. code-block:: bash alchemy make-migrations --config path.to.alchemy-config.config .. list-table:: Options :header-rows: 1 :widths: 30 70 * - Option - Explanation * - ``-m``, ``--message`` TEXT - Revision message * - ``--autogenerate``/ ``--no-autogenerate`` - Automatically detect changes (default: True) * - ``--sql`` - Export to .sql instead of writing to database * - ``--head`` TEXT - Base revision for new revision (default: "head") * - ``--splice`` - Allow non-head revision as the "head" * - ``--branch-label`` TEXT - Branch label for new revision * - ``--version-path`` TEXT - Specific path for version file * - ``--rev-id`` TEXT - Specific revision ID Inspection Commands ~~~~~~~~~~~~~~~~~~~ These commands inspect migration history and database state. check ^^^^^ Check if the database is up to date with the current migration revision: .. code-block:: bash alchemy check --config path.to.alchemy-config.config Returns exit code 0 if database is current, non-zero otherwise. **Use cases:** - CI/CD validation before deployment - Pre-deployment smoke tests - Health checks heads ^^^^^ Show current available heads in the migration script directory: .. code-block:: bash alchemy heads --config path.to.alchemy-config.config .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--verbose`` - Display detailed head information * - ``--resolve-dependencies`` - Resolve dependencies between heads **Use cases:** - Detect multiple heads (branch conflicts) - Verify migration graph state - Branch development coordination history ^^^^^^^ List migration changesets in chronological order: .. code-block:: bash alchemy history --config path.to.alchemy-config.config .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--verbose`` - Display detailed revision information * - ``--rev-range`` TEXT - Revision range to display (e.g., 'base:head', 'abc:def') * - ``--indicate-current`` - Indicate the current revision in output **Use cases:** - Audit migration history - Generate migration documentation - Review changes between revisions show ^^^^ Show details of a specific revision: .. code-block:: bash alchemy show --config path.to.alchemy-config.config REVISION **Examples:** .. code-block:: bash # Show head revision alchemy show head --config path.to.alchemy-config.config # Show specific revision alchemy show abc123def --config path.to.alchemy-config.config # Show base revision alchemy show base --config path.to.alchemy-config.config branches ^^^^^^^^ Show current branch points in the migration history: .. code-block:: bash alchemy branches --config path.to.alchemy-config.config .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--verbose`` - Display detailed branch information **Use cases:** - Identify branch points in migration graph - Multi-team development coordination - Branch-based development workflows Branch Management Commands ~~~~~~~~~~~~~~~~~~~~~~~~~~ These commands manage branched migration workflows. merge ^^^^^ Merge two revisions together, creating a new migration file: .. code-block:: bash alchemy merge --config path.to.alchemy-config.config REVISIONS .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``-m``, ``--message`` TEXT - Merge message * - ``--branch-label`` TEXT - Branch label for merge revision * - ``--rev-id`` TEXT - Specify custom revision ID * - ``REVISIONS`` - Revisions to merge (e.g., 'abc123+def456' or 'heads') **Examples:** .. code-block:: bash # Merge all heads alchemy merge heads -m "merge feature branches" --config path.to.alchemy-config.config # Merge specific revisions alchemy merge abc123+def456 -m "merge database changes" --config path.to.alchemy-config.config **Use cases:** - Resolve multiple heads (branch conflicts) - Consolidate parallel development branches - Team coordination for database changes Utility Commands ~~~~~~~~~~~~~~~~ These commands provide additional migration utilities. edit ^^^^ Edit a revision file using the system editor (set via ``$EDITOR`` environment variable): .. code-block:: bash alchemy edit --config path.to.alchemy-config.config REVISION **Examples:** .. code-block:: bash # Edit latest revision alchemy edit head --config path.to.alchemy-config.config # Edit specific revision alchemy edit abc123def --config path.to.alchemy-config.config ensure-version ^^^^^^^^^^^^^^ Create the Alembic version table if it doesn't exist: .. code-block:: bash alchemy ensure-version --config path.to.alchemy-config.config .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--sql`` - Generate SQL output instead of executing **Use cases:** - Database initialization workflows - Manual database setup - Generate SQL for DBA review (with ``--sql``) list-templates ^^^^^^^^^^^^^^ List available Alembic migration templates: .. code-block:: bash alchemy list-templates --config path.to.alchemy-config.config **Use cases:** - Discover available templates for ``init`` command - Template selection for new projects Database Commands ~~~~~~~~~~~~~~~~~ These commands manage database tables and data. drop-all ^^^^^^^^ Drop all tables from the database: .. code-block:: bash alchemy drop-all --config path.to.alchemy-config.config .. warning:: This command is destructive and will delete all data. Use with caution. dump-data ^^^^^^^^^ Dump specified tables from the database to JSON files: .. code-block:: bash alchemy dump-data --config path.to.alchemy-config.config --table TABLE_NAME .. list-table:: Options :header-rows: 1 :widths: 20 80 * - Option - Explanation * - ``--table`` TEXT - Name of table to dump (use '*' for all tables) * - ``--dir`` PATH - Directory to save JSON files (default: ./fixtures) Extending the CLI ----------------- If you're using Click in your project, you can extend Advanced Alchemy's CLI with your own commands. The CLI provides two main functions for integration: - ``get_alchemy_group()``: Get the base CLI group - ``add_migration_commands()``: Add migration-related commands to a group Basic Extension ~~~~~~~~~~~~~~~ Here's how to extend the CLI with your own commands: .. code-block:: python from advanced_alchemy.cli import get_alchemy_group, add_migration_commands import click # Get the base group alchemy_group = get_alchemy_group() # Add your custom commands @alchemy_group.command(name="my-command") @click.option("--my-option", help="Custom option") def my_command(my_option): """My custom command.""" click.echo(f"Running my command with option: {my_option}") # Add migration commands to your group add_migration_commands(alchemy_group) Custom Group Integration ~~~~~~~~~~~~~~~~~~~~~~~~ You can also integrate Advanced Alchemy's commands into your existing Click group: .. code-block:: python import click from advanced_alchemy.cli import add_migration_commands @click.group() def cli(): """My application CLI.""" pass # Add migration commands to your CLI group add_migration_commands(cli) @cli.command() def my_command(): """Custom command in your CLI.""" pass if __name__ == "__main__": cli() Typer integration ----------------- You can integrate Advanced Alchemy's CLI commands into your existing ``Typer`` application. Here's how: .. code-block:: python :caption: cli.py import typer from advanced_alchemy.cli import get_alchemy_group, add_migration_commands app = typer.Typer() @app.command() def hello(name: str) -> None: """Says hello to the world.""" typer.echo(f"Hello {name}") @app.callback() def callback(): """ Typer app, including Click subapp """ pass def create_cli() -> typer.Typer: """Create the CLI application with both Typer and Click commands.""" # Get the Click group from advanced_alchemy alchemy_group = get_alchemy_group() # Convert our Typer app to a Click command object typer_click_object = typer.main.get_command(app) # Add all migration commands from the alchemy group to our CLI typer_click_object.add_command(add_migration_commands(alchemy_group)) return typer_click_object if __name__ == "__main__": cli = create_cli() cli() After setting up the integration, you can use both your ``Typer`` commands and Advanced Alchemy commands: .. code-block:: bash # Use your Typer commands python cli.py hello Cody # Use Advanced Alchemy commands python cli.py alchemy upgrade --config path.to.config python cli.py alchemy make-migrations --config path.to.config