def test_auto_default_option( file_regression: FileRegressionFixture, cli_runner: CliRunner, ): @auto_default_option( "--width", type=click.INT, help="The max width to display.", show_default=True, ) @click_command() def main(width: int = 80): print(width) argument = main.params[0] assert argument.default == 80 assert not argument.required assert argument.show_default # type: ignore result = cli_runner.invoke(main, args="--help") result.check_stdout(file_regression, extension=".md") assert result.exit_code == 0 result = cli_runner.invoke(main, catch_exceptions=False) assert result.stdout.rstrip() == "80" assert result.exit_code == 0 for width in [0, 8, 36, 48, 130]: result = cli_runner.invoke(main, args=["--width", str(width)]) assert result.stdout.rstrip() == str(width) assert result.exit_code == 0
def test_multi_value_option(cli_runner: CliRunner): @click.option( "--select", type=click.STRING, help="The checks to enable", cls=MultiValueOption, ) @colour_option() @click_command() def main(select: Iterable[str], colour: bool): select = list(select) print(*select) print(", ".join(select)) result: Result = cli_runner.invoke(main, catch_exceptions=False) assert result.stdout.rstrip() == '' assert result.exit_code == 0 result = cli_runner.invoke(main, args=["--select", "E102", "F223"]) assert result.stdout.rstrip() == "E102 F223\nE102, F223" assert result.exit_code == 0 result = cli_runner.invoke(main, args=["--select", "E102", "F223", "--colour"]) assert result.stdout.rstrip() == "E102 F223\nE102, F223" assert result.exit_code == 0 result = cli_runner.invoke(main, args=["--select", "E102"]) assert result.stdout.rstrip() == "E102\nE102" assert result.exit_code == 0
def test_version_option(file_regression: FileRegressionFixture, cli_runner: CliRunner): def version_callback(ctx: click.Context, param: click.Option, value: int): if not value or ctx.resilient_parsing: return if value > 1: click.echo("consolekit version 1.2.3, Python 3.8.5") else: click.echo("consolekit version 1.2.3") ctx.exit() @version_option(version_callback) @click_command() def main(): sys.exit(1) result = cli_runner.invoke(main, args="--version") assert result.stdout.rstrip() == "consolekit version 1.2.3" assert result.exit_code == 0 result = cli_runner.invoke(main, args=["--version", "--version"]) assert result.stdout.rstrip() == "consolekit version 1.2.3, Python 3.8.5" assert result.exit_code == 0
def test_described_argument( file_regression: FileRegressionFixture, cli_runner: CliRunner, ): @click.argument( "dest", cls=DescribedArgument, type=click.STRING, description="The destination directory.", ) @click_command() def main(dest: str): print(dest) result = cli_runner.invoke(main, args="--help") result.check_stdout(file_regression, extension=".md") assert result.exit_code == 0 result = cli_runner.invoke(main, catch_exceptions=False, args="./staging") assert result.stdout.rstrip() == "./staging" assert result.exit_code == 0 ctx = click.Context(main, info_name="main", parent=None) argument = ctx.command.params[0] assert isinstance(argument, DescribedArgument) assert argument.description == "The destination directory."
def test_suggest_classifiers_add_existing(tmp_pathplus, advanced_file_regression: AdvancedFileRegressionFixture): (tmp_pathplus / "repo_helper.yml").write_lines([ "modname: repo_helper", 'copyright_years: "2020"', 'author: "Dominic Davis-Foster"', 'email: "*****@*****.**"', 'version: "0.0.1"', 'username: "******"', "license: 'LGPLv3+'", "short_desc: 'Update multiple configuration files, build scripts etc. from a single location.'", '', "classifiers:", " - 'Framework :: Flake8'", " - 'Intended Audience :: Developers'", ]) (tmp_pathplus / "requirements.txt").touch() (tmp_pathplus / "repo_helper").mkdir() with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke( suggest.classifiers, catch_exceptions=False, args=["-s", '4', "-l", "--add"] ) assert result.exit_code == 0 advanced_file_regression.check_file(tmp_pathplus / "repo_helper.yml")
def test_list_remotes(temp_repo, file_regression: FileRegressionFixture): with in_directory(temp_repo): runner = CliRunner() result: Result = runner.invoke(main, args="--list") assert result.exit_code == 0 check_file_regression(result.stdout, file_regression)
def test_cli( example_file, tmp_pathplus, file_regression: FileRegressionFixture, cli_runner: CliRunner, ): st = (example_file).stat() assert st == st time.sleep( 0.1 ) # the whole thing happens so quickly the mtime was ending up the same result: Result = cli_runner.invoke(main, catch_exceptions=False, args=[str(example_file)]) check_file_output(example_file, file_regression) assert result.exit_code == 1 # mtime should have changed new_st = (example_file).stat() assert new_st.st_mtime != st.st_mtime assert new_st != st # Calling a second time shouldn't change anything result = cli_runner.invoke(main, catch_exceptions=False, args=[str(example_file)]) check_file_output(example_file, file_regression) assert result.exit_code == 0 # mtime should be the same assert (example_file).stat().st_mtime == new_st.st_mtime assert (example_file).stat() == new_st
def test_devenv_verbose(temp_repo: Repo, extra_args, tests): lib_requirements = [ "click", "flask", "werkzeug", "consolekit", "requests", "apeye", ] test_requirements = [ "pytest", "hypothesis", ] repo_path = PathPlus(temp_repo.path) (repo_path / "requirements.txt").write_lines(lib_requirements) if tests: (repo_path / "tests").mkdir() (repo_path / "tests/requirements.txt").write_lines(test_requirements) else: with (repo_path / "repo_helper.yml").open('a') as fp: fp.write("enable_tests: false") with in_directory(temp_repo.path): runner = CliRunner() result: Result = runner.invoke(devenv, args=extra_args) assert result.exit_code == 0 assert "Installing project requirements" in result.stdout assert "Successfully created development virtualenv." in result.stdout if tests: assert "Installing test requirements" in result.stdout
def test_raw_help_group( file_regression: FileRegressionFixture, cli_runner: CliRunner, ): @click_group(cls=consolekit.commands.RawHelpGroup) def demo(): """ This is the summary line. This **program** does *the* ``following``: * This * That * ~~The other~~ (deprecated) """ @demo.command(cls=consolekit.commands.RawHelpCommand) def foo(): """ This is the summary line. This **program** does *the* ``following``: * This * That * ~~The other~~ (deprecated) """ result = cli_runner.invoke(demo, args=["--help"]) result.check_stdout(file_regression, extension="_group.md") result = cli_runner.invoke(foo, args=["--help"]) result.check_stdout(file_regression, extension="_command.md")
def test_mkrecipe_bad_type( tmp_pathplus, pyproject_file, advanced_file_regression: AdvancedFileRegressionFixture, click_ver, ): (tmp_pathplus / "pyproject.toml").write_text( (configs_dir / pyproject_file).read_text()) (tmp_pathplus / "requirements.txt").write_lines([ "click>=7.1.2", 'colorama>=0.4.3; python_version < "3.10"', "deprecation-alias>=0.1.1", "domdf-python-tools>=2.5.1", "mistletoe>=0.7.2", "typing-extensions>=3.7.4.3", ]) with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke(main, args=["--type", "egg"], catch_exceptions=False) assert result.exit_code == 2 result.check_stdout(advanced_file_regression)
def check_file(self, filename: str, mode: black.Mode, kwargs: dict, *, data: bool = True) -> None: source, expected = read_data(filename, data=data) result: Result with TemporaryPathPlus() as tmp_pathplus: (tmp_pathplus / filename).write_text(source) toml_data = dom_toml.load( PathPlus(__file__).parent / "example_formate.toml") toml_data["hooks"]["black"]["kwargs"] = kwargs dom_toml.dump(toml_data, tmp_pathplus / "formate.toml") with in_directory(tmp_pathplus): runner = CliRunner(mix_stderr=False) result = runner.invoke( main, args=[ filename, "--no-colour", "--diff", "--verbose", "-v" ], ) # TODO: check stdout actual = (tmp_pathplus / filename).read_text() self.assertFormatEqual(expected, actual) if source != actual: black.assert_equivalent(source, actual) black.assert_stable(source, actual, mode)
def test_conda_recipe_specifiers( tmp_pathplus, file_regression: FileRegressionFixture, example_config, ): config = example_config.replace("repo_helper_demo", "repo_helper").replace("0.0.1", "2021.3.8") (tmp_pathplus / "repo_helper.yml").write_text(config) (tmp_pathplus / "requirements.txt").write_lines([ 'apeye>=0.3.0; python_version < "3.10"', "attrs[extra]>=20.2.0", ]) with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke(make_recipe, catch_exceptions=False) assert result.exit_code == 0 if os.sep == '/': assert re.match(r"Wrote recipe to .*/conda/meta\.yaml", result.stdout) elif os.sep == '\\': assert re.match(r"Wrote recipe to .*(\\)?conda\\meta\.yaml", result.stdout.splitlines()[0]) else: raise NotImplementedError(os.sep) check_file_output(tmp_pathplus / "conda/meta.yaml", file_regression)
def test_cli_syntax_error_py310( tmp_pathplus: PathPlus, advanced_file_regression: AdvancedFileRegressionFixture, advanced_data_regression: AdvancedDataRegressionFixture, demo_environment, ): code = [ "class F:", "\tfrom collections import (", "Iterable,", "\tCounter,", "\t\t)", '', "\tdef foo(self):", "\t\tpass", '', "print('hello world'", ] (tmp_pathplus / "code.py").write_lines(code, trailing_whitespace=True) with in_directory(tmp_pathplus): runner = CliRunner(mix_stderr=False) result: Result = runner.invoke( main, args=["code.py", "--no-colour", "--verbose"]) assert result.exit_code == 126 check_out(result, advanced_data_regression)
def test_suggestion_group( file_regression: FileRegressionFixture, cli_runner: CliRunner, ): @click_group(context_settings={ **CONTEXT_SETTINGS, "token_normalize_func": lambda x: x.lower() }) def demo(): """ A program. """ @demo.command() def search(): """ Conduct a search. """ result = cli_runner.invoke(demo, args=["searh"]) result.check_stdout(file_regression, extension="_success.md") assert result.exit_code == 2 result = cli_runner.invoke(demo, args=["list"]) result.check_stdout(file_regression, extension="_failure.md") assert result.exit_code == 2 result = cli_runner.invoke(demo, args=["SEARCH"]) assert not result.stdout.rstrip() assert result.exit_code == 0
def test_reformat( tmp_pathplus: PathPlus, toml_string: str, cli_runner: CliRunner, advanced_file_regression: AdvancedFileRegressionFixture, show_diff: bool, ): (tmp_pathplus / "pyproject.toml").write_clean(toml_string) (tmp_pathplus / "README.rst").write_clean("This is the README") (tmp_pathplus / "LICENSE").write_clean("This is the LICENSE") if show_diff: args = ["--no-colour", "--show-diff"] else: args = [] with in_directory(tmp_pathplus): result: Result = cli_runner.invoke(reformat, args=args, catch_exceptions=False) assert result.exit_code == 1 advanced_file_regression.check_file(tmp_pathplus / "pyproject.toml") result.check_stdout(advanced_file_regression, extension=".diff") # Should be no changes with in_directory(tmp_pathplus): result = cli_runner.invoke(reformat, args=args, catch_exceptions=False) assert result.exit_code == 0 advanced_file_regression.check_file(tmp_pathplus / "pyproject.toml") assert result.stdout == "Reformatting 'pyproject.toml'\n"
def test_devenv(temp_repo: Repo): lib_requirements = [ "click", "flask", "werkzeug", "consolekit", "requests", "apeye", ] test_requirements = [ "pytest", "hypothesis", ] repo_path = PathPlus(temp_repo.path) (repo_path / "requirements.txt").write_lines(lib_requirements) (repo_path / "tests").mkdir() (repo_path / "tests/requirements.txt").write_lines(test_requirements) with in_directory(temp_repo.path): runner = CliRunner() result: Result = runner.invoke(devenv) assert result.exit_code == 0 assert result.stdout == 'Successfully created development virtualenv.\n' # Check list of packages in virtualenv venv_dir = repo_path / "venv" if sys.platform == "win32": version_dirs = [(venv_dir / "Lib")] elif PYPY: version_dirs = [venv_dir] else: version_dirs = list((venv_dir / "lib").glob("py*")) for version_dir in version_dirs: for package in lib_requirements: assert (version_dir / "site-packages" / package).is_dir() for package in test_requirements: assert (version_dir / "site-packages" / package).is_dir() assert len(version_dirs) == 1 pyvenv_config: Dict[str, str] = read_pyvenv(venv_dir) assert "prompt" in pyvenv_config assert pyvenv_config["prompt"] == "(repo_helper_demo) " assert "repo_helper_devenv" in pyvenv_config assert pyvenv_config["repo_helper_devenv"] == __version__ assert "virtualenv" in pyvenv_config assert "include-system-site-packages" in pyvenv_config assert not strtobool(pyvenv_config["include-system-site-packages"])
def test_version(tmp_pathplus): with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke(devenv, args=["--version"]) assert result.exit_code == 0 assert result.stdout == f"repo_helper_devenv version {__version__}\n"
def test_toggle_errors(temp_repo): with in_directory(temp_repo): runner = CliRunner() result: Result = runner.invoke(main, args="ftp") assert result.exit_code == 2 error = "Error: Invalid value for '[[http|https|ssh]]': invalid choice: ftp. (choose from http, https, ssh, )" assert result.stdout.splitlines()[-1] == error
def test_bad_config_cli(tmp_pathplus: PathPlus, config: Dict, match: str): dom_toml.dump({"project": config}, tmp_pathplus / "pyproject.toml") with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke(main) assert result.exit_code == 1 assert match in result.stdout
def test_arbitrary_encoding(tmp_pathplus: PathPlus): path = tmp_pathplus / "f.py" contents = '# -*- coding: cp1252\nx = "£"'.encode("cp1252") path.write_bytes(contents) runner = CliRunner() result: Result = runner.invoke(main, args=[str(path)]) assert result.exit_code == 0
def test_integration(tmp_pathplus: PathPlus, contents, expected, expected_out): path = tmp_pathplus / "test.py" path.write_bytes(contents) runner = CliRunner() result: Result = runner.invoke(main, args=[str(path)]) assert result.exit_code == expected assert result.stdout == expected_out.format(filename=str(path))
def test_list_remotes_no_remotes(tmp_pathplus): Repo.init(tmp_pathplus) with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke(main, args="--list") assert result.exit_code == 1 assert result.stdout == "No remotes set!\nAborted!\n"
def test_version(tmp_pathplus, advanced_file_regression: AdvancedFileRegressionFixture): with in_directory(tmp_pathplus): runner = CliRunner() result: Result = runner.invoke(main, args=["--version"]) assert result.exit_code == 0 assert result.stdout == f"pyproject-devenv version {__version__}\n"
def test_integration(input_s, expected_retval, output, tmp_pathplus: PathPlus, cassette): path = tmp_pathplus / "file.txt" path.write_text(input_s) runner = CliRunner() result: Result = runner.invoke(main, args=[str(path)]) assert path.read_text() == output assert result.exit_code == expected_retval
def test_traceback_handler_show_traceback(exception, cli_runner: CliRunner): @click.command() def demo(): with handle_tracebacks(True, CustomTracebackHandler): raise exception with pytest.raises(type(exception), match=re.escape(str(exception))): cli_runner.invoke(demo, catch_exceptions=False)
def test_cli_version(tmp_pathplus: PathPlus) -> None: with in_directory(tmp_pathplus): runner = CliRunner(mix_stderr=False) result: Result = runner.invoke(main, args=["--version"]) assert not result.stderr assert fix_stdout(result.stdout) == "importcheck version 0.0.0" assert result.exit_code == 0
def test_bad_config_cli_traceback(tmp_pathplus: PathPlus, config: Dict, match: str): dom_toml.dump({"project": config}, tmp_pathplus / "pyproject.toml") with in_directory(tmp_pathplus): runner = CliRunner() with pytest.raises(BadConfigError, match=match): runner.invoke(main, args=["-T"])
def test_help(file_regression: FileRegressionFixture): runner = CliRunner() result: Result = runner.invoke(main, args="-h") assert result.exit_code == 0 result.check_stdout(file_regression) result = runner.invoke(main, args="--help") assert result.exit_code == 0 result.check_stdout(file_regression)
def test_cli_clear_cache( advanced_file_regression: AdvancedFileRegressionFixture) -> None: runner = CliRunner() result: Result = runner.invoke(main, catch_exceptions=False, args=["--clear-cache"]) assert result.exit_code == 0 result.check_stdout(advanced_file_regression)
def test_find_url(term: str, url: URL): runner = CliRunner() result: Result = runner.invoke( main, catch_exceptions=False, args=[term], ) assert result.exit_code == 0 assert result.stdout.strip() == str(url)