def test_executor_should_write_pep610_url_references_for_git( tmp_venv, pool, config, io, mock_file_downloads): package = Package( "demo", "0.1.2", source_type="git", source_reference="master", source_resolved_reference="123456", source_url="https://github.com/demo/demo.git", ) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) verify_installed_distribution( tmp_venv, package, { "vcs_info": { "vcs": "git", "requested_revision": "master", "commit_id": "123456", }, "url": package.source_url, }, )
def test_executor_should_write_pep610_url_references_for_editable_directories( tmp_venv, pool, config, io): url = Path(__file__).parent.parent.joinpath( "fixtures/simple_project").resolve() package = Package( "simple-project", "1.2.3", source_type="directory", source_url=url.as_posix(), develop=True, ) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) dist_info = tmp_venv.site_packages.path.joinpath( "simple_project-1.2.3.dist-info") assert dist_info.exists() direct_url_file = dist_info.joinpath("direct_url.json") assert direct_url_file.exists() url_reference = json.loads(direct_url_file.read_text(encoding="utf-8")) assert url_reference == { "dir_info": { "editable": True }, "url": url.as_uri() }
def test_executor_should_write_pep610_url_references_for_urls( tmp_venv, pool, config, io, mock_file_downloads): package = Package( "demo", "0.1.0", source_type="url", source_url= "https://files.pythonhosted.org/demo-0.1.0-py2.py3-none-any.whl", ) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) dist_info = tmp_venv.site_packages.path.joinpath("demo-0.1.0.dist-info") assert dist_info.exists() direct_url_file = dist_info.joinpath("direct_url.json") assert direct_url_file.exists() url_reference = json.loads(direct_url_file.read_text(encoding="utf-8")) assert url_reference == { "archive_info": {}, "url": "https://files.pythonhosted.org/demo-0.1.0-py2.py3-none-any.whl", }
def test_executor_should_write_pep610_url_references_for_git( tmp_venv, pool, config, io, mock_file_downloads): package = Package( "demo", "0.1.2", source_type="git", source_reference="master", source_resolved_reference="123456", source_url="https://github.com/demo/demo.git", ) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) dist_info = tmp_venv.site_packages.path.joinpath("demo-0.1.2.dist-info") assert dist_info.exists() direct_url_file = dist_info.joinpath("direct_url.json") assert direct_url_file.exists() url_reference = json.loads(direct_url_file.read_text(encoding="utf-8")) assert url_reference == { "vcs_info": { "vcs": "git", "requested_revision": "master", "commit_id": "123456", }, "url": "https://github.com/demo/demo.git", }
def test_executor_should_write_pep610_url_references_for_directories( tmp_venv, pool, config, io ): url = Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve() package = Package( "simple-project", "1.2.3", source_type="directory", source_url=url.as_posix() ) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) verify_installed_distribution( tmp_venv, package, {"dir_info": {}, "url": url.as_uri()} )
def test_executor_should_write_pep610_url_references_for_files( tmp_venv, pool, config, io): url = (Path(__file__).parent.parent.joinpath( "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl").resolve()) package = Package("demo", "0.1.0", source_type="file", source_url=url.as_posix()) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) verify_installed_distribution(tmp_venv, package, { "archive_info": {}, "url": url.as_uri() })
def test_executor_should_write_pep610_url_references_for_urls( tmp_venv, pool, config, io, mock_file_downloads ): package = Package( "demo", "0.1.0", source_type="url", source_url="https://files.pythonhosted.org/demo-0.1.0-py2.py3-none-any.whl", ) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) verify_installed_distribution( tmp_venv, package, {"archive_info": {}, "url": package.source_url} )
def test_execute_should_gracefully_handle_io_error(config: Config, pool: Pool, mocker: MockerFixture, io: BufferedIO, env: MockEnv): executor = Executor(env, pool, config, io) executor.verbose() original_write_line = executor._io.write_line def write_line(string: str, **kwargs: Any) -> None: # Simulate UnicodeEncodeError string.encode("ascii") original_write_line(string, **kwargs) mocker.patch.object(io, "write_line", side_effect=write_line) assert executor.execute([Install(Package("clikit", "0.2.3"))]) == 1 expected = r""" Package operations: 1 install, 0 updates, 0 removals \s*Unicode\w+Error """ assert re.match(expected, io.fetch_output())
def test_execute_works_with_no_ansi_output(mocker, config, pool, io_not_decorated, tmp_dir, mock_file_downloads, env): config = Config() config.merge({"cache-dir": tmp_dir}) executor = Executor(env, pool, config, io_not_decorated) install_output = ( "some string that does not contain a keyb0ard !nterrupt or cance11ed by u$er" ) mocker.patch.object(env, "_run", return_value=install_output) return_code = executor.execute([ Install(Package("pytest", "3.5.2")), ]) env._run.assert_called_once() expected = """ Package operations: 1 install, 0 updates, 0 removals • Installing pytest (3.5.2) """ expected = set(expected.splitlines()) output = set(io_not_decorated.fetch_output().splitlines()) assert expected == output assert 0 == return_code
def test_execute_works_with_ansi_output(mocker, config, pool, io_decorated, tmp_dir, mock_file_downloads, env): config = Config() config.merge({"cache-dir": tmp_dir}) executor = Executor(env, pool, config, io_decorated) install_output = ( "some string that does not contain a keyb0ard !nterrupt or cance11ed by u$er" ) mocker.patch.object(env, "_run", return_value=install_output) return_code = executor.execute([ Install(Package("pytest", "3.5.2")), ]) env._run.assert_called_once() expected = [ "\x1b[39;1mPackage operations\x1b[39;22m: \x1b[34m1\x1b[39m install, \x1b[34m0\x1b[39m updates, \x1b[34m0\x1b[39m removals", "\x1b[34;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[39;1m3.5.2\x1b[39;22m\x1b[39m)\x1b[39m: \x1b[34mPending...\x1b[39m", "\x1b[34;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[39;1m3.5.2\x1b[39;22m\x1b[39m)\x1b[39m: \x1b[34mDownloading...\x1b[39m", "\x1b[34;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[39;1m3.5.2\x1b[39;22m\x1b[39m)\x1b[39m: \x1b[34mInstalling...\x1b[39m", "\x1b[32;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[32m3.5.2\x1b[39m\x1b[39m)\x1b[39m", # finished ] output = io_decorated.fetch_output() # hint: use print(repr(output)) if you need to debug this for line in expected: assert line in output assert 0 == return_code
def test_execute_executes_a_batch_of_operations( config, pool, io, tmp_dir, mock_file_downloads ): config = Config() config.merge({"cache-dir": tmp_dir}) env = MockEnv(path=Path(tmp_dir)) executor = Executor(env, pool, config, io) file_package = Package("demo", "0.1.0") file_package.source_type = "file" file_package.source_url = str( Path(__file__) .parent.parent.joinpath( "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl" ) .resolve() ) directory_package = Package("simple-project", "1.2.3") directory_package.source_type = "directory" directory_package.source_url = str( Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve() ) git_package = Package("demo", "0.1.0") git_package.source_type = "git" git_package.source_reference = "master" git_package.source_url = "https://github.com/demo/demo.git" assert 0 == executor.execute( [ Install(Package("pytest", "3.5.2")), Uninstall(Package("attrs", "17.4.0")), Update(Package("requests", "2.18.3"), Package("requests", "2.18.4")), Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed"), Install(file_package), Install(directory_package), Install(git_package), ] ) expected = """ Package operations: 4 installs, 1 update, 1 removal • Installing pytest (3.5.2) • Removing attrs (17.4.0) • Updating requests (2.18.3 -> 2.18.4) • Installing demo (0.1.0 {}) • Installing simple-project (1.2.3 {}) • Installing demo (0.1.0 master) """.format( file_package.source_url, directory_package.source_url ) expected = set(expected.splitlines()) output = set(io.fetch_output().splitlines()) assert expected == output assert 5 == len(env.executed)
def test_executor_should_write_pep610_url_references_for_editable_directories( tmp_venv: "VirtualEnv", pool: Pool, config: "Config", io: BufferedIO ): url = Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve() package = Package( "simple-project", "1.2.3", source_type="directory", source_url=url.as_posix(), develop=True, ) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) verify_installed_distribution( tmp_venv, package, {"dir_info": {"editable": True}, "url": url.as_uri()} )
def test_executor_should_not_write_pep610_url_references_for_cached_package( package: Package, mocker: MockerFixture, fixture_dir: FixtureDirGetter, tmp_venv: VirtualEnv, pool: Pool, config: Config, io: BufferedIO, ): link_cached = fixture_dir( "distributions") / "demo-0.1.0-py2.py3-none-any.whl" mocker.patch("poetry.installation.executor.Executor._download", return_value=link_cached) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) verify_installed_distribution(tmp_venv, package)
def test_executor_should_write_pep610_url_references_for_files( tmp_venv, pool, config, io): url = (Path(__file__).parent.parent.joinpath( "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl").resolve()) package = Package("demo", "0.1.0", source_type="file", source_url=url.as_posix()) executor = Executor(tmp_venv, pool, config, io) executor.execute([Install(package)]) dist_info = tmp_venv.site_packages.path.joinpath("demo-0.1.0.dist-info") assert dist_info.exists() direct_url_file = dist_info.joinpath("direct_url.json") assert direct_url_file.exists() url_reference = json.loads(direct_url_file.read_text(encoding="utf-8")) assert url_reference == {"archive_info": {}, "url": url.as_uri()}
def test_execute_should_show_operation_as_cancelled_on_subprocess_keyboard_interrupt( config, mocker, io, env): executor = Executor(env, pool, config, io) executor.verbose() # A return code of -2 means KeyboardInterrupt in the pip subprocess mocker.patch.object(executor, "_install", return_value=-2) assert 1 == executor.execute([Install(Package("clikit", "0.2.3"))]) expected = """ Package operations: 1 install, 0 updates, 0 removals • Installing clikit (0.2.3) • Installing clikit (0.2.3): Cancelled """ assert expected == io.fetch_output()
def test_execute_shows_skipped_operations_if_verbose(config, pool, io): config = Config() config.merge({"cache-dir": "/foo"}) env = MockEnv() executor = Executor(env, pool, config, io) executor.verbose() assert 0 == executor.execute([ Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed") ]) expected = """ Package operations: 0 installs, 0 updates, 0 removals, 1 skipped • Removing clikit (0.2.3): Skipped for the following reason: Not currently installed """ assert expected == io.fetch_output() assert 0 == len(env.executed)
def test_execute_should_show_errors(config, mocker, io, env): executor = Executor(env, pool, config, io) executor.verbose() mocker.patch.object(executor, "_install", side_effect=Exception("It failed!")) assert 1 == executor.execute([Install(Package("clikit", "0.2.3"))]) expected = """ Package operations: 1 install, 0 updates, 0 removals • Installing clikit (0.2.3) Exception It failed! """ assert expected in io.fetch_output()
def test_execute_shows_skipped_operations_if_verbose(config: Config, pool: Pool, io: BufferedIO, config_cache_dir: Path, env: MockEnv): config.merge({"cache-dir": config_cache_dir.as_posix()}) executor = Executor(env, pool, config, io) executor.verbose() assert (executor.execute([ Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed") ]) == 0) expected = """ Package operations: 0 installs, 0 updates, 0 removals, 1 skipped • Removing clikit (0.2.3): Skipped for the following reason: Not currently installed """ assert io.fetch_output() == expected assert len(env.executed) == 0
def test_execute_should_gracefully_handle_io_error(config, mocker, io, env): executor = Executor(env, pool, config, io) executor.verbose() original_write_line = executor._io.write_line def write_line(string, flags=None): # Simulate UnicodeEncodeError string.encode("ascii") original_write_line(string, flags) mocker.patch.object(io, "write_line", side_effect=write_line) assert 1 == executor.execute([Install(Package("clikit", "0.2.3"))]) expected = r""" Package operations: 1 install, 0 updates, 0 removals \s*Unicode\w+Error """ assert re.match(expected, io.fetch_output())
def test_execute_executes_a_batch_of_operations(mocker, config, pool, io, tmp_dir, mock_file_downloads, env): pip_editable_install = mocker.patch( "poetry.installation.executor.pip_editable_install", unsafe=not PY36) config = Config() config.merge({"cache-dir": tmp_dir}) executor = Executor(env, pool, config, io) file_package = Package( "demo", "0.1.0", source_type="file", source_url=Path(__file__).parent.parent.joinpath( "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl").resolve( ).as_posix(), ) directory_package = Package( "simple-project", "1.2.3", source_type="directory", source_url=Path(__file__).parent.parent.joinpath( "fixtures/simple_project").resolve().as_posix(), ) git_package = Package( "demo", "0.1.0", source_type="git", source_reference="master", source_url="https://github.com/demo/demo.git", develop=True, ) return_code = executor.execute([ Install(Package("pytest", "3.5.2")), Uninstall(Package("attrs", "17.4.0")), Update(Package("requests", "2.18.3"), Package("requests", "2.18.4")), Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed"), Install(file_package), Install(directory_package), Install(git_package), ]) expected = """ Package operations: 4 installs, 1 update, 1 removal • Installing pytest (3.5.2) • Removing attrs (17.4.0) • Updating requests (2.18.3 -> 2.18.4) • Installing demo (0.1.0 {}) • Installing simple-project (1.2.3 {}) • Installing demo (0.1.0 master) """.format(file_package.source_url, directory_package.source_url) expected = set(expected.splitlines()) output = set(io.fetch_output().splitlines()) assert expected == output assert 5 == len(env.executed) assert 0 == return_code pip_editable_install.assert_called_once()
def test_execute_executes_a_batch_of_operations( mocker: MockerFixture, config: Config, pool: Pool, io: BufferedIO, tmp_dir: str, mock_file_downloads: None, env: MockEnv, ): pip_install = mocker.patch("poetry.installation.executor.pip_install") config.merge({"cache-dir": tmp_dir}) executor = Executor(env, pool, config, io) file_package = Package( "demo", "0.1.0", source_type="file", source_url=Path(__file__).parent.parent.joinpath( "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl").resolve( ).as_posix(), ) directory_package = Package( "simple-project", "1.2.3", source_type="directory", source_url=Path(__file__).parent.parent.joinpath( "fixtures/simple_project").resolve().as_posix(), ) git_package = Package( "demo", "0.1.0", source_type="git", source_reference="master", source_url="https://github.com/demo/demo.git", develop=True, ) return_code = executor.execute([ Install(Package("pytest", "3.5.2")), Uninstall(Package("attrs", "17.4.0")), Update(Package("requests", "2.18.3"), Package("requests", "2.18.4")), Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed"), Install(file_package), Install(directory_package), Install(git_package), ]) expected = f""" Package operations: 4 installs, 1 update, 1 removal • Installing pytest (3.5.2) • Removing attrs (17.4.0) • Updating requests (2.18.3 -> 2.18.4) • Installing demo (0.1.0 {file_package.source_url}) • Installing simple-project (1.2.3 {directory_package.source_url}) • Installing demo (0.1.0 master) """ expected = set(expected.splitlines()) output = set(io.fetch_output().splitlines()) assert output == expected assert len(env.executed) == 1 assert return_code == 0 assert pip_install.call_count == 5 assert pip_install.call_args.kwargs.get("upgrade", False) assert pip_install.call_args.kwargs.get("editable", False)