From 40fc496c6a9883559b6fd2c1d347252c3ff0ef6e Mon Sep 17 00:00:00 2001 From: Etty Date: Mon, 19 Oct 2020 22:49:59 +0100 Subject: [PATCH 1/4] add: fix revert for dry-run and interrupts This change correctly reverts pyproject.toml changes for dry runs as well as keyboard interrupts. Resolves: #2933 #318 --- poetry/console/commands/add.py | 33 +++++++++++++++--------------- tests/console/commands/test_add.py | 23 +++++++++++++++++++++ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/poetry/console/commands/add.py b/poetry/console/commands/add.py index 3ad77ad686b..29cf07d2a26 100644 --- a/poetry/console/commands/add.py +++ b/poetry/console/commands/add.py @@ -100,7 +100,6 @@ def handle(self): packages = [name for name in packages if name not in existing_packages] if not packages: - self.poetry.file.write(content) self.line("Nothing to add.") return 0 @@ -152,29 +151,29 @@ def handle(self): poetry_content[section][_constraint["name"]] = constraint - # Write new content - self.poetry.file.write(content) + try: + # Write new content + self.poetry.file.write(content) - # Cosmetic new line - self.line("") + # Cosmetic new line + self.line("") - # Update packages - self.reset_poetry() + # Update packages + self.reset_poetry() - self._installer.set_package(self.poetry.package) - self._installer.dry_run(self.option("dry-run")) - self._installer.verbose(self._io.is_verbose()) - self._installer.update(True) - if self.option("lock"): - self._installer.lock() + self._installer.set_package(self.poetry.package) + self._installer.dry_run(self.option("dry-run")) + self._installer.verbose(self._io.is_verbose()) + self._installer.update(True) + if self.option("lock"): + self._installer.lock() - self._installer.whitelist([r["name"] for r in requirements]) + self._installer.whitelist([r["name"] for r in requirements]) - try: status = self._installer.run() - except Exception: + except BaseException: + # Using BaseException here as some exceptions, eg: KeyboardInterrupt, do not inherit from Exception self.poetry.file.write(original_content) - raise if status != 0 or self.option("dry-run"): diff --git a/tests/console/commands/test_add.py b/tests/console/commands/test_add.py index 09fae525aec..19998592ac3 100644 --- a/tests/console/commands/test_add.py +++ b/tests/console/commands/test_add.py @@ -1630,3 +1630,26 @@ def test_add_with_lock_old_installer(app, repo, installer, old_tester): """ assert expected == old_tester.io.fetch_output() + + +def test_add_keyboard_interrupt_restore_content(app, repo, installer, tester, mocker): + mocker.patch( + "poetry.installation.installer.Installer.run", side_effect=KeyboardInterrupt() + ) + original_content = app.poetry.file.read() + + repo.add_package(get_package("cachy", "0.2.0")) + + tester.execute("cachy --dry-run") + + assert original_content == app.poetry.file.read() + + +def test_dry_run_restore_original_content(app, repo, installer, tester): + original_content = app.poetry.file.read() + + repo.add_package(get_package("cachy", "0.2.0")) + + tester.execute("cachy --dry-run") + + assert original_content == app.poetry.file.read() From 3f726daccfcf789abcaf6da300767836d9fb86f8 Mon Sep 17 00:00:00 2001 From: Etty Date: Mon, 19 Oct 2020 22:57:47 +0100 Subject: [PATCH 2/4] export: use --trusted-host for non HTTPS index Resolves: #1894 --- poetry/utils/exporter.py | 4 ++++ tests/utils/test_exporter.py | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/poetry/utils/exporter.py b/poetry/utils/exporter.py index 5f2d6303817..f7c40f6975f 100644 --- a/poetry/utils/exporter.py +++ b/poetry/utils/exporter.py @@ -7,6 +7,7 @@ from poetry.poetry import Poetry from poetry.utils._compat import Path from poetry.utils._compat import decode +from poetry.utils._compat import urlparse class Exporter(object): @@ -139,6 +140,9 @@ def _export_requirements_txt( url = ( repository.authenticated_url if with_credentials else repository.url ) + parsed_url = urlparse.urlsplit(url) + if parsed_url.scheme == "http": + indexes_header += "--trusted-host {}\n".format(parsed_url.netloc) indexes_header += "--extra-index-url {}\n".format(url) content = indexes_header + "\n" + content diff --git a/tests/utils/test_exporter.py b/tests/utils/test_exporter.py index 3074f5459a9..1e660ce69cd 100644 --- a/tests/utils/test_exporter.py +++ b/tests/utils/test_exporter.py @@ -1028,6 +1028,52 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, poetry) assert expected == content +def test_exporter_exports_requirements_txt_with_legacy_packages_trusted_host( + tmp_dir, poetry +): + poetry.pool.add_repository(LegacyRepository("custom", "http://example.com/simple",)) + poetry.locker.mock_lock_data( + { + "package": [ + { + "name": "bar", + "version": "4.5.6", + "category": "dev", + "optional": False, + "python-versions": "*", + "source": { + "type": "legacy", + "url": "http://example.com/simple", + "reference": "", + }, + }, + ], + "metadata": { + "python-versions": "*", + "content-hash": "123456789", + "hashes": {"bar": ["67890"]}, + }, + } + ) + set_package_requires(poetry) + exporter = Exporter(poetry) + + exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True) + + with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: + content = f.read() + + expected = """\ +--trusted-host example.com +--extra-index-url http://example.com/simple + +bar==4.5.6 \\ + --hash=sha256:67890 +""" + + assert expected == content + + @pytest.mark.parametrize( ("dev", "expected"), [ From ae1c9e094b25258e592a112c8a7b69aa6edeccb0 Mon Sep 17 00:00:00 2001 From: John Peter Yamauchi Date: Tue, 5 Jan 2021 17:55:26 -0600 Subject: [PATCH 3/4] legacy repository: support redirected url --- poetry/repositories/legacy_repository.py | 13 +++++++++++-- tests/repositories/test_legacy_repository.py | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/poetry/repositories/legacy_repository.py b/poetry/repositories/legacy_repository.py index 7442d65a561..75d0a83ff75 100755 --- a/poetry/repositories/legacy_repository.py +++ b/poetry/repositories/legacy_repository.py @@ -394,8 +394,17 @@ def _get(self, endpoint): # type: (str) -> Union[Page, None] if response.status_code in (401, 403): self._log( - "Authorization error accessing {url}".format(url=url), level="warn" + "Authorization error accessing {url}".format(url=response.url), + level="warn", ) return - return Page(url, response.content, response.headers) + if response.url != url: + self._log( + "Response URL {response_url} differs from request URL {url}".format( + response_url=response.url, url=url + ), + level="debug", + ) + + return Page(response.url, response.content, response.headers) diff --git a/tests/repositories/test_legacy_repository.py b/tests/repositories/test_legacy_repository.py index 47ccc1052f9..5b29735aecb 100644 --- a/tests/repositories/test_legacy_repository.py +++ b/tests/repositories/test_legacy_repository.py @@ -1,6 +1,7 @@ import shutil import pytest +import requests from poetry.core.packages import Dependency from poetry.factory import Factory @@ -332,3 +333,17 @@ def test_get_4xx_and_5xx_raises(http): for endpoint in endpoints: with pytest.raises(RepositoryError): repo._get(endpoint) + + +def test_get_redirected_response_url(http, monkeypatch): + repo = MockHttpRepository({"/foo": 200}, http) + redirect_url = "http://legacy.redirect.bar" + + def get_mock(url): + response = requests.Response() + response.status_code = 200 + response.url = redirect_url + "/foo" + return response + + monkeypatch.setattr(repo.session, "get", get_mock) + assert repo._get("/foo")._url == "http://legacy.redirect.bar/foo/" From 0e60f55714d69339c49cfb2fa19d7d88fdca0db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Eustace?= Date: Sat, 30 Jan 2021 20:03:15 +0100 Subject: [PATCH 4/4] Fix legacy repository redirection test --- tests/repositories/test_legacy_repository.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/repositories/test_legacy_repository.py b/tests/repositories/test_legacy_repository.py index 5b29735aecb..55aa67c30ce 100644 --- a/tests/repositories/test_legacy_repository.py +++ b/tests/repositories/test_legacy_repository.py @@ -335,7 +335,7 @@ def test_get_4xx_and_5xx_raises(http): repo._get(endpoint) -def test_get_redirected_response_url(http, monkeypatch): +def test_get_redirected_response_url(http, mocker): repo = MockHttpRepository({"/foo": 200}, http) redirect_url = "http://legacy.redirect.bar" @@ -345,5 +345,5 @@ def get_mock(url): response.url = redirect_url + "/foo" return response - monkeypatch.setattr(repo.session, "get", get_mock) + mocker.patch.object(requests.Session, "get", side_effect=get_mock) assert repo._get("/foo")._url == "http://legacy.redirect.bar/foo/"