def get_subtopic_help(cmd: click.Command, ctx: click.Context, subtopic: str): """Get help for a command including only options that match a subtopic""" # set ctx.info_name or click prints the wrong usage str (usage for help instead of cmd) ctx.info_name = cmd.name usage_str = cmd.get_help(ctx) usage_str = usage_str.partition("\n")[0] info = cmd.to_info_dict(ctx) help_str = info.get("help", "") options = get_matching_options(cmd, ctx, subtopic) # format help text and options formatter = click.HelpFormatter() formatter.write(usage_str) formatter.write_paragraph() format_help_text(help_str, formatter) formatter.write_paragraph() if options: option_str = format_options_help(options, ctx, highlight=subtopic) formatter.write( f"Options that match '[highlight]{subtopic}[/highlight]':\n") formatter.write_paragraph() formatter.write(option_str) else: formatter.write( f"No options match '[highlight]{subtopic}[/highlight]'") return formatter.getvalue()
def __init__(self, *args, **kwargs): self.require = kwargs.pop("require", []) if isinstance(self.require, basestring): self.require = [ self.require, ] assert isinstance(self.require, (list, tuple)) Command.__init__(self, *args, **kwargs)
def _make_options(ctx: click.Context) -> List[str]: """Creates the markdown lines describing the options for the command""" formatter = ctx.make_formatter() Command.format_options(ctx.command, ctx, formatter) # First line is redundant "Options" # Last line is `--help` option_lines = formatter.getvalue().splitlines()[1:-1] if not option_lines: return [] return ["Options:", "```code", *option_lines, "```"]
def decorator(command: click.Command) -> click.Command: assert command.callback callback = command.callback command.params += options def call_with_blockchain_info(**params: Any) -> Callable: address_overwrites = { contract: value for contract, value in ( (contract, params.pop(param)) for contract, param in param_for_contract.items()) if value is not None } params["web3"], params["contracts"], params[ "start_block"] = connect_to_blockchain( eth_rpc=params.pop("eth_rpc"), gas_price_strategy=params.pop("gas_price"), used_contracts=contracts, address_overwrites=address_overwrites, development_environment=params.pop( "development_environment"), ) return callback(**params) command.callback = call_with_blockchain_info return command
def decorator(command: click.Command) -> click.Command: assert command.callback callback = command.callback command.params += options def call_with_blockchain_info(**params: Any) -> Callable: address_overwrites = { contract: value for contract, value in ( (contract, params.pop(param)) for contract, param in param_for_contract.items()) if value is not None } params['web3'], params['contracts'], params[ 'start_block'] = connect_to_blockchain( eth_rpc=params.pop('eth_rpc'), used_contracts=contracts, address_overwrites=address_overwrites, contracts_version=contracts_version, ) return callback(**params) command.callback = call_with_blockchain_info return command
def invoke(self, ctx): """'Fix' for Click not reading the '--version' or '--rename' flag without a sub command.""" if not ctx.protected_args and ( ("version" in ctx.params and ctx.params["version"]) or ("rename" in ctx.params and ctx.params["rename"])): return Command.invoke(self, ctx) return super().invoke(ctx)
class CaseMixin: ctx = Context(Command("Test")) def set_read_requirements_cases(self): # Paths Setup self.right_path_txt = Path("./tmp/right_path.txt") self.wrong_path_txt = Path("./tmp/not_found.txt") self.support_fmt_file = Path("./tmp/right_path.txt") self.unsupport_fmt_file = Path("./tmp/right_path.md") # Contents Setup self.formatted_content = """ numpy==1.16; (python<=3.6) numpy>1.19.0; (python>3.6) pandas==0.25.2 """ self.unformatted_content = ( """numpy==1.16\nnumpy>1.19.0\npandas==0.25.2; (numpy<=1.17)\nmatplotlib""" ) self.messy_content = """numpy==1.16; (python<=3.6) numpy>1.19.0; (python>3.6) scikit-learn==0.17.1;\n\tjoblib=0.16 \n\n\n\n\n\n\n\t\tpandas==0.25.2 """ def set_toml_at_root_cases(self): self.toml_present_path = "./tmp/pyproject.toml" self.toml_not_present_path = "./tmp/pyproject_not_present.toml" def set_in_pty_cases(self): self.return_zero_cmd1 = ["echo", "Hello", "world"] self.return_zero_cmd2 = "echo Hello world" self.return_error_cmd = ["echo Hello world"]
def add_command(self, cmd: click.Command, name: Optional[str] = None) -> None: if cmd.callback: # type: ignore cmd.callback = error_handler(should_exit=True)( cmd.callback) # type: ignore return super().add_command(cmd, name=name)
def _wrapper(command: click.Command): original_command = command.callback def _callback(*args, **kwargs): context = click.get_current_context() config = context.obj.config value = kwargs.get(param) if value is None: if (not hasattr(config, param) or getattr(config, param) is None): raise click.BadParameter( f"must provide {param}", context, get_param_obj(context, param), ) value = getattr(config, param) config.validate(param, value) return original_command(*args, **kwargs) command.callback = update_wrapper(_callback, original_command) return command
def _get_sub_commands(command: click.Command, ctx: click.Context) -> List[click.Command]: """Return subcommands of a Click command.""" subcommands = getattr(command, "commands", {}) if subcommands: return subcommands.values() if not isinstance(command, click.MultiCommand): return [] subcommands = [] for name in command.list_commands(ctx): subcommand = command.get_command(ctx, name) assert subcommand is not None subcommands.append(subcommand) return subcommands
def _format_subcommand( command: click.Command) -> ty.Generator[str, None, None]: """Format a sub-command of a `click.Command` or `click.Group`.""" yield '.. object:: {}'.format(command.name) short_help = command.get_short_help_str() if short_help: yield '' for line in statemachine.string2lines(short_help, tab_width=4, convert_whitespace=True): yield _indent(line)
def multi_instance(command: click.Command): """ decorator for a click command to allow multiple instances to be passed in """ original_command = command.callback def multi_callback(instance_names: List[str], *args, **kwargs): from gs_manager.servers import ( BaseServer, STATUS_SUCCESS, STATUS_FAILED, STATUS_PARTIAL_FAIL, ) context = click.get_current_context() server: BaseServer = context.obj if context.params.get("foreground"): raise click.ClickException( "cannot use @ options with the --foreground option") if context.params.get("parallel"): results = _run_parallel(original_command, instance_names, *args, **kwargs) else: results = _run_sync(original_command, instance_names, *args, **kwargs) server.logger.debug(f"results: {results}") partial_failed = results.count(STATUS_PARTIAL_FAIL) failed = results.count(STATUS_FAILED) return_code = STATUS_SUCCESS total = len(results) if failed > 0: server.logger.warning(f"{failed}/{total} return a failure code") return_code = STATUS_PARTIAL_FAIL if partial_failed > 0: server.logger.warning( f"{partial_failed}/{total} return a partial failure code") return_code = STATUS_PARTIAL_FAIL if failed == total: return_code = STATUS_FAILED return return_code wrapper_function = _instance_wrapper(original_command, multi_callback) command.callback = update_wrapper(wrapper_function, original_command) return command
def build_entry_point_args(command: click.Command, config: str, dry_run: Optional[str], integration_name: str, extra_args: Optional[str]) -> list[str]: args = ['--config', config] if dry_run is not None: args.append(dry_run) # if the integration_name is a known sub command, we add it right before the extra_args if integration_name and isinstance(command, click.MultiCommand) and \ command.get_command(None, integration_name): # type: ignore args.append(integration_name) if extra_args is not None: args.extend(extra_args.split()) return args
def single_instance(command: click.Command): """ decorator for a click command to enforce a single instance or zero instances are passed in """ original_command = command.callback def multi_callback(*args, **kwargs): raise click.ClickException("{} does not support @all".format( command.name)) wrapper_function = _instance_wrapper(original_command, multi_callback) command.callback = update_wrapper(wrapper_function, original_command) return command
def read_black_config(src: Path, value: Optional[str]) -> Dict[str, Union[bool, int]]: """Read the black configuration from pyproject.toml""" command = Command("main") context = Context(command) context.params["src"] = (str(src), ) parameter = Option(["--config"]) read_pyproject_toml(context, parameter, value) return { key: value for key, value in (context.default_map or {}).items() if key in ["line_length", "skip_string_normalization"] }
def _collect_params(cmd: click.Command, ctx: click.Context) -> Dict[str, Optional[str]]: params = ctx.params.copy() for param in cmd.get_params(ctx): if param.name not in params: continue if params[param.name] == param.get_default(ctx): # drop default param del params[param.name] continue if param.param_type_name != "option": # save name only params[param.name] = None else: if getattr(param, "secure", True): params[param.name] = None else: params[param.name] = str(params[param.name]) return params
def get_params(self, ctx): print("???") if not config_exists(): click.echo("WARNING NO CONFIG FILE FOUND!!!", err=True) result = click.prompt("WOULD YOU LIKE TO SETUP CONFIG NOW(y/n)?", type=click.Choice(['y', 'n'])) if result == "n": click.echo( "GOODBYE! you cannot continue without configuring the system", err=True) sys.exit(1) subprocess.Popen([sys.executable, sys.argv[0], 'runsetup'], stderr=sys.stderr, stdout=sys.stdout).communicate() if self.require: cfg = get_config() for item in self.require: print("CHK:", item, cfg.has_section(item)) if not cfg.has_section(item): cmd = globals().get('setup_' + item, None) if cmd: click.echo( "It appears your {0} is not setup".format(item)) result = click.prompt( "WOULD YOU LIKE TO SETUP {0} NOW(y/n)?".format( item), type=click.Choice(['y', 'n'])) if result == "n": click.echo( "GOODBYE! you cannot continue without configuring the system", err=True) sys.exit(1) print("SETUP {0} NOW".format(item)) subprocess.Popen( [sys.executable, sys.argv[0], cmd.name], stderr=sys.stderr, stdout=sys.stdout).communicate() else: raise Exception( "Cannot find setup_{0} method".format(item)) return Command.get_params(self, ctx)
def test_request_headers(scan_mock: Mock, client): c = Commit() c._patch = _SIMPLE_SECRET with Context(Command("bar"), info_name="bar") as ctx: ctx.parent = Context(Group("foo"), info_name="foo") c.scan( client=client, cache=Cache(), matches_ignore={}, all_policies=True, verbose=False, ) scan_mock.assert_called_with( ANY, { "GGShield-Version": __version__, "GGShield-Command-Path": "foo bar", }, )
def show_usage(cmd: click.Command): """ Show the relevant usage and exit. The actual usage message is also specific to incomplete commands, thanks to using the click context. """ ctx = click.get_current_context() # TODO: disabling this next line for the time being because of inconsistent # behavior between this function and calling --help directly, which would produce # different output. still have to figure that out # ctx.max_content_width = MAX_CONTENT_WIDTH formatter = ctx.make_formatter() cmd.format_help_text(ctx, formatter) cmd.format_options(ctx, formatter) cmd.format_epilog(ctx, formatter) click.echo(formatter.getvalue().rstrip("\n")) ctx.exit(2)
async def run( queue, ctx=Context(Command('run')), environment='', target=[], upload_port='', project_dir='.', project_conf='./platformio.ini', jobs=8, silent='', verbose='', disable_auto_clean='', ): saveStdout, saveStderr = sys.stdout, sys.stderr sys.stderr = MyStringIOERR(queue) sys.stdout = MyStringIO(queue) # sys.stderr,sys.stdout=logger,logger app.set_session_var("custom_project_conf", project_conf) # find project directory on upper level if isfile(project_dir): project_dir = find_project_dir_above(project_dir) is_test_running = False # CTX_META_TEST_IS_RUNNING in ctx.meta with fs.cd(project_dir): config = ProjectConfig.get_instance(project_conf) config.validate(environment) # clean obsolete build dir if not disable_auto_clean: build_dir = config.get_optional_dir("build") try: clean_build_dir(build_dir, config) except: # pylint: disable=bare-except click.secho( "Can not remove temporary directory `%s`. Please remove " "it manually to avoid build issues" % build_dir, fg="yellow", ) handle_legacy_libdeps(project_dir, config) default_envs = config.default_envs() results = [] for env in config.envs(): skipenv = any([ environment and env not in environment, not environment and default_envs and env not in default_envs, ]) if skipenv: results.append({"env": env}) continue # print empty line between multi environment project if not silent and any( r.get("succeeded") is not None for r in results): click.echo() results.append( process_env( ctx, env, config, environment, target, upload_port, silent, verbose, jobs, is_test_running, )) command_failed = any(r.get("succeeded") is False for r in results) if not is_test_running and (command_failed or not silent) and len(results) > 1: print_processing_summary(results) # sys.stdout,sys.stderr=saveStdout,saveStderr queue.put("QUIT") if command_failed: raise exception.ReturnErrorCode(1) return True
def click_ctx(): """ A dummy Click context to allow testing of methods that raise exceptions. Fixes Click capturing actual exceptions and raising its own `RuntimeError: There is no active click context`. """ return Context(Command('cmd'))
def init_cron(self): if self.cron is None: cron = super().init_cron() self.app.cli.add_command(Command('cron', callback=cron.run)) return cron
def test_create_app_instance_creates_flask_instance(): u"""Check that :func:`_create_app_instance` creates a Flask instance.""" with Context(Command("")): application = _create_app_instance(ScriptInfo()) assert isinstance(application, Flask)
def get_docs_for_click( *, obj: Command, ctx: typer.Context, indent: int = 0, name: str = "", call_prefix: str = "", ) -> str: docs = "#" * (1 + indent) command_name = name or obj.name if call_prefix: command_name = f"{call_prefix} {command_name}" title = f"`{command_name}`" if command_name else "CLI" docs += f" {title}\n\n" if obj.help: docs += f"{obj.help}\n\n" usage_pieces = obj.collect_usage_pieces(ctx) if usage_pieces: docs += "**Usage**:\n\n" docs += "```console\n" docs += "$ " if command_name: docs += f"{command_name} " docs += f"{' '.join(usage_pieces)}\n" docs += "```\n\n" args = [] opts = [] for param in obj.get_params(ctx): rv = param.get_help_record(ctx) if rv is not None: if param.param_type_name == "argument": args.append(rv) elif param.param_type_name == "option": opts.append(rv) if args: docs += f"**Arguments**:\n\n" for arg_name, arg_help in args: docs += f"* `{arg_name}`" if arg_help: docs += f": {arg_help}" docs += "\n" docs += "\n" if opts: docs += f"**Options**:\n\n" for opt_name, opt_help in opts: docs += f"* `{opt_name}`" if opt_help: docs += f": {opt_help}" docs += "\n" docs += "\n" if obj.epilog: docs += f"{obj.epilog}\n\n" if isinstance(obj, Group): group: Group = cast(Group, obj) commands = group.list_commands(ctx) if commands: docs += f"**Commands**:\n\n" for command in commands: command_obj = group.get_command(ctx, command) assert command_obj docs += f"* `{command_obj.name}`" command_help = command_obj.get_short_help_str() if command_help: docs += f": {command_help}" docs += "\n" docs += "\n" for command in commands: command_obj = group.get_command(ctx, command) assert command_obj use_prefix = "" if command_name: use_prefix += f"{command_name}" docs += get_docs_for_click( obj=command_obj, ctx=ctx, indent=indent + 1, call_prefix=use_prefix ) return docs
def init_app(self, app): self.app = app app.extensions['cron'] = self app.cli.add_command(Command('cron', callback=self.run))