def test_executor_should_delete_incomplete_downloads(config, io, tmp_dir, mocker, pool, mock_file_downloads): fixture = Path(__file__).parent.parent.joinpath( "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl") destination_fixture = Path(tmp_dir) / "tomlkit-0.5.3-py2.py3-none-any.whl" shutil.copyfile(str(fixture), str(destination_fixture)) mocker.patch( "poetry.installation.executor.Executor._download_archive", side_effect=Exception("Download error"), ) mocker.patch( "poetry.installation.chef.Chef.get_cached_archive_for_link", side_effect=lambda link: link, ) mocker.patch( "poetry.installation.chef.Chef.get_cache_directory_for_link", return_value=Path(tmp_dir), ) config = Config() config.merge({"cache-dir": tmp_dir}) env = MockEnv(path=Path(tmp_dir)) executor = Executor(env, pool, config, io) with pytest.raises(Exception, match="Download error"): executor._download(Install(Package("tomlkit", "0.5.3"))) assert not destination_fixture.exists()
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_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 create_config(cls, io: Optional["IO"] = None) -> Config: if io is None: io = NullIO() config = Config() # Load global config config_file = TOMLFile(Path(CONFIG_DIR) / "config.toml") if config_file.exists(): if io.is_debug(): io.write_line( f"<debug>Loading configuration file {config_file.path}</debug>" ) config.merge(config_file.read()) config.set_config_source(FileConfigSource(config_file)) # Load global auth config auth_config_file = TOMLFile(Path(CONFIG_DIR) / "auth.toml") if auth_config_file.exists(): if io.is_debug(): io.write_line( f"<debug>Loading configuration file {auth_config_file.path}</debug>" ) config.merge(auth_config_file.read()) config.set_auth_config_source(FileConfigSource(auth_config_file)) return config
def test_authenticator_with_implicit_repository_configuration( http: type[httpretty.httpretty], config: Config, repositories: dict[str, dict[str, str]], ) -> None: http.register_uri( http.GET, re.compile("^https?://foo.bar/(.+?)$"), ) config.merge( { "repositories": repositories, "http-basic": { "source": {"username": "******", "password": "******"}, "publish": {"username": "******", "password": "******"}, }, } ) repo = LegacyRepository(name="source", url="https://foo.bar/simple", config=config) repo._get_page("/foo") request = http.last_request() basic_auth = base64.b64encode(b"foo:bar").decode() assert request.headers["Authorization"] == f"Basic {basic_auth}"
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_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_executor_should_be_initialized_with_correct_workers( tmp_venv: VirtualEnv, pool: Pool, config: Config, io: BufferedIO, mocker: MockerFixture, max_workers: int | None, cpu_count: int | None, side_effect: Exception | None, expected_workers: int, ): config.merge({"installer": {"max-workers": max_workers}}) mocker.patch("os.cpu_count", return_value=cpu_count, side_effect=side_effect) executor = Executor(tmp_venv, pool, config, io) assert executor._max_workers == expected_workers
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_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)
def test_config_expands_tilde_for_virtualenvs_path(config: Config, path_config: str, expected: Path): config.merge({"virtualenvs": {"path": path_config}}) assert config.virtualenvs_path == expected