From a6113ea2d9902fa950ad11a2a81d0c2830fe5661 Mon Sep 17 00:00:00 2001 From: Fabio Todaro Date: Wed, 12 May 2021 15:25:36 +0200 Subject: [PATCH] Replace tmpdir in favour of tmp_path (#1545) * Remove tmpdir * Deduplicate fixtures * Fix lint --- tests/conftest.py | 32 +++++-- ...ermine_repository_should_use_local_repo.py | 24 ++--- tests/test_abort_generate_on_hook_error.py | 8 +- tests/test_cli.py | 24 ++--- tests/test_custom_extensions_in_hooks.py | 6 -- tests/test_default_extensions.py | 12 +-- tests/test_generate_files.py | 55 ++++++------ tests/test_generate_hooks.py | 36 ++++---- tests/test_hooks.py | 15 ++-- tests/test_log.py | 7 +- tests/test_specify_output_dir.py | 13 +-- tests/vcs/test_clone.py | 32 +++---- tests/zipfile/test_unzip.py | 90 +++++++------------ 13 files changed, 160 insertions(+), 194 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 57964f903..5f8bbddb4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -137,9 +137,9 @@ def restore_backup(): @pytest.fixture(scope='session') -def user_dir(tmpdir_factory): +def user_dir(tmp_path_factory): """Fixture that simulates the user's home directory.""" - return tmpdir_factory.mktemp('user_dir') + return tmp_path_factory.mktemp('user_dir') @pytest.fixture(scope='session') @@ -153,9 +153,10 @@ def user_config_data(user_dir): :returns: Dict with name of both user config dirs """ - cookiecutters_dir = user_dir.mkdir('cookiecutters') - replay_dir = user_dir.mkdir('cookiecutter_replay') - + cookiecutters_dir = user_dir.joinpath('cookiecutters') + cookiecutters_dir.mkdir() + replay_dir = user_dir.joinpath('cookiecutter_replay') + replay_dir.mkdir() return { 'cookiecutters_dir': str(cookiecutters_dir), 'replay_dir': str(replay_dir), @@ -173,8 +174,25 @@ def user_config_file(user_dir, user_config_data): :param user_config_data: Dict of config values :returns: String of path to config file """ - config_file = user_dir.join('config') + config_file = user_dir.joinpath('config') config_text = USER_CONFIG.format(**user_config_data) - config_file.write(config_text) + config_file.write_text(config_text) return str(config_file) + + +@pytest.fixture +def output_dir(tmp_path): + """Fixture to prepare test output directory.""" + output_path = tmp_path.joinpath("output") + output_path.mkdir() + return str(output_path) + + +@pytest.fixture +def clone_dir(tmp_path): + """Simulate creation of a directory called `clone_dir` inside of `tmp_path`. \ + Returns a str to said directory.""" + clone_dir = tmp_path.joinpath("clone_dir") + clone_dir.mkdir() + return clone_dir diff --git a/tests/repository/test_determine_repository_should_use_local_repo.py b/tests/repository/test_determine_repository_should_use_local_repo.py index 34c6b0a36..b61da5e09 100644 --- a/tests/repository/test_determine_repository_should_use_local_repo.py +++ b/tests/repository/test_determine_repository_should_use_local_repo.py @@ -1,18 +1,18 @@ """Tests around using locally cached cookiecutter template repositories.""" -import os +from pathlib import Path import pytest from cookiecutter import repository, exceptions -def test_finds_local_repo(tmpdir): +def test_finds_local_repo(tmp_path): """A valid local repository should be returned.""" project_dir, cleanup = repository.determine_repo_dir( 'tests/fake-repo', abbreviations={}, - clone_to_dir=str(tmpdir), + clone_to_dir=str(tmp_path), checkout=None, no_input=True, ) @@ -21,15 +21,15 @@ def test_finds_local_repo(tmpdir): assert not cleanup -def test_local_repo_with_no_context_raises(tmpdir): +def test_local_repo_with_no_context_raises(tmp_path): """A local repository without a cookiecutter.json should raise a \ `RepositoryNotFound` exception.""" - template_path = os.path.join('tests', 'fake-repo-bad') + template_path = str(Path('tests', 'fake-repo-bad')) with pytest.raises(exceptions.RepositoryNotFound) as err: repository.determine_repo_dir( template_path, abbreviations={}, - clone_to_dir=str(tmpdir), + clone_to_dir=str(tmp_path), checkout=None, no_input=True, ) @@ -38,20 +38,22 @@ def test_local_repo_with_no_context_raises(tmpdir): 'A valid repository for "{}" could not be found in the following ' 'locations:\n{}'.format( template_path, - '\n'.join([template_path, str(tmpdir / 'tests/fake-repo-bad')]), + '\n'.join( + [template_path, str(tmp_path.joinpath('tests', 'fake-repo-bad'))] + ), ) ) -def test_local_repo_typo(tmpdir): +def test_local_repo_typo(tmp_path): """An unknown local repository should raise a `RepositoryNotFound` \ exception.""" - template_path = os.path.join('tests', 'unknown-repo') + template_path = str(Path('tests', 'unknown-repo')) with pytest.raises(exceptions.RepositoryNotFound) as err: repository.determine_repo_dir( template_path, abbreviations={}, - clone_to_dir=str(tmpdir), + clone_to_dir=str(tmp_path), checkout=None, no_input=True, ) @@ -60,6 +62,6 @@ def test_local_repo_typo(tmpdir): 'A valid repository for "{}" could not be found in the following ' 'locations:\n{}'.format( template_path, - '\n'.join([template_path, str(tmpdir / 'tests/unknown-repo')]), + '\n'.join([template_path, str(tmp_path.joinpath('tests', 'unknown-repo'))]), ) ) diff --git a/tests/test_abort_generate_on_hook_error.py b/tests/test_abort_generate_on_hook_error.py index de1426834..8d4643361 100644 --- a/tests/test_abort_generate_on_hook_error.py +++ b/tests/test_abort_generate_on_hook_error.py @@ -16,7 +16,7 @@ ids=("pre_gen_hook_raises_error", "post_gen_hook_raises_error"), ) @pytest.mark.usefixtures("clean_system") -def test_hooks_raises_errors(tmpdir, abort_pre_gen, abort_post_gen): +def test_hooks_raises_errors(tmp_path, abort_pre_gen, abort_post_gen): """Verify pre- and pos-gen errors raises correct error code from script. This allows developers to make different error codes in their code, @@ -32,7 +32,9 @@ def test_hooks_raises_errors(tmpdir, abort_pre_gen, abort_post_gen): with pytest.raises(exceptions.FailedHookException) as error: generate.generate_files( - repo_dir="tests/hooks-abort-render", context=context, output_dir=str(tmpdir) + repo_dir="tests/hooks-abort-render", + context=context, + output_dir=str(tmp_path), ) assert error.value.code == 5 - assert not tmpdir.join("foobar").isdir() + assert not tmp_path.joinpath("foobar").is_dir() diff --git a/tests/test_cli.py b/tests/test_cli.py index 8be25b122..0da736ec2 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -238,12 +238,6 @@ def output_dir_flag(request): return request.param -@pytest.fixture -def output_dir(tmpdir): - """Pytest fixture return `output_dir` argument as string.""" - return str(tmpdir.mkdir('output')) - - def test_cli_output_dir(mocker, cli_runner, output_dir_flag, output_dir): """Test cli invocation with `output-dir` flag changes output directory.""" mock_cookiecutter = mocker.patch('cookiecutter.cli.cookiecutter') @@ -283,9 +277,9 @@ def test_cli_help(cli_runner, help_cli_flag): @pytest.fixture -def user_config_path(tmpdir): +def user_config_path(tmp_path): """Pytest fixture return `user_config` argument as string.""" - return str(tmpdir.join('tests/config.yaml')) + return str(tmp_path.joinpath("tests", "config.yaml")) def test_user_config(mocker, cli_runner, user_config_path): @@ -365,9 +359,8 @@ def test_default_user_config(mocker, cli_runner): ) -def test_echo_undefined_variable_error(tmpdir, cli_runner): +def test_echo_undefined_variable_error(output_dir, cli_runner): """Cli invocation return error if variable undefined in template.""" - output_dir = str(tmpdir.mkdir('output')) template_path = 'tests/undefined-variable/file-name/' result = cli_runner( @@ -396,9 +389,8 @@ def test_echo_undefined_variable_error(tmpdir, cli_runner): assert context_str in result.output -def test_echo_unknown_extension_error(tmpdir, cli_runner): +def test_echo_unknown_extension_error(output_dir, cli_runner): """Cli return error if extension incorrectly defined in template.""" - output_dir = str(tmpdir.mkdir('output')) template_path = 'tests/test-extensions/unknown/' result = cli_runner( @@ -434,9 +426,9 @@ def test_cli_extra_context_invalid_format(cli_runner): @pytest.fixture -def debug_file(tmpdir): +def debug_file(tmp_path): """Pytest fixture return `debug_file` argument as path object.""" - return tmpdir.join('fake-repo.log') + return tmp_path.joinpath('fake-repo.log') @pytest.mark.usefixtures('remove_fake_project_dir') @@ -458,7 +450,7 @@ def test_debug_file_non_verbose(cli_runner, debug_file): "DEBUG cookiecutter.main: context_file is " "tests/fake-repo-pre/cookiecutter.json" ) - assert context_log in debug_file.readlines(cr=False) + assert context_log in debug_file.read_text() assert context_log not in result.output @@ -485,7 +477,7 @@ def test_debug_file_verbose(cli_runner, debug_file): "DEBUG cookiecutter.main: context_file is " "tests/fake-repo-pre/cookiecutter.json" ) - assert context_log in debug_file.readlines(cr=False) + assert context_log in debug_file.read_text() assert context_log in result.output diff --git a/tests/test_custom_extensions_in_hooks.py b/tests/test_custom_extensions_in_hooks.py index 07314bd28..cd5f8aa3a 100644 --- a/tests/test_custom_extensions_in_hooks.py +++ b/tests/test_custom_extensions_in_hooks.py @@ -21,12 +21,6 @@ def template(request): return 'tests/test-extensions/' + request.param -@pytest.fixture -def output_dir(tmpdir): - """Fixture. Create and return custom temp directory for test.""" - return str(tmpdir.mkdir('hello')) - - @pytest.fixture(autouse=True) def modify_syspath(monkeypatch): """Fixture. Make sure that the custom extension can be loaded.""" diff --git a/tests/test_default_extensions.py b/tests/test_default_extensions.py index 8ee5bcfe7..e73ef9c1b 100644 --- a/tests/test_default_extensions.py +++ b/tests/test_default_extensions.py @@ -17,10 +17,10 @@ def freeze(): freezer.stop() -def test_jinja2_time_extension(tmpdir): +def test_jinja2_time_extension(tmp_path): """Verify Jinja2 time extension work correctly.""" project_dir = cookiecutter( - 'tests/test-extensions/default/', no_input=True, output_dir=str(tmpdir) + 'tests/test-extensions/default/', no_input=True, output_dir=str(tmp_path) ) changelog_file = os.path.join(project_dir, 'HISTORY.rst') assert os.path.isfile(changelog_file) @@ -40,19 +40,19 @@ def test_jinja2_time_extension(tmpdir): assert expected_lines == changelog_lines -def test_jinja2_slugify_extension(tmpdir): +def test_jinja2_slugify_extension(tmp_path): """Verify Jinja2 slugify extension work correctly.""" project_dir = cookiecutter( - 'tests/test-extensions/default/', no_input=True, output_dir=str(tmpdir) + 'tests/test-extensions/default/', no_input=True, output_dir=str(tmp_path) ) assert os.path.basename(project_dir) == "it-s-slugified-foobar" -def test_jinja2_uuid_extension(tmpdir): +def test_jinja2_uuid_extension(tmp_path): """Verify Jinja2 uuid extension work correctly.""" project_dir = cookiecutter( - 'tests/test-extensions/default/', no_input=True, output_dir=str(tmpdir) + 'tests/test-extensions/default/', no_input=True, output_dir=str(tmp_path) ) changelog_file = os.path.join(project_dir, 'id') assert os.path.isfile(changelog_file) diff --git a/tests/test_generate_files.py b/tests/test_generate_files.py index d666ee09d..4e21c7053 100644 --- a/tests/test_generate_files.py +++ b/tests/test_generate_files.py @@ -3,7 +3,6 @@ Use the global clean_system fixture and run additional teardown code to remove some special folders. """ -import os from pathlib import Path import pytest @@ -321,33 +320,32 @@ def undefined_context(): } -def test_raise_undefined_variable_file_name(tmpdir, undefined_context): +def test_raise_undefined_variable_file_name(output_dir, undefined_context): """Verify correct error raised when file name cannot be rendered.""" - output_dir = tmpdir.mkdir('output') - with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: generate.generate_files( repo_dir='tests/undefined-variable/file-name/', - output_dir=str(output_dir), + output_dir=output_dir, context=undefined_context, ) error = err.value assert "Unable to create file '{{cookiecutter.foobar}}'" == error.message assert error.context == undefined_context - assert not output_dir.join('testproject').exists() + assert not Path(output_dir).joinpath('testproject').exists() -def test_raise_undefined_variable_file_name_existing_project(tmpdir, undefined_context): +def test_raise_undefined_variable_file_name_existing_project( + output_dir, undefined_context +): """Verify correct error raised when file name cannot be rendered.""" - output_dir = tmpdir.mkdir('output') - - output_dir.join('testproject').mkdir() + testproj_path = Path(output_dir, 'testproject') + testproj_path.mkdir() with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: generate.generate_files( repo_dir='tests/undefined-variable/file-name/', - output_dir=str(output_dir), + output_dir=output_dir, context=undefined_context, overwrite_if_exists=True, ) @@ -355,69 +353,66 @@ def test_raise_undefined_variable_file_name_existing_project(tmpdir, undefined_c assert "Unable to create file '{{cookiecutter.foobar}}'" == error.message assert error.context == undefined_context - assert output_dir.join('testproject').exists() + assert testproj_path.exists() -def test_raise_undefined_variable_file_content(tmpdir, undefined_context): +def test_raise_undefined_variable_file_content(output_dir, undefined_context): """Verify correct error raised when file content cannot be rendered.""" - output_dir = tmpdir.mkdir('output') - with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: generate.generate_files( repo_dir='tests/undefined-variable/file-content/', - output_dir=str(output_dir), + output_dir=output_dir, context=undefined_context, ) error = err.value assert "Unable to create file 'README.rst'" == error.message assert error.context == undefined_context - assert not output_dir.join('testproject').exists() + assert not Path(output_dir).joinpath('testproject').exists() -def test_raise_undefined_variable_dir_name(tmpdir, undefined_context): +def test_raise_undefined_variable_dir_name(output_dir, undefined_context): """Verify correct error raised when directory name cannot be rendered.""" - output_dir = tmpdir.mkdir('output') - with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: generate.generate_files( repo_dir='tests/undefined-variable/dir-name/', - output_dir=str(output_dir), + output_dir=output_dir, context=undefined_context, ) error = err.value - directory = os.path.join('testproject', '{{cookiecutter.foobar}}') + directory = Path('testproject', '{{cookiecutter.foobar}}') msg = "Unable to create directory '{}'".format(directory) assert msg == error.message assert error.context == undefined_context - assert not output_dir.join('testproject').exists() + assert not Path(output_dir).joinpath('testproject').exists() -def test_raise_undefined_variable_dir_name_existing_project(tmpdir, undefined_context): +def test_raise_undefined_variable_dir_name_existing_project( + output_dir, undefined_context +): """Verify correct error raised when directory name cannot be rendered.""" - output_dir = tmpdir.mkdir('output') - - output_dir.join('testproject').mkdir() + testproj_path = Path(output_dir, 'testproject') + testproj_path.mkdir() with pytest.raises(exceptions.UndefinedVariableInTemplate) as err: generate.generate_files( repo_dir='tests/undefined-variable/dir-name/', - output_dir=str(output_dir), + output_dir=output_dir, context=undefined_context, overwrite_if_exists=True, ) error = err.value - directory = os.path.join('testproject', '{{cookiecutter.foobar}}') + directory = Path('testproject', '{{cookiecutter.foobar}}') msg = "Unable to create directory '{}'".format(directory) assert msg == error.message assert error.context == undefined_context - assert output_dir.join('testproject').exists() + assert testproj_path.exists() def test_raise_undefined_variable_project_dir(tmp_path): diff --git a/tests/test_generate_hooks.py b/tests/test_generate_hooks.py index 837f2c58a..9624bb8ae 100644 --- a/tests/test_generate_hooks.py +++ b/tests/test_generate_hooks.py @@ -12,14 +12,14 @@ @pytest.fixture(scope='function') -def remove_additional_folders(tmpdir): +def remove_additional_folders(tmp_path): """Remove some special folders which are created by the tests.""" yield directories_to_delete = [ 'tests/test-pyhooks/inputpyhooks', 'inputpyhooks', 'inputhooks', - os.path.join(str(tmpdir), 'test-shellhooks'), + tmp_path.joinpath('test-shellhooks'), 'tests/test-hooks', ] for directory in directories_to_delete: @@ -170,7 +170,7 @@ def test_run_failing_hook_preserves_existing_output_directory(): @pytest.mark.skipif(sys.platform.startswith('win'), reason="Linux only test") @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') -def test_run_shell_hooks(tmpdir): +def test_run_shell_hooks(tmp_path): """Verify pre and post generate project shell hooks executed. This test for .sh files. @@ -178,21 +178,21 @@ def test_run_shell_hooks(tmpdir): generate.generate_files( context={'cookiecutter': {'shellhooks': 'shellhooks'}}, repo_dir='tests/test-shellhooks/', - output_dir=os.path.join(str(tmpdir), 'test-shellhooks'), + output_dir=tmp_path.joinpath('test-shellhooks'), ) - shell_pre_file = os.path.join( - str(tmpdir), 'test-shellhooks', 'inputshellhooks', 'shell_pre.txt' + shell_pre_file = tmp_path.joinpath( + 'test-shellhooks', 'inputshellhooks', 'shell_pre.txt' ) - shell_post_file = os.path.join( - str(tmpdir), 'test-shellhooks', 'inputshellhooks', 'shell_post.txt' + shell_post_file = tmp_path.joinpath( + 'test-shellhooks', 'inputshellhooks', 'shell_post.txt' ) - assert os.path.exists(shell_pre_file) - assert os.path.exists(shell_post_file) + assert shell_pre_file.exists() + assert shell_post_file.exists() @pytest.mark.skipif(not sys.platform.startswith('win'), reason="Win only test") @pytest.mark.usefixtures('clean_system', 'remove_additional_folders') -def test_run_shell_hooks_win(tmpdir): +def test_run_shell_hooks_win(tmp_path): """Verify pre and post generate project shell hooks executed. This test for .bat files. @@ -200,16 +200,16 @@ def test_run_shell_hooks_win(tmpdir): generate.generate_files( context={'cookiecutter': {'shellhooks': 'shellhooks'}}, repo_dir='tests/test-shellhooks-win/', - output_dir=os.path.join(str(tmpdir), 'test-shellhooks-win'), + output_dir=tmp_path.joinpath('test-shellhooks-win'), ) - shell_pre_file = os.path.join( - str(tmpdir), 'test-shellhooks-win', 'inputshellhooks', 'shell_pre.txt' + shell_pre_file = tmp_path.joinpath( + 'test-shellhooks-win', 'inputshellhooks', 'shell_pre.txt' ) - shell_post_file = os.path.join( - str(tmpdir), 'test-shellhooks-win', 'inputshellhooks', 'shell_post.txt' + shell_post_file = tmp_path.joinpath( + 'test-shellhooks-win', 'inputshellhooks', 'shell_post.txt' ) - assert os.path.exists(shell_pre_file) - assert os.path.exists(shell_post_file) + assert shell_pre_file.exists() + assert shell_post_file.exists() @pytest.mark.usefixtures("clean_system", "remove_additional_folders") diff --git a/tests/test_hooks.py b/tests/test_hooks.py index ffcd00f85..d8b55dff2 100644 --- a/tests/test_hooks.py +++ b/tests/test_hooks.py @@ -232,9 +232,10 @@ def test_run_failing_hook(self): @pytest.fixture() -def dir_with_hooks(tmpdir): +def dir_with_hooks(tmp_path): """Yield a directory that contains hook backup files.""" - hooks_dir = tmpdir.mkdir('hooks') + hooks_dir = tmp_path.joinpath('hooks') + hooks_dir.mkdir() pre_hook_content = textwrap.dedent( """ @@ -243,7 +244,7 @@ def dir_with_hooks(tmpdir): print('pre_gen_project.py~') """ ) - pre_gen_hook_file = hooks_dir / 'pre_gen_project.py~' + pre_gen_hook_file = hooks_dir.joinpath('pre_gen_project.py~') pre_gen_hook_file.write_text(pre_hook_content, encoding='utf8') post_hook_content = textwrap.dedent( @@ -254,15 +255,15 @@ def dir_with_hooks(tmpdir): """ ) - post_gen_hook_file = hooks_dir / 'post_gen_project.py~' + post_gen_hook_file = hooks_dir.joinpath('post_gen_project.py~') post_gen_hook_file.write_text(post_hook_content, encoding='utf8') # Make sure to yield the parent directory as `find_hooks()` # looks into `hooks/` in the current working directory - yield str(tmpdir) + yield str(tmp_path) - pre_gen_hook_file.remove() - post_gen_hook_file.remove() + pre_gen_hook_file.unlink() + post_gen_hook_file.unlink() def test_ignore_hook_backup_files(monkeypatch, dir_with_hooks): diff --git a/tests/test_log.py b/tests/test_log.py index 4f4d9ffa9..3f38a090f 100644 --- a/tests/test_log.py +++ b/tests/test_log.py @@ -58,9 +58,9 @@ def debug_logger(): @pytest.fixture -def debug_file(tmpdir): +def debug_file(tmp_path): """Fixture. Generate debug file location for tests.""" - return tmpdir / 'pytest-plugin.log' + return tmp_path.joinpath('pytest-plugin.log') @pytest.fixture @@ -117,4 +117,5 @@ def test_debug_file_logging(caplog, info_logger_with_file, debug_file, debug_mes assert debug_file.exists() # Last line in the log file is an empty line - assert debug_file.readlines(cr=False) == debug_messages + [''] + with debug_file.open() as f: + assert f.read().split('\n') == debug_messages + [''] diff --git a/tests/test_specify_output_dir.py b/tests/test_specify_output_dir.py index 1636aa528..56c9eda6a 100644 --- a/tests/test_specify_output_dir.py +++ b/tests/test_specify_output_dir.py @@ -18,16 +18,11 @@ def context(): @pytest.fixture -def output_dir(tmpdir): - """Fixture to prepare test output directory.""" - return str(tmpdir.mkdir('output')) - - -@pytest.fixture -def template(tmpdir): +def template(tmp_path): """Fixture to prepare test template directory.""" - template_dir = tmpdir.mkdir('template') - template_dir.join('cookiecutter.json').ensure(file=True) + template_dir = tmp_path.joinpath("template") + template_dir.mkdir() + template_dir.joinpath('cookiecutter.json').touch() return str(template_dir) diff --git a/tests/vcs/test_clone.py b/tests/vcs/test_clone.py index 8be72cac0..9e3b78496 100644 --- a/tests/vcs/test_clone.py +++ b/tests/vcs/test_clone.py @@ -7,13 +7,6 @@ from cookiecutter import exceptions, vcs -@pytest.fixture -def clone_dir(tmpdir): - """Simulate creation of a directory called `clone_dir` inside of `tmpdir`. \ - Returns a str to said directory.""" - return str(tmpdir.mkdir('clone_dir')) - - def test_clone_should_raise_if_vcs_not_installed(mocker, clone_dir): """In `clone()`, a `VCSNotInstalled` exception should be raised if no VCS \ is installed.""" @@ -22,7 +15,7 @@ def test_clone_should_raise_if_vcs_not_installed(mocker, clone_dir): repo_url = 'https://github.com/pytest-dev/cookiecutter-pytest-plugin.git' with pytest.raises(exceptions.VCSNotInstalled): - vcs.clone(repo_url, clone_to_dir=clone_dir) + vcs.clone(repo_url, clone_to_dir=str(clone_dir)) def test_clone_should_rstrip_trailing_slash_in_repo_url(mocker, clone_dir): @@ -34,16 +27,16 @@ def test_clone_should_rstrip_trailing_slash_in_repo_url(mocker, clone_dir): 'cookiecutter.vcs.subprocess.check_output', autospec=True, ) - vcs.clone('https://github.com/foo/bar/', clone_to_dir=clone_dir, no_input=True) + vcs.clone('https://github.com/foo/bar/', clone_to_dir=str(clone_dir), no_input=True) mock_subprocess.assert_called_once_with( ['git', 'clone', 'https://github.com/foo/bar'], - cwd=clone_dir, + cwd=str(clone_dir), stderr=subprocess.STDOUT, ) -def test_clone_should_abort_if_user_does_not_want_to_reclone(mocker, tmpdir): +def test_clone_should_abort_if_user_does_not_want_to_reclone(mocker, clone_dir): """In `clone()`, if user doesn't want to reclone, Cookiecutter should exit \ without cloning anything.""" mocker.patch('cookiecutter.vcs.is_vcs_installed', autospec=True, return_value=True) @@ -54,15 +47,14 @@ def test_clone_should_abort_if_user_does_not_want_to_reclone(mocker, tmpdir): 'cookiecutter.vcs.subprocess.check_output', autospec=True, ) - clone_to_dir = tmpdir.mkdir('clone') - # Create repo_dir to trigger prompt_and_delete - clone_to_dir.mkdir('cookiecutter-pytest-plugin') + repo_dir = clone_dir.joinpath('cookiecutter-pytest-plugin') + repo_dir.mkdir() repo_url = 'https://github.com/pytest-dev/cookiecutter-pytest-plugin.git' with pytest.raises(SystemExit): - vcs.clone(repo_url, clone_to_dir=str(clone_to_dir)) + vcs.clone(repo_url, clone_to_dir=str(clone_dir)) assert not mock_subprocess.called @@ -96,13 +88,13 @@ def test_clone_should_invoke_vcs_command( branch = 'foobar' repo_dir = vcs.clone( - repo_url, checkout=branch, clone_to_dir=clone_dir, no_input=True + repo_url, checkout=branch, clone_to_dir=str(clone_dir), no_input=True ) assert repo_dir == expected_repo_dir mock_subprocess.assert_any_call( - [repo_type, 'clone', repo_url], cwd=clone_dir, stderr=subprocess.STDOUT + [repo_type, 'clone', repo_url], cwd=str(clone_dir), stderr=subprocess.STDOUT ) mock_subprocess.assert_any_call( [repo_type, 'checkout', branch], cwd=expected_repo_dir, stderr=subprocess.STDOUT @@ -132,7 +124,7 @@ def test_clone_handles_repo_typo(mocker, clone_dir, error_message): repository_url = 'https://github.com/hackebro/cookiedozer' with pytest.raises(exceptions.RepositoryNotFound) as err: - vcs.clone(repository_url, clone_to_dir=clone_dir, no_input=True) + vcs.clone(repository_url, clone_to_dir=str(clone_dir), no_input=True) assert str(err.value) == ( 'The repository {} could not be found, have you made a typo?' @@ -161,7 +153,7 @@ def test_clone_handles_branch_typo(mocker, clone_dir, error_message): with pytest.raises(exceptions.RepositoryCloneFailed) as err: vcs.clone( repository_url, - clone_to_dir=clone_dir, + clone_to_dir=str(clone_dir), checkout='unknown_branch', no_input=True, ) @@ -187,6 +179,6 @@ def test_clone_unknown_subprocess_error(mocker, clone_dir): with pytest.raises(subprocess.CalledProcessError): vcs.clone( 'https://github.com/pytest-dev/cookiecutter-pytest-plugin', - clone_to_dir=clone_dir, + clone_to_dir=str(clone_dir), no_input=True, ) diff --git a/tests/zipfile/test_unzip.py b/tests/zipfile/test_unzip.py index 14f6582a8..5135f4eec 100644 --- a/tests/zipfile/test_unzip.py +++ b/tests/zipfile/test_unzip.py @@ -16,34 +16,30 @@ def mock_download(): chunk = zf.read(1024) -def test_unzip_local_file(mocker, tmpdir): +def test_unzip_local_file(mocker, clone_dir): """Local file reference can be unzipped.""" mock_prompt_and_delete = mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True ) - clone_to_dir = tmpdir.mkdir('clone') - output_dir = zipfile.unzip( - 'tests/files/fake-repo-tmpl.zip', is_url=False, clone_to_dir=str(clone_to_dir) + 'tests/files/fake-repo-tmpl.zip', is_url=False, clone_to_dir=str(clone_dir) ) assert output_dir.startswith(tempfile.gettempdir()) assert not mock_prompt_and_delete.called -def test_unzip_protected_local_file_environment_password(mocker, tmpdir): +def test_unzip_protected_local_file_environment_password(mocker, clone_dir): """In `unzip()`, the environment can be used to provide a repo password.""" mock_prompt_and_delete = mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True ) - clone_to_dir = tmpdir.mkdir('clone') - output_dir = zipfile.unzip( 'tests/files/protected-fake-repo-tmpl.zip', is_url=False, - clone_to_dir=str(clone_to_dir), + clone_to_dir=str(clone_dir), password='sekrit', ) @@ -51,60 +47,54 @@ def test_unzip_protected_local_file_environment_password(mocker, tmpdir): assert not mock_prompt_and_delete.called -def test_unzip_protected_local_file_bad_environment_password(mocker, tmpdir): +def test_unzip_protected_local_file_bad_environment_password(mocker, clone_dir): """In `unzip()`, an error occurs if the environment has a bad password.""" mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True ) - clone_to_dir = tmpdir.mkdir('clone') - with pytest.raises(InvalidZipRepository): zipfile.unzip( 'tests/files/protected-fake-repo-tmpl.zip', is_url=False, - clone_to_dir=str(clone_to_dir), + clone_to_dir=str(clone_dir), password='not-the-right-password', ) -def test_unzip_protected_local_file_user_password_with_noinput(mocker, tmpdir): +def test_unzip_protected_local_file_user_password_with_noinput(mocker, clone_dir): """Can't unpack a password-protected repo in no_input mode.""" mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True ) - clone_to_dir = tmpdir.mkdir('clone') - with pytest.raises(InvalidZipRepository): zipfile.unzip( 'tests/files/protected-fake-repo-tmpl.zip', is_url=False, - clone_to_dir=str(clone_to_dir), + clone_to_dir=str(clone_dir), no_input=True, ) -def test_unzip_protected_local_file_user_password(mocker, tmpdir): +def test_unzip_protected_local_file_user_password(mocker, clone_dir): """A password-protected local file reference can be unzipped.""" mock_prompt_and_delete = mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True ) mocker.patch('cookiecutter.zipfile.read_repo_password', return_value='sekrit') - clone_to_dir = tmpdir.mkdir('clone') - output_dir = zipfile.unzip( 'tests/files/protected-fake-repo-tmpl.zip', is_url=False, - clone_to_dir=str(clone_to_dir), + clone_to_dir=str(clone_dir), ) assert output_dir.startswith(tempfile.gettempdir()) assert not mock_prompt_and_delete.called -def test_unzip_protected_local_file_user_bad_password(mocker, tmpdir): +def test_unzip_protected_local_file_user_bad_password(mocker, clone_dir): """Error in `unzip()`, if user can't provide a valid password.""" mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True @@ -113,59 +103,51 @@ def test_unzip_protected_local_file_user_bad_password(mocker, tmpdir): 'cookiecutter.zipfile.read_repo_password', return_value='not-the-right-password' ) - clone_to_dir = tmpdir.mkdir('clone') - with pytest.raises(InvalidZipRepository): zipfile.unzip( 'tests/files/protected-fake-repo-tmpl.zip', is_url=False, - clone_to_dir=str(clone_to_dir), + clone_to_dir=str(clone_dir), ) -def test_empty_zip_file(mocker, tmpdir): +def test_empty_zip_file(mocker, clone_dir): """In `unzip()`, an empty file raises an error.""" mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True ) - clone_to_dir = tmpdir.mkdir('clone') - with pytest.raises(InvalidZipRepository): zipfile.unzip( - 'tests/files/empty.zip', is_url=False, clone_to_dir=str(clone_to_dir) + 'tests/files/empty.zip', is_url=False, clone_to_dir=str(clone_dir) ) -def test_non_repo_zip_file(mocker, tmpdir): +def test_non_repo_zip_file(mocker, clone_dir): """In `unzip()`, a repository must have a top level directory.""" mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True ) - clone_to_dir = tmpdir.mkdir('clone') - with pytest.raises(InvalidZipRepository): zipfile.unzip( - 'tests/files/not-a-repo.zip', is_url=False, clone_to_dir=str(clone_to_dir) + 'tests/files/not-a-repo.zip', is_url=False, clone_to_dir=str(clone_dir) ) -def test_bad_zip_file(mocker, tmpdir): +def test_bad_zip_file(mocker, clone_dir): """In `unzip()`, a corrupted zip file raises an error.""" mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True ) - clone_to_dir = tmpdir.mkdir('clone') - with pytest.raises(InvalidZipRepository): zipfile.unzip( - 'tests/files/bad-zip-file.zip', is_url=False, clone_to_dir=str(clone_to_dir) + 'tests/files/bad-zip-file.zip', is_url=False, clone_to_dir=str(clone_dir) ) -def test_unzip_url(mocker, tmpdir): +def test_unzip_url(mocker, clone_dir): """In `unzip()`, a url will be downloaded and unzipped.""" mock_prompt_and_delete = mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True @@ -178,19 +160,17 @@ def test_unzip_url(mocker, tmpdir): 'cookiecutter.zipfile.requests.get', return_value=request, autospec=True, ) - clone_to_dir = tmpdir.mkdir('clone') - output_dir = zipfile.unzip( 'https://example.com/path/to/fake-repo-tmpl.zip', is_url=True, - clone_to_dir=str(clone_to_dir), + clone_to_dir=str(clone_dir), ) assert output_dir.startswith(tempfile.gettempdir()) assert not mock_prompt_and_delete.called -def test_unzip_url_existing_cache(mocker, tmpdir): +def test_unzip_url_existing_cache(mocker, clone_dir): """Url should be downloaded and unzipped, old zip file will be removed.""" mock_prompt_and_delete = mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', return_value=True, autospec=True @@ -203,23 +183,21 @@ def test_unzip_url_existing_cache(mocker, tmpdir): 'cookiecutter.zipfile.requests.get', return_value=request, autospec=True, ) - clone_to_dir = tmpdir.mkdir('clone') - # Create an existing cache of the zipfile - existing_zip = clone_to_dir.join('fake-repo-tmpl.zip') - existing_zip.write('This is an existing zipfile') + existing_zip = clone_dir.joinpath('fake-repo-tmpl.zip') + existing_zip.write_text('This is an existing zipfile') output_dir = zipfile.unzip( 'https://example.com/path/to/fake-repo-tmpl.zip', is_url=True, - clone_to_dir=str(clone_to_dir), + clone_to_dir=str(clone_dir), ) assert output_dir.startswith(tempfile.gettempdir()) assert mock_prompt_and_delete.call_count == 1 -def test_unzip_url_existing_cache_no_input(mocker, tmpdir): +def test_unzip_url_existing_cache_no_input(mocker, clone_dir): """If no_input is provided, the existing file should be removed.""" request = mocker.MagicMock() request.iter_content.return_value = mock_download() @@ -228,23 +206,21 @@ def test_unzip_url_existing_cache_no_input(mocker, tmpdir): 'cookiecutter.zipfile.requests.get', return_value=request, autospec=True, ) - clone_to_dir = tmpdir.mkdir('clone') - # Create an existing cache of the zipfile - existing_zip = clone_to_dir.join('fake-repo-tmpl.zip') - existing_zip.write('This is an existing zipfile') + existing_zip = clone_dir.joinpath('fake-repo-tmpl.zip') + existing_zip.write_text('This is an existing zipfile') output_dir = zipfile.unzip( 'https://example.com/path/to/fake-repo-tmpl.zip', is_url=True, - clone_to_dir=str(clone_to_dir), + clone_to_dir=str(clone_dir), no_input=True, ) assert output_dir.startswith(tempfile.gettempdir()) -def test_unzip_should_abort_if_no_redownload(mocker, tmpdir): +def test_unzip_should_abort_if_no_redownload(mocker, clone_dir): """Should exit without cloning anything If no redownload.""" mocker.patch( 'cookiecutter.zipfile.prompt_and_delete', side_effect=SystemExit, autospec=True @@ -254,15 +230,13 @@ def test_unzip_should_abort_if_no_redownload(mocker, tmpdir): 'cookiecutter.zipfile.requests.get', autospec=True, ) - clone_to_dir = tmpdir.mkdir('clone') - # Create an existing cache of the zipfile - existing_zip = clone_to_dir.join('fake-repo-tmpl.zip') - existing_zip.write('This is an existing zipfile') + existing_zip = clone_dir.joinpath('fake-repo-tmpl.zip') + existing_zip.write_text('This is an existing zipfile') zipfile_url = 'https://example.com/path/to/fake-repo-tmpl.zip' with pytest.raises(SystemExit): - zipfile.unzip(zipfile_url, is_url=True, clone_to_dir=str(clone_to_dir)) + zipfile.unzip(zipfile_url, is_url=True, clone_to_dir=str(clone_dir)) assert not mock_requests_get.called