Mercurial > repos > shellac > sam_consensus_v3
diff env/lib/python3.9/site-packages/argcomplete/__init__.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/lib/python3.9/site-packages/argcomplete/__init__.py Mon Mar 22 18:12:50 2021 +0000 @@ -0,0 +1,684 @@ +# Copyright 2012-2019, Andrey Kislyuk and argcomplete contributors. +# Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info. + +from __future__ import absolute_import, division, print_function, unicode_literals + +import os, sys, argparse, contextlib +from . import completers, my_shlex as shlex +from .compat import USING_PYTHON2, str, sys_encoding, ensure_str, ensure_bytes +from .completers import FilesCompleter, SuppressCompleter +from .my_argparse import IntrospectiveArgumentParser, action_is_satisfied, action_is_open, action_is_greedy +from .shell_integration import shellcode + +_DEBUG = "_ARC_DEBUG" in os.environ + +debug_stream = sys.stderr + +def debug(*args): + if _DEBUG: + if USING_PYTHON2: + # debug_stream has to be binary mode in Python 2. + # Attempting to write unicode directly uses the default ascii conversion. + # Convert any unicode to bytes, leaving non-string input alone. + args = [ensure_bytes(x) if isinstance(x, str) else x for x in args] + print(file=debug_stream, *args) + +BASH_FILE_COMPLETION_FALLBACK = 79 +BASH_DIR_COMPLETION_FALLBACK = 80 + +safe_actions = (argparse._StoreAction, + argparse._StoreConstAction, + argparse._StoreTrueAction, + argparse._StoreFalseAction, + argparse._AppendAction, + argparse._AppendConstAction, + argparse._CountAction) + +@contextlib.contextmanager +def mute_stdout(): + stdout = sys.stdout + sys.stdout = open(os.devnull, "w") + try: + yield + finally: + sys.stdout = stdout + +@contextlib.contextmanager +def mute_stderr(): + stderr = sys.stderr + sys.stderr = open(os.devnull, "w") + try: + yield + finally: + sys.stderr.close() + sys.stderr = stderr + +class ArgcompleteException(Exception): + pass + +def split_line(line, point=None): + if point is None: + point = len(line) + lexer = shlex.shlex(line, posix=True) + lexer.whitespace_split = True + lexer.wordbreaks = os.environ.get("_ARGCOMPLETE_COMP_WORDBREAKS", "") + words = [] + + def split_word(word): + # TODO: make this less ugly + point_in_word = len(word) + point - lexer.instream.tell() + if isinstance(lexer.state, (str, bytes)) and lexer.state in lexer.whitespace: + point_in_word += 1 + if point_in_word > len(word): + debug("In trailing whitespace") + words.append(word) + word = "" + prefix, suffix = word[:point_in_word], word[point_in_word:] + prequote = "" + # posix + if lexer.state is not None and lexer.state in lexer.quotes: + prequote = lexer.state + # non-posix + # if len(prefix) > 0 and prefix[0] in lexer.quotes: + # prequote, prefix = prefix[0], prefix[1:] + + return prequote, prefix, suffix, words, lexer.last_wordbreak_pos + + while True: + try: + word = lexer.get_token() + if word == lexer.eof: + # TODO: check if this is ever unsafe + # raise ArgcompleteException("Unexpected end of input") + return "", "", "", words, None + if lexer.instream.tell() >= point: + debug("word", word, "split, lexer state: '{s}'".format(s=lexer.state)) + return split_word(word) + words.append(word) + except ValueError: + debug("word", lexer.token, "split (lexer stopped, state: '{s}')".format(s=lexer.state)) + if lexer.instream.tell() >= point: + return split_word(lexer.token) + else: + msg = ("Unexpected internal state. " + "Please report this bug at https://github.com/kislyuk/argcomplete/issues.") + raise ArgcompleteException(msg) + +def default_validator(completion, prefix): + return completion.startswith(prefix) + +class CompletionFinder(object): + """ + Inherit from this class if you wish to override any of the stages below. Otherwise, use + ``argcomplete.autocomplete()`` directly (it's a convenience instance of this class). It has the same signature as + :meth:`CompletionFinder.__call__()`. + """ + def __init__(self, argument_parser=None, always_complete_options=True, exclude=None, validator=None, + print_suppressed=False, default_completer=FilesCompleter(), append_space=None): + self._parser = argument_parser + self.always_complete_options = always_complete_options + self.exclude = exclude + if validator is None: + validator = default_validator + self.validator = validator + self.print_suppressed = print_suppressed + self.completing = False + self._display_completions = {} + self.default_completer = default_completer + if append_space is None: + append_space = os.environ.get("_ARGCOMPLETE_SUPPRESS_SPACE") != "1" + self.append_space = append_space + + def __call__(self, argument_parser, always_complete_options=True, exit_method=os._exit, output_stream=None, + exclude=None, validator=None, print_suppressed=False, append_space=None, + default_completer=FilesCompleter()): + """ + :param argument_parser: The argument parser to autocomplete on + :type argument_parser: :class:`argparse.ArgumentParser` + :param always_complete_options: + Controls the autocompletion of option strings if an option string opening character (normally ``-``) has not + been entered. If ``True`` (default), both short (``-x``) and long (``--x``) option strings will be + suggested. If ``False``, no option strings will be suggested. If ``long``, long options and short options + with no long variant will be suggested. If ``short``, short options and long options with no short variant + will be suggested. + :type always_complete_options: boolean or string + :param exit_method: + Method used to stop the program after printing completions. Defaults to :meth:`os._exit`. If you want to + perform a normal exit that calls exit handlers, use :meth:`sys.exit`. + :type exit_method: callable + :param exclude: List of strings representing options to be omitted from autocompletion + :type exclude: iterable + :param validator: + Function to filter all completions through before returning (called with two string arguments, completion + and prefix; return value is evaluated as a boolean) + :type validator: callable + :param print_suppressed: + Whether or not to autocomplete options that have the ``help=argparse.SUPPRESS`` keyword argument set. + :type print_suppressed: boolean + :param append_space: + Whether to append a space to unique matches. The default is ``True``. + :type append_space: boolean + + .. note:: + If you are not subclassing CompletionFinder to override its behaviors, + use ``argcomplete.autocomplete()`` directly. It has the same signature as this method. + + Produces tab completions for ``argument_parser``. See module docs for more info. + + Argcomplete only executes actions if their class is known not to have side effects. Custom action classes can be + added to argcomplete.safe_actions, if their values are wanted in the ``parsed_args`` completer argument, or + their execution is otherwise desirable. + """ + self.__init__(argument_parser, always_complete_options=always_complete_options, exclude=exclude, + validator=validator, print_suppressed=print_suppressed, append_space=append_space, + default_completer=default_completer) + + if "_ARGCOMPLETE" not in os.environ: + # not an argument completion invocation + return + + global debug_stream + try: + debug_stream = os.fdopen(9, "w") + except: + debug_stream = sys.stderr + debug() + + if output_stream is None: + filename = os.environ.get("_ARGCOMPLETE_STDOUT_FILENAME") + if filename is not None: + debug("Using output file {}".format(filename)) + output_stream = open(filename, "wb") + + if output_stream is None: + try: + output_stream = os.fdopen(8, "wb") + except: + debug("Unable to open fd 8 for writing, quitting") + exit_method(1) + + # print("", stream=debug_stream) + # for v in "COMP_CWORD COMP_LINE COMP_POINT COMP_TYPE COMP_KEY _ARGCOMPLETE_COMP_WORDBREAKS COMP_WORDS".split(): + # print(v, os.environ[v], stream=debug_stream) + + ifs = os.environ.get("_ARGCOMPLETE_IFS", "\013") + if len(ifs) != 1: + debug("Invalid value for IFS, quitting [{v}]".format(v=ifs)) + exit_method(1) + + dfs = os.environ.get("_ARGCOMPLETE_DFS") + if dfs and len(dfs) != 1: + debug("Invalid value for DFS, quitting [{v}]".format(v=dfs)) + exit_method(1) + + comp_line = os.environ["COMP_LINE"] + comp_point = int(os.environ["COMP_POINT"]) + + comp_line = ensure_str(comp_line) + cword_prequote, cword_prefix, cword_suffix, comp_words, last_wordbreak_pos = split_line(comp_line, comp_point) + + # _ARGCOMPLETE is set by the shell script to tell us where comp_words + # should start, based on what we're completing. + # 1: <script> [args] + # 2: python <script> [args] + # 3: python -m <module> [args] + start = int(os.environ["_ARGCOMPLETE"]) - 1 + comp_words = comp_words[start:] + + if cword_prefix and cword_prefix[0] in self._parser.prefix_chars and "=" in cword_prefix: + # Special case for when the current word is "--optional=PARTIAL_VALUE". Give the optional to the parser. + comp_words.append(cword_prefix.split("=", 1)[0]) + + debug("\nLINE: {!r}".format(comp_line), + "\nPOINT: {!r}".format(comp_point), + "\nPREQUOTE: {!r}".format(cword_prequote), + "\nPREFIX: {!r}".format(cword_prefix), + "\nSUFFIX: {!r}".format(cword_suffix), + "\nWORDS:", comp_words) + + completions = self._get_completions(comp_words, cword_prefix, cword_prequote, last_wordbreak_pos) + + if dfs: + display_completions = {key_part: value.replace(ifs, " ") if value else "" + for key, value in self._display_completions.items() + for key_part in key} + completions = [dfs.join((key, display_completions.get(key) or "")) for key in completions] + + debug("\nReturning completions:", completions) + output_stream.write(ifs.join(completions).encode(sys_encoding)) + output_stream.flush() + debug_stream.flush() + exit_method(0) + + def _get_completions(self, comp_words, cword_prefix, cword_prequote, last_wordbreak_pos): + active_parsers = self._patch_argument_parser() + + parsed_args = argparse.Namespace() + self.completing = True + + if USING_PYTHON2: + # Python 2 argparse only properly works with byte strings. + comp_words = [ensure_bytes(word) for word in comp_words] + + try: + debug("invoking parser with", comp_words[1:]) + with mute_stderr(): + a = self._parser.parse_known_args(comp_words[1:], namespace=parsed_args) + debug("parsed args:", a) + except BaseException as e: + debug("\nexception", type(e), str(e), "while parsing args") + + self.completing = False + + if "--" in comp_words: + self.always_complete_options = False + + completions = self.collect_completions(active_parsers, parsed_args, cword_prefix, debug) + completions = self.filter_completions(completions) + completions = self.quote_completions(completions, cword_prequote, last_wordbreak_pos) + return completions + + def _patch_argument_parser(self): + """ + Since argparse doesn't support much introspection, we monkey-patch it to replace the parse_known_args method and + all actions with hooks that tell us which action was last taken or about to be taken, and let us have the parser + figure out which subparsers need to be activated (then recursively monkey-patch those). + We save all active ArgumentParsers to extract all their possible option names later. + """ + self.active_parsers = [] + self.visited_positionals = [] + + completer = self + + def patch(parser): + completer.visited_positionals.append(parser) + completer.active_parsers.append(parser) + + if isinstance(parser, IntrospectiveArgumentParser): + return + + classname = "MonkeyPatchedIntrospectiveArgumentParser" + if USING_PYTHON2: + classname = bytes(classname) + parser.__class__ = type(classname, (IntrospectiveArgumentParser, parser.__class__), {}) + + for action in parser._actions: + + if hasattr(action, "_orig_class"): + continue + + # TODO: accomplish this with super + class IntrospectAction(action.__class__): + def __call__(self, parser, namespace, values, option_string=None): + debug("Action stub called on", self) + debug("\targs:", parser, namespace, values, option_string) + debug("\torig class:", self._orig_class) + debug("\torig callable:", self._orig_callable) + + if not completer.completing: + self._orig_callable(parser, namespace, values, option_string=option_string) + elif issubclass(self._orig_class, argparse._SubParsersAction): + debug("orig class is a subparsers action: patching and running it") + patch(self._name_parser_map[values[0]]) + self._orig_callable(parser, namespace, values, option_string=option_string) + elif self._orig_class in safe_actions: + if not self.option_strings: + completer.visited_positionals.append(self) + + self._orig_callable(parser, namespace, values, option_string=option_string) + + action._orig_class = action.__class__ + action._orig_callable = action.__call__ + action.__class__ = IntrospectAction + + patch(self._parser) + + debug("Active parsers:", self.active_parsers) + debug("Visited positionals:", self.visited_positionals) + + return self.active_parsers + + def _get_subparser_completions(self, parser, cword_prefix): + def filter_aliases(aliases, prefix): + return tuple(x for x in aliases if x.startswith(prefix)) + + aliases_by_parser = {} + for key in parser.choices.keys(): + p = parser.choices[key] + aliases_by_parser.setdefault(p, []).append(key) + + for action in parser._get_subactions(): + subcmd_with_aliases = filter_aliases(aliases_by_parser[parser.choices[action.dest]], cword_prefix) + if subcmd_with_aliases: + self._display_completions[subcmd_with_aliases] = action.help + + completions = [subcmd for subcmd in parser.choices.keys() if subcmd.startswith(cword_prefix)] + return completions + + def _include_options(self, action, cword_prefix): + if len(cword_prefix) > 0 or self.always_complete_options is True: + return [ensure_str(opt) for opt in action.option_strings if ensure_str(opt).startswith(cword_prefix)] + long_opts = [ensure_str(opt) for opt in action.option_strings if len(opt) > 2] + short_opts = [ensure_str(opt) for opt in action.option_strings if len(opt) <= 2] + if self.always_complete_options == "long": + return long_opts if long_opts else short_opts + elif self.always_complete_options == "short": + return short_opts if short_opts else long_opts + return [] + + def _get_option_completions(self, parser, cword_prefix): + self._display_completions.update( + [[tuple(ensure_str(x) for x in action.option_strings + if ensure_str(x).startswith(cword_prefix)), action.help] + for action in parser._actions + if action.option_strings]) + + option_completions = [] + for action in parser._actions: + if not self.print_suppressed: + completer = getattr(action, "completer", None) + if isinstance(completer, SuppressCompleter) and completer.suppress(): + continue + if action.help == argparse.SUPPRESS: + continue + if not self._action_allowed(action, parser): + continue + if not isinstance(action, argparse._SubParsersAction): + option_completions += self._include_options(action, cword_prefix) + return option_completions + + @staticmethod + def _action_allowed(action, parser): + # Logic adapted from take_action in ArgumentParser._parse_known_args + # (members are saved by my_argparse.IntrospectiveArgumentParser) + for conflict_action in parser._action_conflicts.get(action, []): + if conflict_action in parser._seen_non_default_actions: + return False + return True + + def _complete_active_option(self, parser, next_positional, cword_prefix, parsed_args, completions): + debug("Active actions (L={l}): {a}".format(l=len(parser.active_actions), a=parser.active_actions)) + + isoptional = cword_prefix and cword_prefix[0] in parser.prefix_chars + optional_prefix = "" + greedy_actions = [x for x in parser.active_actions if action_is_greedy(x, isoptional)] + if greedy_actions: + assert len(greedy_actions) == 1, "expect at most 1 greedy action" + # This means the action will fail to parse if the word under the cursor is not given + # to it, so give it exclusive control over completions (flush previous completions) + debug("Resetting completions because", greedy_actions[0], "must consume the next argument") + self._display_completions = {} + completions = [] + elif isoptional: + if "=" in cword_prefix: + # Special case for when the current word is "--optional=PARTIAL_VALUE". + # The completer runs on PARTIAL_VALUE. The prefix is added back to the completions + # (and chopped back off later in quote_completions() by the COMP_WORDBREAKS logic). + optional_prefix, _, cword_prefix = cword_prefix.partition("=") + else: + # Only run completers if current word does not start with - (is not an optional) + return completions + + complete_remaining_positionals = False + # Use the single greedy action (if there is one) or all active actions. + for active_action in greedy_actions or parser.active_actions: + if not active_action.option_strings: # action is a positional + if action_is_open(active_action): + # Any positional arguments after this may slide down into this action + # if more arguments are added (since the user may not be done yet), + # so it is extremely difficult to tell which completers to run. + # Running all remaining completers will probably show more than the user wants + # but it also guarantees we won't miss anything. + complete_remaining_positionals = True + if not complete_remaining_positionals: + if action_is_satisfied(active_action) and not action_is_open(active_action): + debug("Skipping", active_action) + continue + + debug("Activating completion for", active_action, active_action._orig_class) + # completer = getattr(active_action, "completer", DefaultCompleter()) + completer = getattr(active_action, "completer", None) + + if completer is None: + if active_action.choices is not None and not isinstance(active_action, argparse._SubParsersAction): + completer = completers.ChoicesCompleter(active_action.choices) + elif not isinstance(active_action, argparse._SubParsersAction): + completer = self.default_completer + + if completer: + if isinstance(completer, SuppressCompleter) and completer.suppress(): + continue + + if callable(completer): + completions_from_callable = [c for c in completer( + prefix=cword_prefix, action=active_action, parser=parser, parsed_args=parsed_args) + if self.validator(c, cword_prefix)] + + if completions_from_callable: + completions += completions_from_callable + if isinstance(completer, completers.ChoicesCompleter): + self._display_completions.update( + [[(x,), active_action.help] for x in completions_from_callable]) + else: + self._display_completions.update( + [[(x,), ""] for x in completions_from_callable]) + else: + debug("Completer is not callable, trying the readline completer protocol instead") + for i in range(9999): + next_completion = completer.complete(cword_prefix, i) + if next_completion is None: + break + if self.validator(next_completion, cword_prefix): + self._display_completions.update({(next_completion,): ""}) + completions.append(next_completion) + if optional_prefix: + completions = [optional_prefix + "=" + completion for completion in completions] + debug("Completions:", completions) + return completions + + def collect_completions(self, active_parsers, parsed_args, cword_prefix, debug): + """ + Visits the active parsers and their actions, executes their completers or introspects them to collect their + option strings. Returns the resulting completions as a list of strings. + + This method is exposed for overriding in subclasses; there is no need to use it directly. + """ + completions = [] + + debug("all active parsers:", active_parsers) + active_parser = active_parsers[-1] + debug("active_parser:", active_parser) + if self.always_complete_options or (len(cword_prefix) > 0 and cword_prefix[0] in active_parser.prefix_chars): + completions += self._get_option_completions(active_parser, cword_prefix) + debug("optional options:", completions) + + next_positional = self._get_next_positional() + debug("next_positional:", next_positional) + + if isinstance(next_positional, argparse._SubParsersAction): + completions += self._get_subparser_completions(next_positional, cword_prefix) + + completions = self._complete_active_option(active_parser, next_positional, cword_prefix, parsed_args, + completions) + debug("active options:", completions) + debug("display completions:", self._display_completions) + + return completions + + def _get_next_positional(self): + """ + Get the next positional action if it exists. + """ + active_parser = self.active_parsers[-1] + last_positional = self.visited_positionals[-1] + + all_positionals = active_parser._get_positional_actions() + if not all_positionals: + return None + + if active_parser == last_positional: + return all_positionals[0] + + i = 0 + for i in range(len(all_positionals)): + if all_positionals[i] == last_positional: + break + + if i + 1 < len(all_positionals): + return all_positionals[i + 1] + + return None + + def filter_completions(self, completions): + """ + Ensures collected completions are Unicode text, de-duplicates them, and excludes those specified by ``exclude``. + Returns the filtered completions as an iterable. + + This method is exposed for overriding in subclasses; there is no need to use it directly. + """ + # On Python 2, we have to make sure all completions are unicode objects before we continue and output them. + # Otherwise, because python disobeys the system locale encoding and uses ascii as the default encoding, it will + # try to implicitly decode string objects using ascii, and fail. + completions = [ensure_str(c) for c in completions] + + # De-duplicate completions and remove excluded ones + if self.exclude is None: + self.exclude = set() + seen = set(self.exclude) + return [c for c in completions if c not in seen and not seen.add(c)] + + def quote_completions(self, completions, cword_prequote, last_wordbreak_pos): + """ + If the word under the cursor started with a quote (as indicated by a nonempty ``cword_prequote``), escapes + occurrences of that quote character in the completions, and adds the quote to the beginning of each completion. + Otherwise, escapes all characters that bash splits words on (``COMP_WORDBREAKS``), and removes portions of + completions before the first colon if (``COMP_WORDBREAKS``) contains a colon. + + If there is only one completion, and it doesn't end with a **continuation character** (``/``, ``:``, or ``=``), + adds a space after the completion. + + This method is exposed for overriding in subclasses; there is no need to use it directly. + """ + special_chars = "\\" + # If the word under the cursor was quoted, escape the quote char. + # Otherwise, escape all special characters and specially handle all COMP_WORDBREAKS chars. + if cword_prequote == "": + # Bash mangles completions which contain characters in COMP_WORDBREAKS. + # This workaround has the same effect as __ltrim_colon_completions in bash_completion + # (extended to characters other than the colon). + if last_wordbreak_pos: + completions = [c[last_wordbreak_pos + 1:] for c in completions] + special_chars += "();<>|&!`$* \t\n\"'" + elif cword_prequote == '"': + special_chars += '"`$!' + + if os.environ.get("_ARGCOMPLETE_SHELL") in ("tcsh", "fish"): + # tcsh and fish escapes special characters itself. + special_chars = "" + elif cword_prequote == "'": + # Nothing can be escaped in single quotes, so we need to close + # the string, escape the single quote, then open a new string. + special_chars = "" + completions = [c.replace("'", r"'\''") for c in completions] + + for char in special_chars: + completions = [c.replace(char, "\\" + char) for c in completions] + + if self.append_space: + # Similar functionality in bash was previously turned off by supplying the "-o nospace" option to complete. + # Now it is conditionally disabled using "compopt -o nospace" if the match ends in a continuation character. + # This code is retained for environments where this isn't done natively. + continuation_chars = "=/:" + if len(completions) == 1 and completions[0][-1] not in continuation_chars: + if cword_prequote == "": + completions[0] += " " + + return completions + + def rl_complete(self, text, state): + """ + Alternate entry point for using the argcomplete completer in a readline-based REPL. See also + `rlcompleter <https://docs.python.org/2/library/rlcompleter.html#completer-objects>`_. + Usage: + + .. code-block:: python + + import argcomplete, argparse, readline + parser = argparse.ArgumentParser() + ... + completer = argcomplete.CompletionFinder(parser) + readline.set_completer_delims("") + readline.set_completer(completer.rl_complete) + readline.parse_and_bind("tab: complete") + result = input("prompt> ") + + (Use ``raw_input`` instead of ``input`` on Python 2, or use `eight <https://github.com/kislyuk/eight>`_). + """ + if state == 0: + cword_prequote, cword_prefix, cword_suffix, comp_words, first_colon_pos = split_line(text) + comp_words.insert(0, sys.argv[0]) + matches = self._get_completions(comp_words, cword_prefix, cword_prequote, first_colon_pos) + self._rl_matches = [text + match[len(cword_prefix):] for match in matches] + + if state < len(self._rl_matches): + return self._rl_matches[state] + else: + return None + + def get_display_completions(self): + """ + This function returns a mapping of option names to their help strings for displaying to the user + + Usage: + + .. code-block:: python + + def display_completions(substitution, matches, longest_match_length): + _display_completions = argcomplete.autocomplete.get_display_completions() + print("") + if _display_completions: + help_len = [len(x) for x in _display_completions.values() if x] + + if help_len: + maxlen = max([len(x) for x in _display_completions]) + print("\\n".join("{0:{2}} -- {1}".format(k, v, maxlen) + for k, v in sorted(_display_completions.items()))) + else: + print(" ".join(k for k in sorted(_display_completions))) + else: + print(" ".join(x for x in sorted(matches))) + + import readline + print("cli /> {0}".format(readline.get_line_buffer()), end="") + readline.redisplay() + + ... + readline.set_completion_display_matches_hook(display_completions) + + """ + return {" ".join(k): v for k, v in self._display_completions.items()} + +class ExclusiveCompletionFinder(CompletionFinder): + @staticmethod + def _action_allowed(action, parser): + if not CompletionFinder._action_allowed(action, parser): + return False + + append_classes = (argparse._AppendAction, argparse._AppendConstAction) + if action._orig_class in append_classes: + return True + + if action not in parser._seen_non_default_actions: + return True + + return False + +autocomplete = CompletionFinder() +autocomplete.__doc__ = """ Use this to access argcomplete. See :meth:`argcomplete.CompletionFinder.__call__()`. """ + +def warn(*args): + """ + Prints **args** to standard error when running completions. This will interrupt the user's command line interaction; + use it to indicate an error condition that is preventing your completer from working. + """ + print("\n", file=debug_stream, *args)