Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,7 @@ module = [
'poetry.mixology.term',
'poetry.mixology.version_solver',
'poetry.repositories.installed_repository',
'poetry.utils.appdirs',
'poetry.utils.authenticator',
'poetry.utils.env',
'poetry.utils.exporter',
'poetry.utils.setup_reader',
]
ignore_errors = true

Expand Down
13 changes: 4 additions & 9 deletions src/poetry/utils/appdirs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,11 @@
import os
import sys

from typing import TYPE_CHECKING


if TYPE_CHECKING:
from pathlib import Path


WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt")


def expanduser(path: str | Path) -> str:
def expanduser(path: str) -> str:
"""
Expand ~ and ~user constructions.

Expand Down Expand Up @@ -214,14 +208,15 @@ def _get_win_folder_with_ctypes(csidl_name: str) -> str:
}[csidl_name]

buf = ctypes.create_unicode_buffer(1024)
ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
windll = ctypes.windll # type: ignore[attr-defined]
windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)

# Downgrade to short path name if have highbit chars. See
# <http://bugs.activestate.com/show_bug.cgi?id=85099>.
has_high_char = any(ord(c) > 255 for c in buf)
if has_high_char:
buf2 = ctypes.create_unicode_buffer(1024)
if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
if windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
buf = buf2

return buf.value
Expand Down
43 changes: 25 additions & 18 deletions src/poetry/utils/authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ class Authenticator:
def __init__(self, config: Config, io: IO | None = None) -> None:
self._config = config
self._io = io
self._session = None
self._credentials = {}
self._certs = {}
self._session: requests.Session | None = None
self._credentials: dict[str, tuple[str, str]] = {}
self._certs: dict[str, dict[str, Path | None]] = {}
self._password_manager = PasswordManager(self._config)

def _log(self, message: str, level: str = "debug") -> None:
Expand Down Expand Up @@ -118,7 +118,9 @@ def get_credentials_for_url(self, url: str) -> tuple[str | None, str | None]:

netloc = parsed_url.netloc

credentials = self._credentials.get(netloc, (None, None))
credentials: tuple[str | None, str | None] = self._credentials.get(
netloc, (None, None)
)

if credentials == (None, None):
if "@" not in netloc:
Expand All @@ -131,25 +133,27 @@ def get_credentials_for_url(self, url: str) -> tuple[str | None, str | None]:
# Split from the left because that's how urllib.parse.urlsplit()
# behaves if more than one : is present (which again can be checked
# using the password attribute of the return value)
credentials = auth.split(":", 1) if ":" in auth else (auth, None)
credentials = tuple(
None if x is None else urllib.parse.unquote(x) for x in credentials
user, password = auth.split(":", 1) if ":" in auth else (auth, "")
credentials = (
urllib.parse.unquote(user),
urllib.parse.unquote(password),
)

if credentials[0] is not None or credentials[1] is not None:
if any(credential is not None for credential in credentials):
credentials = (credentials[0] or "", credentials[1] or "")

self._credentials[netloc] = credentials

return credentials[0], credentials[1]
return credentials

def get_pypi_token(self, name: str) -> str:
def get_pypi_token(self, name: str) -> str | None:
return self._password_manager.get_pypi_token(name)

def get_http_auth(self, name: str) -> dict[str, str] | None:
def get_http_auth(self, name: str) -> dict[str, str | None] | None:
return self._get_http_auth(name, None)

def _get_http_auth(self, name: str, netloc: str | None) -> dict[str, str] | None:
def _get_http_auth(
self, name: str, netloc: str | None
) -> dict[str, str | None] | None:
if name == "pypi":
url = "https://upload.pypi.org/legacy/"
else:
Expand All @@ -161,23 +165,26 @@ def _get_http_auth(self, name: str, netloc: str | None) -> dict[str, str] | None

if netloc is None or netloc == parsed_url.netloc:
auth = self._password_manager.get_http_auth(name)
auth = auth or {}

if auth is None or auth["password"] is None:
username = auth["username"] if auth else None
if auth.get("password") is None:
username = auth.get("username")
auth = self._get_credentials_for_netloc_from_keyring(
url, parsed_url.netloc, username
)

return auth

return None

def _get_credentials_for_netloc(self, netloc: str) -> tuple[str | None, str | None]:
for repository_name, _ in self._get_repository_netlocs():
auth = self._get_http_auth(repository_name, netloc)

if auth is None:
continue

return auth["username"], auth["password"]
return auth.get("username"), auth.get("password")

return None, None

Expand All @@ -199,7 +206,7 @@ def _get_repository_netlocs(self) -> Iterator[tuple[str, str]]:

def _get_credentials_for_netloc_from_keyring(
self, url: str, netloc: str, username: str | None
) -> dict[str, str] | None:
) -> dict[str, str | None] | None:
import keyring

cred = keyring.get_credential(url, username)
Expand All @@ -225,7 +232,7 @@ def _get_credentials_for_netloc_from_keyring(
return None

def _get_certs_for_netloc_from_config(self, netloc: str) -> dict[str, Path | None]:
certs = {"cert": None, "verify": None}
certs: dict[str, Path | None] = {"cert": None, "verify": None}

for repository_name, repository_netloc in self._get_repository_netlocs():
if netloc == repository_netloc:
Expand Down
10 changes: 7 additions & 3 deletions src/poetry/utils/password_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def delete_pypi_token(self, name: str) -> None:

self.keyring.delete_password(name, "__token__")

def get_http_auth(self, name: str) -> dict[str, str] | None:
def get_http_auth(self, name: str) -> dict[str, str | None] | None:
auth = self._config.get(f"http-basic.{name}")
if not auth:
username = self._config.get(f"http-basic.{name}.username")
Expand Down Expand Up @@ -181,10 +181,14 @@ def set_http_password(self, name: str, username: str, password: str) -> None:

def delete_http_password(self, name: str) -> None:
auth = self.get_http_auth(name)
if not auth or "username" not in auth:
if not auth:
return

username = auth.get("username")
if username is None:
return

with suppress(KeyRingError):
self.keyring.delete_password(name, auth["username"])
self.keyring.delete_password(name, username)

self._config.auth_config_source.remove_property(f"http-basic.{name}")
Loading