[Feature request] Make --help from "flask db migrate" return original help text.
At the moment, the "--help" is not very helpful.
Actual behavior
(venv) user@pc project % flask db migrate revision --help
Usage: flask db migrate [OPTIONS] [ALEMBIC_ARGS]...
Wrap the alembic CLI tool (defaults to running upgrade head).
Options:
--help Show this message and exit.
Proposed behavior
Alternative behavior for Flask-DB would be to return the actual help documentation from alembic:
(venv) user@pc project % flask db migrate revision --help
usage: alembic revision [-h] [-m MESSAGE] [--autogenerate] [--sql] [--head HEAD] [--splice]
[--branch-label BRANCH_LABEL] [--version-path VERSION_PATH] [--rev-id REV_ID]
[--depends-on DEPENDS_ON]
optional arguments:
-h, --help show this help message and exit
-m MESSAGE, --message MESSAGE
Message string to use with 'revision'
--autogenerate Populate revision script with candidate migration operations, based on
comparison of database to model.
--sql Don't emit SQL to database - dump to standard output/file instead. See docs on
offline mode.
--head HEAD Specify head revision or <branchname>@head to base new revision on.
--splice Allow a non-head revision as the 'head' to splice onto
--branch-label BRANCH_LABEL
Specify a branch label to apply to the new revision
--version-path VERSION_PATH
Specify specific path from config for version file
--rev-id REV_ID Specify a hardcoded revision id instead of generating one
--depends-on DEPENDS_ON
Specify one or more revision identifiers which this revision should depend on.
Implementing this
To implement, add help_option_names=[] to the context_settings of the migrate command. At the moment, the Click context sees the --help before the Alembic CLI does.
# Old
@db.command(context_settings=dict(ignore_unknown_options=True))
@click.argument("alembic_args", nargs=-1, type=click.UNPROCESSED)
@with_appcontext
def migrate(alembic_args):
...
# New
@db.command(context_settings=dict(ignore_unknown_options=True,
help_option_names=[]))
@click.argument("alembic_args", nargs=-1, type=click.UNPROCESSED)
@with_appcontext
def migrate(alembic_args):
...
Alternatively, you can implement the --help so that when you run exactly flask db migrate --help it returns the Click docs, but provides the alembic docs when you invoke an Alembic subcommand. Something like this? I would need to play with it more to get super sane default behavior.
@db.command(context_settings=dict(ignore_unknown_options=True,
help_option_names=[]))
@click.argument("alembic_args", nargs=-1, type=click.UNPROCESSED)
@with_appcontext
@click.pass_context
def migrate(ctx, alembic_args):
if len(ctx.args) == 1 and ctx.args[0] == '--help':
return ctx.get_help_option_names(migrate)
...
Small problem with this approach, which is that the help text will say usage: alembic revision ... instead of usage: flask db migrate revision .... Fixing that would take more work. But even with the simple implementation, I have such a strong instinct to rely on --help for options, I think having it work the way you'd mostly expect beats the downside of not returning anything.
What do you think?
Hi,
This is mentioned in the readme at https://github.com/nickjj/flask-db#migrate btw,, a workaround is to run -h instead of --help to get Alembic's help. I know it's kind of lame but like you've discovered it's not straight forward to figure out how to list out 2 different help menus with the same flag.
It's a tough call. Since db migrate is an alias to alembic I think I'm ok with db migrate --help showing Alembic's help menu because the db migrate command from this extension's point of view has no arguments or flags since it's an alias to alembic and I would guess the natural behavior there is to always want Alembic's help menu.
Totally missed that in the readme.
The existing default behavior is defensible for the case of flask db migrate --help specifically, it feels a little overkill that it follows through to subcommands like flask db migrate revision --help. So using something like if len(ctx.args) == 1 and ctx.args[0] == '--help' lets one distinguish those two cases.
Are you saying if you ran flask db migrate --help you would expect to see Click's help menu for Flask-DB instead of Alembic's list of available commands, even if flask db migrate itself technically has no flags or arguments?
I should have been clearer!
flask db migrate --help
Normally I would expect a list of all the subcommands plus a description of the default behavior, like a typical CLI. Doing that is tough though because:
alembic --helpdoesn't describe the default behavior offlask db migrate, which is to runalembic ugprade head.- The default help text doesn't list the subcommands available because of how Flask-DB is inherently designed to arbitrarily wrap Alembic.
So without expending lots of effort, you get to choose between describing default behavior or returning alembic --help.
Current behavior is the former, which is defensible. As you said, "you've discovered it's not straight forward to figure out how to list out 2 different help menus with the same flag," so you picked one.
flask db migrate [subcommand] --help
^ This is where I am a bit more confident that --help should return the Alembic documentation, because the default behavior of flask db migrate to run alembic upgrade head no longer applies; it's a pure wrapper around Alembic once you specify a subcommand. So in this case I think the only reasonable default behavior is to return Alembic's docs because "2 different help menus" doesn't apply anymore, just the one.
So in my personal opinion I think the best behavior here is have the context run ctx.get_help_option_names(migrate) when no subcommands are specified, otherwise pass to Alembic; the final snippet of code I listed should achieve that goal. (warning: didn't test, just winged it based on my understanding of Click.)