def format_command_args(args): # type: (Union[List[str], CommandArgs]) -> str """ Format command arguments for display. """ # For HiddenText arguments, display the redacted form by calling str(). # Also, we don't apply str() to arguments that aren't HiddenText since # this can trigger a UnicodeDecodeError in Python 2 if the argument # has type unicode and includes a non-ascii character. (The type # checker doesn't ensure the annotations are correct in all cases.) return ' '.join( shlex_quote(str(arg)) if isinstance(arg, HiddenText ) else shlex_quote(arg) for arg in args)
def test_get_compile_command_with_files(tmpdir_cwd, filename): """ Test that get_compile_command returns a command with correct and sanitized file names. """ os.mkdir("sub") path = os.path.join("sub", filename) with open(path, "w"): pass args = [path, "--output-file", "requirements.txt"] with compile_cli.make_context("pip-compile", args) as ctx: assert get_compile_command( ctx ) == "pip-compile --output-file=requirements.txt {src_file}".format( src_file=shlex_quote(path) )
def format_command_args(args): # type: (List[str]) -> str """ Format command arguments for display. """ return ' '.join(shlex_quote(arg) for arg in args)
def get_compile_command(click_ctx): """ Returns a normalized compile command depending on cli context. The command will be normalized by: - expanding options short to long - removing values that are already default - sorting the arguments - removing one-off arguments like '--upgrade' - removing arguments that don't change build behaviour like '--verbose' """ from piptools.scripts.compile import cli # Map of the compile cli options (option name -> click.Option) compile_options = {option.name: option for option in cli.params} left_args = [] right_args = [] for option_name, value in click_ctx.params.items(): option = compile_options[option_name] # Collect variadic args separately, they will be added # at the end of the command later if option.nargs < 0: # These will necessarily be src_files # Re-add click-stripped '--' if any start with '-' if any(val.startswith("-") and val != "-" for val in value): right_args.append("--") right_args.extend([shlex_quote(force_text(val)) for val in value]) continue # Get the latest option name (usually it'll be a long name) option_long_name = option.opts[-1] # Exclude one-off options (--upgrade/--upgrade-package/--rebuild/...) # or options that don't change compile behaviour (--verbose/--dry-run/...) if option_long_name in COMPILE_EXCLUDE_OPTIONS: continue # Skip options without a value if option.default is None and not value: continue # Skip options with a default value if option.default == value: continue # Use a file name for file-like objects if isinstance(value, LazyFile): value = value.name # Convert value to the list if not isinstance(value, (tuple, list)): value = [value] for val in value: # Flags don't have a value, thus add to args true or false option long name if option.is_flag: # If there are false-options, choose an option name depending on a value if option.secondary_opts: # Get the latest false-option secondary_option_long_name = option.secondary_opts[-1] arg = option_long_name if val else secondary_option_long_name # There are no false-options, use true-option else: arg = option_long_name left_args.append(shlex_quote(arg)) # Append to args the option with a value else: if isinstance(val, six.string_types) and is_url(val): val = redact_auth_from_url(val) if option.name == "pip_args": # shlex_quote would produce functional but noisily quoted results, # e.g. --pip-args='--cache-dir='"'"'/tmp/with spaces'"'"'' # Instead, we try to get more legible quoting via repr: left_args.append("{option}={value}".format( option=option_long_name, value=repr(fs_str(force_text(val))))) else: left_args.append("{option}={value}".format( option=option_long_name, value=shlex_quote(force_text(val)))) return " ".join(["pip-compile"] + sorted(left_args) + sorted(right_args))