diff --git a/mypy.ini b/mypy.ini index fd6e3c61bb4..3a0a1634419 100644 --- a/mypy.ini +++ b/mypy.ini @@ -13,7 +13,7 @@ warn_unused_configs = True # should be added to this whitelist. # see https://github.com/python-poetry/poetry/pull/4510. -[mypy-poetry.config.*] +[mypy-poetry.config.file_config_source] ignore_errors = True [mypy-poetry.console.*] @@ -34,16 +34,13 @@ ignore_errors = True [mypy-poetry.mixology.*] ignore_errors = True -[mypy-poetry.packages.*] -ignore_errors = True - -[mypy-poetry.publishing.*] +[mypy-poetry.packages.locker] ignore_errors = True [mypy-poetry.puzzle.*] ignore_errors = True -[mypy-poetry.repositories.*] +[mypy-poetry.repositories.installed_repository] ignore_errors = True [mypy-poetry.utils.*] diff --git a/poetry/config/config.py b/poetry/config/config.py index b1b3b3e61bb..82eb95b3282 100644 --- a/poetry/config/config.py +++ b/poetry/config/config.py @@ -14,9 +14,6 @@ from .dict_config_source import DictConfigSource -_NOT_SET = object() - - def boolean_validator(val: str) -> bool: return val in {"true", "false", "1", "0"} @@ -27,7 +24,7 @@ def boolean_normalizer(val: str) -> bool: class Config: - default_config = { + default_config: Dict[str, Any] = { "cache-dir": str(CACHE_DIR), "virtualenvs": { "create": True, @@ -45,12 +42,8 @@ def __init__( self._config = deepcopy(self.default_config) self._use_environment = use_environment self._base_dir = base_dir - self._config_source = DictConfigSource() - self._auth_config_source = DictConfigSource() - - @property - def name(self) -> str: - return str(self._file.path) + self._config_source: ConfigSource = DictConfigSource() + self._auth_config_source: ConfigSource = DictConfigSource() @property def config(self) -> Dict: @@ -114,9 +107,9 @@ def get(self, setting_name: str, default: Any = None) -> Any: env = "POETRY_{}".format( "_".join(k.upper().replace("-", "_") for k in keys) ) - value = os.getenv(env, _NOT_SET) - if value is not _NOT_SET: - return self.process(self._get_normalizer(setting_name)(value)) + env_value = os.getenv(env) + if env_value is not None: + return self.process(self._get_normalizer(setting_name)(env_value)) value = self._config for key in keys: diff --git a/poetry/config/dict_config_source.py b/poetry/config/dict_config_source.py index 941e39e6be6..6a5258d80bc 100644 --- a/poetry/config/dict_config_source.py +++ b/poetry/config/dict_config_source.py @@ -6,7 +6,7 @@ class DictConfigSource(ConfigSource): def __init__(self) -> None: - self._config = {} + self._config: Dict[str, Any] = {} @property def config(self) -> Dict[str, Any]: diff --git a/poetry/inspection/info.py b/poetry/inspection/info.py index 22dc0fa2651..3766b8474e6 100644 --- a/poetry/inspection/info.py +++ b/poetry/inspection/info.py @@ -59,7 +59,7 @@ def __init__( platform: Optional[str] = None, requires_dist: Optional[List[str]] = None, requires_python: Optional[str] = None, - files: Optional[List[str]] = None, + files: Optional[List[Dict[str, str]]] = None, cache_version: Optional[str] = None, ): self.name = name diff --git a/poetry/packages/project_package.py b/poetry/packages/project_package.py index 635ec37c78a..81e727ca8f4 100644 --- a/poetry/packages/project_package.py +++ b/poetry/packages/project_package.py @@ -21,5 +21,3 @@ def set_version( else: self._version = version self._pretty_version = pretty_version or version.text - - return self diff --git a/poetry/publishing/publisher.py b/poetry/publishing/publisher.py index ca1c08a73de..31d8972d6d9 100644 --- a/poetry/publishing/publisher.py +++ b/poetry/publishing/publisher.py @@ -44,7 +44,7 @@ def publish( password: Optional[str], cert: Optional[Path] = None, client_cert: Optional[Path] = None, - dry_run: Optional[bool] = False, + dry_run: bool = False, ) -> None: if not repository_name: url = "https://upload.pypi.org/legacy/" diff --git a/poetry/publishing/uploader.py b/poetry/publishing/uploader.py index 2e5f0faf246..8de42e9cebb 100644 --- a/poetry/publishing/uploader.py +++ b/poetry/publishing/uploader.py @@ -57,8 +57,8 @@ def __init__(self, poetry: "Poetry", io: "NullIO") -> None: self._poetry = poetry self._package = poetry.package self._io = io - self._username = None - self._password = None + self._username: Optional[str] = None + self._password: Optional[str] = None @property def user_agent(self) -> str: @@ -89,14 +89,15 @@ def files(self) -> List[Path]: return sorted(wheels + tars) - def auth(self, username: str, password: str) -> None: + def auth(self, username: Optional[str], password: Optional[str]) -> None: self._username = username self._password = password def make_session(self) -> requests.Session: session = requests.session() - if self.is_authenticated(): - session.auth = (self._username, self._password) + auth = self.get_auth() + if auth is not None: + session.auth = auth session.headers["User-Agent"] = self.user_agent for scheme in ("http://", "https://"): @@ -104,8 +105,11 @@ def make_session(self) -> requests.Session: return session - def is_authenticated(self) -> bool: - return self._username is not None and self._password is not None + def get_auth(self) -> Optional[Tuple[str, str]]: + if self._username is None or self._password is None: + return None + + return (self._username, self._password) def upload( self, @@ -147,16 +151,15 @@ def post_data(self, file: Path) -> Dict[str, Any]: md5_digest = md5_hash.hexdigest() sha2_digest = sha256_hash.hexdigest() + blake2_256_digest: Optional[str] = None if _has_blake2: blake2_256_digest = blake2_256_hash.hexdigest() - else: - blake2_256_digest = None + py_version: Optional[str] = None if file_type == "bdist_wheel": wheel_info = wheel_file_re.match(file.name) - py_version = wheel_info.group("pyver") - else: - py_version = None + if wheel_info is not None: + py_version = wheel_info.group("pyver") data = { # identify release @@ -231,7 +234,7 @@ def _upload_file( } ) - data_to_send = self._prepare_data(data) + data_to_send: List[Tuple[str, Any]] = self._prepare_data(data) with file.open("rb") as fp: data_to_send.append( @@ -256,7 +259,7 @@ def _upload_file( allow_redirects=False, headers={"Content-Type": monitor.content_type}, ) - if dry_run or 200 <= resp.status_code < 300: + if resp is None or 200 <= resp.status_code < 300: bar.set_format( f" - Uploading {file.name} %percent%%" ) diff --git a/poetry/repositories/base_repository.py b/poetry/repositories/base_repository.py index 3d5e5c5ebcd..c93c9624a53 100644 --- a/poetry/repositories/base_repository.py +++ b/poetry/repositories/base_repository.py @@ -10,22 +10,22 @@ class BaseRepository: def __init__(self) -> None: - self._packages = [] + self._packages: List[Package] = [] @property def packages(self) -> List["Package"]: return self._packages - def has_package(self, package: "Package") -> None: + def has_package(self, package: "Package") -> bool: raise NotImplementedError() def package( self, name: str, version: str, extras: Optional[List[str]] = None - ) -> None: + ) -> "Package": raise NotImplementedError() - def find_packages(self, dependency: "Dependency") -> None: + def find_packages(self, dependency: "Dependency") -> List["Package"]: raise NotImplementedError() - def search(self, query: str) -> None: + def search(self, query: str) -> List["Package"]: raise NotImplementedError() diff --git a/poetry/repositories/legacy_repository.py b/poetry/repositories/legacy_repository.py index 2f411f00cd9..c3766017a11 100644 --- a/poetry/repositories/legacy_repository.py +++ b/poetry/repositories/legacy_repository.py @@ -5,6 +5,7 @@ import warnings from collections import defaultdict +from html import unescape from pathlib import Path from typing import TYPE_CHECKING from typing import Any @@ -12,6 +13,7 @@ from typing import Iterator from typing import List from typing import Optional +from urllib.parse import quote import requests import requests.auth @@ -43,23 +45,6 @@ if TYPE_CHECKING: from poetry.core.packages.dependency import Dependency -try: - from html import unescape -except ImportError: - try: - from html.parser import HTMLParser - except ImportError: - from HTMLParser import HTMLParser - - unescape = HTMLParser().unescape - - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - - with warnings.catch_warnings(): warnings.simplefilter("ignore") import html5lib @@ -164,6 +149,8 @@ def clean_link(self, url: str) -> str: return self._clean_re.sub(lambda match: "%%%2x" % ord(match.group(0)), url) +# TODO: revisit whether the LegacyRepository should inherit from PyPiRepository. +# . class LegacyRepository(PyPiRepository): def __init__( self, @@ -269,7 +256,7 @@ def find_packages(self, dependency: "Dependency") -> List[Package]: if self._cache.store("matches").has(key): versions = self._cache.store("matches").get(key) else: - page = self._get("/{}/".format(dependency.name.replace(".", "-"))) + page = self._get_page("/{}/".format(dependency.name.replace(".", "-"))) if page is None: return [] @@ -338,14 +325,14 @@ def package( return package def find_links_for_package(self, package: Package) -> List[Link]: - page = self._get("/{}/".format(package.name.replace(".", "-"))) + page = self._get_page("/{}/".format(package.name.replace(".", "-"))) if page is None: return [] return list(page.links_for_version(package.version)) def _get_release_info(self, name: str, version: str) -> dict: - page = self._get("/{}/".format(canonicalize_name(name).replace(".", "-"))) + page = self._get_page("/{}/".format(canonicalize_name(name).replace(".", "-"))) if page is None: raise PackageNotFound(f'No package named "{name}"') @@ -419,7 +406,7 @@ def _get_release_info(self, name: str, version: str) -> dict: return data.asdict() - def _get(self, endpoint: str) -> Optional[Page]: + def _get_page(self, endpoint: str) -> Optional[Page]: url = self._url + endpoint try: response = self.session.get(url) diff --git a/poetry/repositories/pool.py b/poetry/repositories/pool.py index 6658530b1bb..866e8c8a656 100644 --- a/poetry/repositories/pool.py +++ b/poetry/repositories/pool.py @@ -22,11 +22,11 @@ def __init__( if repositories is None: repositories = [] - self._lookup: Dict[str, int] = {} + self._lookup: Dict[Optional[str], int] = {} self._repositories: List[Repository] = [] self._default = False self._has_primary_repositories = False - self._secondary_start_idx = None + self._secondary_start_idx: Optional[int] = None for repository in repositories: self.add_repository(repository) @@ -65,6 +65,8 @@ def add_repository( """ Adds a repository to the pool. """ + # FIXME: surely it's a problem that the repository name can be None here? + # All nameless repositories will collide in self._lookup. repository_name = ( repository.name.lower() if repository.name is not None else None ) diff --git a/poetry/repositories/repository.py b/poetry/repositories/repository.py index c1a939b203b..874dcbbd62b 100644 --- a/poetry/repositories/repository.py +++ b/poetry/repositories/repository.py @@ -24,7 +24,7 @@ def __init__(self, packages: List["Package"] = None, name: str = None) -> None: self.add_package(package) @property - def name(self) -> str: + def name(self) -> Optional[str]: return self._name def package( diff --git a/tests/repositories/test_legacy_repository.py b/tests/repositories/test_legacy_repository.py index a1db15952e1..fd29ecd8811 100644 --- a/tests/repositories/test_legacy_repository.py +++ b/tests/repositories/test_legacy_repository.py @@ -28,7 +28,7 @@ def __init__(self): "legacy", url="http://legacy.foo.bar", disable_cache=True ) - def _get(self, endpoint): + def _get_page(self, endpoint): parts = endpoint.split("/") name = parts[1] @@ -49,7 +49,7 @@ def _download(self, url, dest): def test_page_relative_links_path_are_correct(): repo = MockRepository() - page = repo._get("/relative") + page = repo._get_page("/relative") for link in page.links: assert link.netloc == "legacy.foo.bar" @@ -59,7 +59,7 @@ def test_page_relative_links_path_are_correct(): def test_page_absolute_links_path_are_correct(): repo = MockRepository() - page = repo._get("/absolute") + page = repo._get_page("/absolute") for link in page.links: assert link.netloc == "files.pythonhosted.org" @@ -68,7 +68,7 @@ def test_page_absolute_links_path_are_correct(): def test_sdist_format_support(): repo = MockRepository() - page = repo._get("/relative") + page = repo._get_page("/relative") bz2_links = list(filter(lambda link: link.ext == ".tar.bz2", page.links)) assert len(bz2_links) == 1 assert bz2_links[0].filename == "poetry-0.1.1.tar.bz2" @@ -335,21 +335,21 @@ def __init__(self, endpoint_responses, http): def test_get_200_returns_page(http): repo = MockHttpRepository({"/foo": 200}, http) - assert repo._get("/foo") + assert repo._get_page("/foo") @pytest.mark.parametrize("status_code", [401, 403, 404]) def test_get_40x_and_returns_none(http, status_code): repo = MockHttpRepository({"/foo": status_code}, http) - assert repo._get("/foo") is None + assert repo._get_page("/foo") is None def test_get_5xx_raises(http): repo = MockHttpRepository({"/foo": 500}, http) with pytest.raises(RepositoryError): - repo._get("/foo") + repo._get_page("/foo") def test_get_redirected_response_url(http, monkeypatch): @@ -363,4 +363,4 @@ def get_mock(url): return response monkeypatch.setattr(repo.session, "get", get_mock) - assert repo._get("/foo")._url == "http://legacy.redirect.bar/foo/" + assert repo._get_page("/foo")._url == "http://legacy.redirect.bar/foo/"