From 28bf29abda5959956f8ef0be5785a7eb3042efb6 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sat, 25 Jun 2022 15:58:33 +0200 Subject: [PATCH 01/15] add checking for env variable in pypi token getter --- src/poetry/utils/password_manager.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index e003d56b41a..550d882b840 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -2,6 +2,7 @@ import dataclasses import logging +import os from contextlib import suppress from typing import TYPE_CHECKING @@ -173,6 +174,9 @@ def set_pypi_token(self, name: str, token: str) -> None: self.keyring.set_password(name, "__token__", token) def get_pypi_token(self, name: str) -> str | None: + if os.getenv("POETRY_PYPI_TOKEN_PYPI"): + return os.getenv("POETRY_PYPI_TOKEN_PYPI") + if not self.keyring.is_available(): token: str | None = self._config.get(f"pypi-token.{name}") return token From e68806720b748308658f4dca341e932578ba7022 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sat, 25 Jun 2022 19:42:17 +0200 Subject: [PATCH 02/15] add unit tests for env pypi token --- src/poetry/utils/password_manager.py | 16 ++++++++++++ tests/utils/test_password_manager.py | 37 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index 550d882b840..26ab03d43cc 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -174,6 +174,22 @@ def set_pypi_token(self, name: str, token: str) -> None: self.keyring.set_password(name, "__token__", token) def get_pypi_token(self, name: str) -> str | None: + """Get PYPI token. + + First checks the enviroment variables for a token, + then the configured username/password and last the + available keyring. + + + Parameters + ---------- + name + PYPI username. + + Returns + ------- + Returns a token as a string if found, otherwise None. + """ if os.getenv("POETRY_PYPI_TOKEN_PYPI"): return os.getenv("POETRY_PYPI_TOKEN_PYPI") diff --git a/tests/utils/test_password_manager.py b/tests/utils/test_password_manager.py index 5859069ed0a..aaa0d874cd9 100644 --- a/tests/utils/test_password_manager.py +++ b/tests/utils/test_password_manager.py @@ -3,6 +3,7 @@ import os from typing import TYPE_CHECKING +from unittest import mock import pytest @@ -231,3 +232,39 @@ def test_get_http_auth_from_environment_variables( assert auth["username"] == "bar" assert auth["password"] == "baz" + + +def test_get_pypi_token_with_env_var_positive( + config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend +): + sample_token = "sampletoken-1234" + manager = PasswordManager(config) + + with mock.patch.dict(os.environ, {"POETRY_PYPI_TOKEN_PYPI": sample_token}): + result_token = manager.get_pypi_token("foo") + + assert result_token == sample_token + + +def test_get_pypi_token_with_env_var_negative( + config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend +): + sample_token = "sampletoken-1234" + manager = PasswordManager(config) + + with mock.patch.dict( + os.environ, {"POETRY_PYPI_TOKEN_PYPI": sample_token + "somestuff"} + ): + result_token = manager.get_pypi_token("foo") + + assert result_token != sample_token + + +def test_get_pypi_token_with_env_var_not_available( + config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend +): + manager = PasswordManager(config) + + result_token = manager.get_pypi_token("foo") + + assert result_token is None From d7659bc32732f13549cb5bb21ddd49ff12b6cb0a Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sat, 25 Jun 2022 15:58:33 +0200 Subject: [PATCH 03/15] add checking for env variable in pypi token getter --- src/poetry/utils/password_manager.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index e003d56b41a..550d882b840 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -2,6 +2,7 @@ import dataclasses import logging +import os from contextlib import suppress from typing import TYPE_CHECKING @@ -173,6 +174,9 @@ def set_pypi_token(self, name: str, token: str) -> None: self.keyring.set_password(name, "__token__", token) def get_pypi_token(self, name: str) -> str | None: + if os.getenv("POETRY_PYPI_TOKEN_PYPI"): + return os.getenv("POETRY_PYPI_TOKEN_PYPI") + if not self.keyring.is_available(): token: str | None = self._config.get(f"pypi-token.{name}") return token From 8a6585f3aba2b003e88b972b3147a26a03d20909 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sat, 25 Jun 2022 19:42:17 +0200 Subject: [PATCH 04/15] add unit tests for env pypi token --- src/poetry/utils/password_manager.py | 16 ++++++++++++ tests/utils/test_password_manager.py | 37 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index 550d882b840..26ab03d43cc 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -174,6 +174,22 @@ def set_pypi_token(self, name: str, token: str) -> None: self.keyring.set_password(name, "__token__", token) def get_pypi_token(self, name: str) -> str | None: + """Get PYPI token. + + First checks the enviroment variables for a token, + then the configured username/password and last the + available keyring. + + + Parameters + ---------- + name + PYPI username. + + Returns + ------- + Returns a token as a string if found, otherwise None. + """ if os.getenv("POETRY_PYPI_TOKEN_PYPI"): return os.getenv("POETRY_PYPI_TOKEN_PYPI") diff --git a/tests/utils/test_password_manager.py b/tests/utils/test_password_manager.py index 5859069ed0a..aaa0d874cd9 100644 --- a/tests/utils/test_password_manager.py +++ b/tests/utils/test_password_manager.py @@ -3,6 +3,7 @@ import os from typing import TYPE_CHECKING +from unittest import mock import pytest @@ -231,3 +232,39 @@ def test_get_http_auth_from_environment_variables( assert auth["username"] == "bar" assert auth["password"] == "baz" + + +def test_get_pypi_token_with_env_var_positive( + config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend +): + sample_token = "sampletoken-1234" + manager = PasswordManager(config) + + with mock.patch.dict(os.environ, {"POETRY_PYPI_TOKEN_PYPI": sample_token}): + result_token = manager.get_pypi_token("foo") + + assert result_token == sample_token + + +def test_get_pypi_token_with_env_var_negative( + config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend +): + sample_token = "sampletoken-1234" + manager = PasswordManager(config) + + with mock.patch.dict( + os.environ, {"POETRY_PYPI_TOKEN_PYPI": sample_token + "somestuff"} + ): + result_token = manager.get_pypi_token("foo") + + assert result_token != sample_token + + +def test_get_pypi_token_with_env_var_not_available( + config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend +): + manager = PasswordManager(config) + + result_token = manager.get_pypi_token("foo") + + assert result_token is None From be2d1291a0ee2bd667a754ca1bee54facf745166 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sat, 25 Jun 2022 19:50:00 +0200 Subject: [PATCH 05/15] add info to the changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86c64ae7a15..d786481cb89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,6 +107,8 @@ - Improved documentation of the `readme` option, including multiple files and additional formats ([#5158](https://github.com/python-poetry/poetry/pull/5158)) - Improved contributing documentation ([#5708](https://github.com/python-poetry/poetry/pull/5708)) - Remove all references to `--dev-only` option ([#5771](https://github.com/python-poetry/poetry/pull/5771)) +- Added environment variable checking for PyPi token ([#5911](https://github.com/python-poetry/poetry/pull/5911)) + ## [1.2.0b1] - 2022-03-17 From 27e2dcac66d85713709a2c3a8d65d8d2e6b02e80 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sat, 25 Jun 2022 21:27:15 +0200 Subject: [PATCH 06/15] refactor the structure --- src/poetry/utils/password_manager.py | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index 26ab03d43cc..2d02cd5542d 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -2,7 +2,6 @@ import dataclasses import logging -import os from contextlib import suppress from typing import TYPE_CHECKING @@ -173,31 +172,29 @@ def set_pypi_token(self, name: str, token: str) -> None: else: self.keyring.set_password(name, "__token__", token) - def get_pypi_token(self, name: str) -> str | None: - """Get PYPI token. + def get_pypi_token(self, repo_name: str) -> str | None: + """Get PyPi token. - First checks the enviroment variables for a token, - then the configured username/password and last the + First checks the environment variables for a token, + then the configured username/password and the available keyring. Parameters ---------- - name - PYPI username. + repo_name + Name of repository. Returns ------- Returns a token as a string if found, otherwise None. """ - if os.getenv("POETRY_PYPI_TOKEN_PYPI"): - return os.getenv("POETRY_PYPI_TOKEN_PYPI") - - if not self.keyring.is_available(): - token: str | None = self._config.get(f"pypi-token.{name}") - return token - - return self.keyring.get_password(name, "__token__") + token = self._config.get(f"pypi-token.{repo_name}") + return ( + token + if token is not None + else self.keyring.get_password(repo_name, "__token__") + ) def delete_pypi_token(self, name: str) -> None: if not self.keyring.is_available(): From 4eff8fd5bb4aadea38dcc3328087050ce9158b19 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sat, 25 Jun 2022 21:33:44 +0200 Subject: [PATCH 07/15] fix unit tests --- tests/utils/test_password_manager.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/utils/test_password_manager.py b/tests/utils/test_password_manager.py index aaa0d874cd9..bc80ab93894 100644 --- a/tests/utils/test_password_manager.py +++ b/tests/utils/test_password_manager.py @@ -238,10 +238,14 @@ def test_get_pypi_token_with_env_var_positive( config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend ): sample_token = "sampletoken-1234" + repo_name = "foo" manager = PasswordManager(config) - with mock.patch.dict(os.environ, {"POETRY_PYPI_TOKEN_PYPI": sample_token}): - result_token = manager.get_pypi_token("foo") + with mock.patch.dict( + os.environ, + {f"POETRY-PYPI-TOKEN-{repo_name}".upper().replace("-", "_"): sample_token}, + ): + result_token = manager.get_pypi_token(repo_name) assert result_token == sample_token @@ -250,12 +254,17 @@ def test_get_pypi_token_with_env_var_negative( config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend ): sample_token = "sampletoken-1234" + repo_name = "foo" manager = PasswordManager(config) with mock.patch.dict( - os.environ, {"POETRY_PYPI_TOKEN_PYPI": sample_token + "somestuff"} + os.environ, + { + "POETRY-PYPI-TOKEN-{repo_name}".upper().replace("-", "_"): sample_token + + "somestuff" + }, ): - result_token = manager.get_pypi_token("foo") + result_token = manager.get_pypi_token(repo_name) assert result_token != sample_token @@ -263,8 +272,9 @@ def test_get_pypi_token_with_env_var_negative( def test_get_pypi_token_with_env_var_not_available( config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend ): + repo_name = "foo" manager = PasswordManager(config) - result_token = manager.get_pypi_token("foo") + result_token = manager.get_pypi_token(repo_name) assert result_token is None From 362bffe5a048c775defc218c69a7a7311ae1dcc6 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sat, 25 Jun 2022 21:53:21 +0200 Subject: [PATCH 08/15] undo changelog addition --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d786481cb89..86c64ae7a15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,8 +107,6 @@ - Improved documentation of the `readme` option, including multiple files and additional formats ([#5158](https://github.com/python-poetry/poetry/pull/5158)) - Improved contributing documentation ([#5708](https://github.com/python-poetry/poetry/pull/5708)) - Remove all references to `--dev-only` option ([#5771](https://github.com/python-poetry/poetry/pull/5771)) -- Added environment variable checking for PyPi token ([#5911](https://github.com/python-poetry/poetry/pull/5911)) - ## [1.2.0b1] - 2022-03-17 From 0812c00404255e5c3887a330fb52ee3908ba7b05 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sat, 25 Jun 2022 22:29:30 +0200 Subject: [PATCH 09/15] change docstring format to sphinx --- src/poetry/utils/password_manager.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index 2d02cd5542d..d9ef281cd5e 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -179,15 +179,8 @@ def get_pypi_token(self, repo_name: str) -> str | None: then the configured username/password and the available keyring. - - Parameters - ---------- - repo_name - Name of repository. - - Returns - ------- - Returns a token as a string if found, otherwise None. + :param repo_name: Name of repository. + :return: Returns a token as a string if found, otherwise None. """ token = self._config.get(f"pypi-token.{repo_name}") return ( From b7f3110061881c6d4793f4afae3843c0d7ea601f Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Sun, 26 Jun 2022 18:49:19 +0200 Subject: [PATCH 10/15] delete uncrsy unit test --- tests/utils/test_password_manager.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tests/utils/test_password_manager.py b/tests/utils/test_password_manager.py index bc80ab93894..8ac29f22da5 100644 --- a/tests/utils/test_password_manager.py +++ b/tests/utils/test_password_manager.py @@ -250,25 +250,6 @@ def test_get_pypi_token_with_env_var_positive( assert result_token == sample_token -def test_get_pypi_token_with_env_var_negative( - config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend -): - sample_token = "sampletoken-1234" - repo_name = "foo" - manager = PasswordManager(config) - - with mock.patch.dict( - os.environ, - { - "POETRY-PYPI-TOKEN-{repo_name}".upper().replace("-", "_"): sample_token - + "somestuff" - }, - ): - result_token = manager.get_pypi_token(repo_name) - - assert result_token != sample_token - - def test_get_pypi_token_with_env_var_not_available( config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend ): From 7ab8274124aca968e0c2d33aa2a91836bbd150f3 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Mon, 27 Jun 2022 09:55:21 +0200 Subject: [PATCH 11/15] Delete unscry funtion call Co-authored-by: Bjorn Neergaard --- tests/utils/test_password_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/test_password_manager.py b/tests/utils/test_password_manager.py index 8ac29f22da5..3f3a0aab43b 100644 --- a/tests/utils/test_password_manager.py +++ b/tests/utils/test_password_manager.py @@ -243,7 +243,7 @@ def test_get_pypi_token_with_env_var_positive( with mock.patch.dict( os.environ, - {f"POETRY-PYPI-TOKEN-{repo_name}".upper().replace("-", "_"): sample_token}, + {f"POETRY_PYPI_TOKEN_{repo_name.upper()}": sample_token}, ): result_token = manager.get_pypi_token(repo_name) From 5bbcea01ddc3ab1c71f937e5449a91860375df40 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Tue, 2 Aug 2022 22:05:44 +0200 Subject: [PATCH 12/15] Update src/poetry/utils/password_manager.py Co-authored-by: Bartosz Sokorski --- src/poetry/utils/password_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index 537d226e90c..a480352e9de 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -180,7 +180,7 @@ def get_pypi_token(self, repo_name: str) -> str | None: :param repo_name: Name of repository. :return: Returns a token as a string if found, otherwise None. """ - token = self._config.get(f"pypi-token.{repo_name}") + return self._config.get(f"pypi-token.{repo_name}", self.keyring.get_password(repo_name, "__token__")) return ( token if token is not None From abc96d4b8b5f48040e94eafd9c968bef4bf6f708 Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Mon, 15 Aug 2022 18:25:06 +0200 Subject: [PATCH 13/15] fix unit tests --- src/poetry/utils/password_manager.py | 7 ++----- tests/utils/test_password_manager.py | 14 +++++++------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index a480352e9de..36d56754fa9 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -180,11 +180,8 @@ def get_pypi_token(self, repo_name: str) -> str | None: :param repo_name: Name of repository. :return: Returns a token as a string if found, otherwise None. """ - return self._config.get(f"pypi-token.{repo_name}", self.keyring.get_password(repo_name, "__token__")) - return ( - token - if token is not None - else self.keyring.get_password(repo_name, "__token__") + return self._config.get( + f"pypi-token.{repo_name}", self.keyring.get_password(repo_name, "__token__") ) def delete_pypi_token(self, name: str) -> None: diff --git a/tests/utils/test_password_manager.py b/tests/utils/test_password_manager.py index 3f3a0aab43b..468ef14f689 100644 --- a/tests/utils/test_password_manager.py +++ b/tests/utils/test_password_manager.py @@ -3,7 +3,6 @@ import os from typing import TYPE_CHECKING -from unittest import mock import pytest @@ -235,19 +234,20 @@ def test_get_http_auth_from_environment_variables( def test_get_pypi_token_with_env_var_positive( - config: Config, with_simple_keyring: None, dummy_keyring: DummyBackend + mocker: MockerFixture, + config: Config, + with_simple_keyring: None, + dummy_keyring: DummyBackend, ): sample_token = "sampletoken-1234" repo_name = "foo" manager = PasswordManager(config) - - with mock.patch.dict( + mocker.patch.dict( os.environ, {f"POETRY_PYPI_TOKEN_{repo_name.upper()}": sample_token}, - ): - result_token = manager.get_pypi_token(repo_name) + ) - assert result_token == sample_token + assert manager.get_pypi_token(repo_name) == sample_token def test_get_pypi_token_with_env_var_not_available( From d6d38bd2bbb632b24fe35f5bd257935f1a2ef59b Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Mon, 15 Aug 2022 19:18:25 +0200 Subject: [PATCH 14/15] lol --- src/poetry/utils/password_manager.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index 36d56754fa9..299f33e0a9b 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -180,9 +180,11 @@ def get_pypi_token(self, repo_name: str) -> str | None: :param repo_name: Name of repository. :return: Returns a token as a string if found, otherwise None. """ - return self._config.get( - f"pypi-token.{repo_name}", self.keyring.get_password(repo_name, "__token__") - ) + token = self._config.get(f"pypi-token.{repo_name}") + if token: + return token + + return self.keyring.get_password(repo_name, "__token__") def delete_pypi_token(self, name: str) -> None: if not self.keyring.is_available(): From 90af09a7edb6f6928a4bffd97905103d33b7632f Mon Sep 17 00:00:00 2001 From: Jan Bronicki Date: Wed, 17 Aug 2022 23:50:18 +0200 Subject: [PATCH 15/15] fix type hints --- src/poetry/utils/password_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/poetry/utils/password_manager.py b/src/poetry/utils/password_manager.py index 299f33e0a9b..e687711b5db 100644 --- a/src/poetry/utils/password_manager.py +++ b/src/poetry/utils/password_manager.py @@ -180,7 +180,7 @@ def get_pypi_token(self, repo_name: str) -> str | None: :param repo_name: Name of repository. :return: Returns a token as a string if found, otherwise None. """ - token = self._config.get(f"pypi-token.{repo_name}") + token: str | None = self._config.get(f"pypi-token.{repo_name}") if token: return token