|
35 | 35 | import clickdc |
36 | 36 | from configobj import ConfigObj |
37 | 37 | import keyring |
| 38 | +import prompt_toolkit |
38 | 39 | from prompt_toolkit import print_formatted_text |
39 | 40 | from prompt_toolkit.application.current import get_app |
40 | 41 | from prompt_toolkit.auto_suggest import AutoSuggestFromHistory, ThreadedAutoSuggest |
|
55 | 56 | from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor |
56 | 57 | from prompt_toolkit.lexers import PygmentsLexer |
57 | 58 | from prompt_toolkit.output import ColorDepth |
58 | | -from prompt_toolkit.shortcuts import CompleteStyle, PromptSession |
| 59 | +from prompt_toolkit.shortcuts import CompleteStyle, ProgressBar, PromptSession |
| 60 | +from prompt_toolkit.shortcuts.progress_bar import formatters as progress_bar_formatters |
59 | 61 | import pymysql |
60 | 62 | from pymysql.constants.CR import CR_SERVER_LOST |
61 | 63 | from pymysql.constants.ER import ACCESS_DENIED_ERROR, HANDSHAKE_ERROR |
@@ -2036,7 +2038,7 @@ class CliArgs: |
2036 | 2038 | ) |
2037 | 2039 | ssl_verify_server_cert: bool = clickdc.option( |
2038 | 2040 | is_flag=True, |
2039 | | - help=('Verify server\'s "Common Name" in its cert against hostname used when connecting. This option is disabled by default.'), |
| 2041 | + help=("""Verify server's "Common Name" in its cert against hostname used when connecting. This option is disabled by default."""), |
2040 | 2042 | ) |
2041 | 2043 | verbose: bool = clickdc.option( |
2042 | 2044 | '-v', |
@@ -2167,6 +2169,10 @@ class CliArgs: |
2167 | 2169 | default=0.0, |
2168 | 2170 | help='Pause in seconds between queries in batch mode.', |
2169 | 2171 | ) |
| 2172 | + progress: bool = clickdc.option( |
| 2173 | + is_flag=True, |
| 2174 | + help='Show progress on the standard error with --batch.', |
| 2175 | + ) |
2170 | 2176 | use_keyring: str | None = clickdc.option( |
2171 | 2177 | type=click.Choice(['true', 'false', 'reset']), |
2172 | 2178 | default=None, |
@@ -2721,17 +2727,70 @@ def dispatch_batch_statements(statements: str, batch_counter: int) -> None: |
2721 | 2727 | click.secho(str(e), err=True, fg="red") |
2722 | 2728 | sys.exit(1) |
2723 | 2729 |
|
2724 | | - if cli_args.batch or not sys.stdin.isatty(): |
2725 | | - if cli_args.batch: |
2726 | | - if not sys.stdin.isatty() and cli_args.batch != '-': |
2727 | | - click.secho('Ignoring STDIN since --batch was also given.', err=True, fg='red') |
2728 | | - try: |
2729 | | - batch_h = click.open_file(cli_args.batch) |
2730 | | - except (OSError, FileNotFoundError): |
2731 | | - click.secho(f'Failed to open --batch file: {cli_args.batch}', err=True, fg='red') |
2732 | | - sys.exit(1) |
2733 | | - else: |
2734 | | - batch_h = click.get_text_stream('stdin') |
| 2730 | + if cli_args.batch and cli_args.batch != '-' and cli_args.progress and sys.stderr.isatty(): |
| 2731 | + # The actual number of SQL statements can be greater, if there is more than |
| 2732 | + # one statement per line, but this is how the progress bar will count. |
| 2733 | + goal_statements = 0 |
| 2734 | + if not sys.stdin.isatty() and cli_args.batch != '-': |
| 2735 | + click.secho('Ignoring STDIN since --batch was also given.', err=True, fg='yellow') |
| 2736 | + if os.path.exists(cli_args.batch) and not os.path.isfile(cli_args.batch): |
| 2737 | + click.secho('--progress is only compatible with a plain file.', err=True, fg='red') |
| 2738 | + sys.exit(1) |
| 2739 | + try: |
| 2740 | + batch_count_h = click.open_file(cli_args.batch) |
| 2741 | + for _statement, _counter in statements_from_filehandle(batch_count_h): |
| 2742 | + goal_statements += 1 |
| 2743 | + batch_count_h.close() |
| 2744 | + batch_h = click.open_file(cli_args.batch) |
| 2745 | + except (OSError, FileNotFoundError): |
| 2746 | + click.secho(f'Failed to open --batch file: {cli_args.batch}', err=True, fg='red') |
| 2747 | + sys.exit(1) |
| 2748 | + except ValueError as e: |
| 2749 | + click.secho(f'Error reading --batch file: {cli_args.batch}: {e}', err=True, fg='red') |
| 2750 | + sys.exit(1) |
| 2751 | + try: |
| 2752 | + if goal_statements: |
| 2753 | + pb_style = prompt_toolkit.styles.Style.from_dict({'bar-a': 'reverse'}) |
| 2754 | + custom_formatters = [ |
| 2755 | + progress_bar_formatters.Bar(start='[', end=']', sym_a=' ', sym_b=' ', sym_c=' '), |
| 2756 | + progress_bar_formatters.Text(' '), |
| 2757 | + progress_bar_formatters.Progress(), |
| 2758 | + progress_bar_formatters.Text(' '), |
| 2759 | + progress_bar_formatters.Text('eta ', style='class:time-left'), |
| 2760 | + progress_bar_formatters.TimeLeft(), |
| 2761 | + progress_bar_formatters.Text(' ', style='class:time-left'), |
| 2762 | + ] |
| 2763 | + err_output = prompt_toolkit.output.create_output(stdout=sys.stderr, always_prefer_tty=True) |
| 2764 | + with ProgressBar(style=pb_style, formatters=custom_formatters, output=err_output) as pb: |
| 2765 | + for pb_counter in pb(range(goal_statements)): |
| 2766 | + statement, _untrusted_counter = next(statements_from_filehandle(batch_h)) |
| 2767 | + dispatch_batch_statements(statement, pb_counter) |
| 2768 | + except (ValueError, StopIteration) as e: |
| 2769 | + click.secho(str(e), err=True, fg='red') |
| 2770 | + sys.exit(1) |
| 2771 | + finally: |
| 2772 | + batch_h.close() |
| 2773 | + sys.exit(0) |
| 2774 | + |
| 2775 | + if cli_args.batch: |
| 2776 | + if not sys.stdin.isatty() and cli_args.batch != '-': |
| 2777 | + click.secho('Ignoring STDIN since --batch was also given.', err=True, fg='red') |
| 2778 | + try: |
| 2779 | + batch_h = click.open_file(cli_args.batch) |
| 2780 | + except (OSError, FileNotFoundError): |
| 2781 | + click.secho(f'Failed to open --batch file: {cli_args.batch}', err=True, fg='red') |
| 2782 | + sys.exit(1) |
| 2783 | + try: |
| 2784 | + for statement, counter in statements_from_filehandle(batch_h): |
| 2785 | + dispatch_batch_statements(statement, counter) |
| 2786 | + batch_h.close() |
| 2787 | + except ValueError as e: |
| 2788 | + click.secho(str(e), err=True, fg='red') |
| 2789 | + sys.exit(1) |
| 2790 | + sys.exit(0) |
| 2791 | + |
| 2792 | + if not sys.stdin.isatty(): |
| 2793 | + batch_h = click.get_text_stream('stdin') |
2735 | 2794 | try: |
2736 | 2795 | for statement, counter in statements_from_filehandle(batch_h): |
2737 | 2796 | dispatch_batch_statements(statement, counter) |
|
0 commit comments