simonw / sqlite-utils

Python CLI utility and library for manipulating SQLite databases
https://sqlite-utils.datasette.io
Apache License 2.0
1.67k stars 111 forks source link

Mechanism to make memory DB created by `sqlite-utils memory` available to other commands #643

Closed simonw closed 6 hours ago

simonw commented 7 hours ago

For an experimental feature for https://github.com/simonw/sqlite-utils-ask I found myself wanting to invoke the existing sqlite-utils memory command and then do something else with the memory database it created.

I can do this with a sqlite_utils.Database(memory_name="x") but I need to ensure the variable doesn't go out of scope or it will be dropped by the sqlite3 library.

simonw commented 7 hours ago

Documented a pattern using this here: https://github.com/simonw/sqlite-utils/blob/8906f57740aaf3e9ea77af3de0b061a64a2f5d3b/docs/plugins.rst#register_commandscli

from contextlib import redirect_stdout
import io

@cli.command()
@click.pass_context
@click.argument(
    "paths",
    type=click.Path(file_okay=True, dir_okay=False, allow_dash=True),
    required=False,
    nargs=-1,
)
def show_schema_for_files(ctx, paths):
    from sqlite_utils.cli import memory
    with redirect_stdout(io.StringIO()):
        ctx.invoke(memory, paths=paths, sql="select 1")
    db = sqlite_utils.Database(memory_name="sqlite_utils_memory")
    # Now do something with that database
    click.echo(db.schema)
simonw commented 6 hours ago

OK, I massively over-engineered this. There's a much neater pattern:

from sqlite_utils.cli import memory
db = ctx.invoke(memory, paths=paths, return_db=True)
simonw commented 6 hours ago

Much neater:

@cli.command()
@click.pass_context
@click.argument(
    "paths",
    type=click.Path(file_okay=True, dir_okay=False, allow_dash=True),
    required=False,
    nargs=-1,
)
def show_schema_for_files(ctx, paths):
    from sqlite_utils.cli import memory
    db = ctx.invoke(memory, paths=paths, return_db=True)
    # Now do something with that database
    click.echo(db.schema)